/*
 * Copyright 2013 Google Inc.
 *
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 */
#include "Global.h"

#include "SkWindow.h"
#include "SkEvent.h"


Global* Global::gGlobal = NULL;

// Extracts a C string from a V8 Utf8Value.
static const char* to_cstring(const v8::String::Utf8Value& value) {
    return *value ? *value : "<string conversion failed>";
}

// Slight modification to an original function found in the V8 sample shell.cc.
void Global::reportException(TryCatch* tryCatch) {
    HandleScope handleScope(fIsolate);
    String::Utf8Value exception(tryCatch->Exception());
    const char* exceptionString = to_cstring(exception);
    Handle<Message> message = tryCatch->Message();
    if (message.IsEmpty()) {
        // V8 didn't provide any extra information about this error; just
        // print the exception.
        fprintf(stderr, "%s\n", exceptionString);
    } else {
        // Print (filename):(line number): (message).
        String::Utf8Value filename(message->GetScriptResourceName());
        const char* filenameString = to_cstring(filename);
        int linenum = message->GetLineNumber();
        fprintf(stderr,
                "%s:%i: %s\n", filenameString, linenum, exceptionString);
        // Print line of source code.
        String::Utf8Value sourceline(message->GetSourceLine());
        const char* sourceLineString = to_cstring(sourceline);
        fprintf(stderr, "%s\n", sourceLineString);
        // Print wavy underline.
        int start = message->GetStartColumn();
        for (int i = 0; i < start; i++) {
            fprintf(stderr, " ");
        }
        int end = message->GetEndColumn();
        for (int i = start; i < end; i++) {
            fprintf(stderr, "^");
        }
        fprintf(stderr, "\n");
        String::Utf8Value stackTrace(tryCatch->StackTrace());
        if (stackTrace.length() > 0) {
            const char* stackTraceString = to_cstring(stackTrace);
            fprintf(stderr, "%s\n", stackTraceString);
        }
    }
}

// The callback that implements the JavaScript 'inval' function.
// Invalidates the current window, forcing a redraw.
//
// JS: inval();
void Global::Inval(const v8::FunctionCallbackInfo<Value>& args) {
    gGlobal->getWindow()->inval(NULL);
}

// The callback that is invoked by v8 whenever the JavaScript 'print'
// function is called. Prints its arguments on stdout separated by
// spaces and ending with a newline.
//
// JS: print("foo", "bar");
void Global::Print(const v8::FunctionCallbackInfo<v8::Value>& args) {
    bool first = true;
    HandleScope handleScope(args.GetIsolate());
    for (int i = 0; i < args.Length(); i++) {
        if (first) {
            first = false;
        } else {
            printf(" ");
        }
        v8::String::Utf8Value str(args[i]);
        printf("%s", to_cstring(str));
    }
    printf("\n");
    fflush(stdout);
}

// The callback that is invoked by v8 whenever the JavaScript 'setTimeout'
// function is called.
//
// JS: setTimeout(on_timeout, 500);
//
// TODO(jcgregorio) Currently only handles one timeout, should support any
// number.
void Global::SetTimeout(const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 2) {
        args.GetIsolate()->ThrowException(
                v8::String::NewFromUtf8(
                        args.GetIsolate(), "Error: 2 arguments required."));
        return;
    }

    // Pull out the first arg, make sure it's a function.
    if (!args[0]->IsFunction()) {
        printf("Not a function passed to setTimeout.\n");
        return;
    }
    Handle<Function> timeoutFn = Handle<Function>::Cast(args[0]);
    gGlobal->fTimeout.Reset(args.GetIsolate(), timeoutFn);

    double delay = args[1]->NumberValue();

    // Create an SkEvent and add it with the right delay.
    (new SkEvent())->setTargetProc(Global::TimeOutProc)->postDelay(delay);

    // TODO(jcgregorio) Return the ID as the return value.
}

// Callback function for SkEvents used to implement timeouts.
bool Global::TimeOutProc(const SkEvent& evt) {
    // Create a handle scope to keep the temporary object references.
    HandleScope handleScope(gGlobal->getIsolate());

    // Create a local context from our global context.
    Local<Context> context = gGlobal->getContext();

    // Enter the context so all the remaining operations take place there.
    Context::Scope contextScope(context);

    // Set up an exception handler before calling the Process function.
    TryCatch tryCatch;

    const int argc = 0;
    Local<Function> onTimeout =
            Local<Function>::New(gGlobal->getIsolate(), gGlobal->fTimeout);
    Handle<Value> result = onTimeout->Call(context->Global(), argc, NULL);

    // Handle any exceptions or output.
    if (result.IsEmpty()) {
        SkASSERT(tryCatch.HasCaught());
        // Print errors that happened during execution.
        gGlobal->reportException(&tryCatch);
    } else {
        SkASSERT(!tryCatch.HasCaught());
        if (!result->IsUndefined()) {
            // If all went well and the result wasn't undefined then print the
            // returned value.
            String::Utf8Value str(result);
            const char* cstr = to_cstring(str);
            printf("%s\n", cstr);
        }
    }
    return true;
}

// Creates a new execution environment containing the built-in functions.
Handle<Context> Global::createRootContext() {
  // Create a template for the global object.
  Handle<ObjectTemplate> global = ObjectTemplate::New();

  global->Set(v8::String::NewFromUtf8(fIsolate, "print"),
              v8::FunctionTemplate::New(Global::Print));
  global->Set(v8::String::NewFromUtf8(fIsolate, "setTimeout"),
              v8::FunctionTemplate::New(Global::SetTimeout));
  global->Set(v8::String::NewFromUtf8(fIsolate, "inval"),
              v8::FunctionTemplate::New(Global::Inval));


  return Context::New(fIsolate, NULL, global);
}


// Creates the root context, parses the script into it, then stores the
// context in a global.
//
// TODO(jcgregorio) Currently only handles one script. Need to move
// createRootContext to another call that's only done once.
bool Global::parseScript(const char script[]) {

    // Create a stack-allocated handle scope.
    HandleScope handleScope(fIsolate);

    printf("Before create context\n");

    // Create a new context.
    Handle<Context> context = this->createRootContext();

    // Enter the scope so all operations take place in the scope.
    Context::Scope contextScope(context);

    v8::TryCatch tryCatch;

    // Compile the source code.
    Handle<String> source = String::NewFromUtf8(fIsolate, script);
    printf("Before Compile\n");
    Handle<Script> compiledScript = Script::Compile(source);
    printf("After Compile\n");

    if (compiledScript.IsEmpty()) {
        // Print errors that happened during compilation.
        this->reportException(&tryCatch);
        return false;
    }
    printf("After Exception.\n");

    // Try running it now to create the onDraw function.
    Handle<Value> result = compiledScript->Run();

    // Handle any exceptions or output.
    if (result.IsEmpty()) {
        SkASSERT(tryCatch.HasCaught());
        // Print errors that happened during execution.
        this->reportException(&tryCatch);
        return false;
    } else {
        SkASSERT(!tryCatch.HasCaught());
        if (!result->IsUndefined()) {
            // If all went well and the result wasn't undefined then print
            // the returned value.
            String::Utf8Value str(result);
            const char* cstr = to_cstring(str);
            printf("%s\n", cstr);
            return false;
        }
    }

    // Also make the context persistent.
    fContext.Reset(fIsolate, context);
    return true;
}
