// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <v8.h>

#ifdef ENABLE_DEBUGGER_SUPPORT
#include <v8-debug.h>
#endif  // ENABLE_DEBUGGER_SUPPORT

#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

/**
 * This sample program should demonstrate certain aspects of debugging
 * standalone V8-based application.
 *
 * The program reads input stream, processes it line by line and print
 * the result to output. The actual processing is done by custom JavaScript
 * script. The script is specified with command line parameters.
 *
 * The main cycle of the program will sequentially read lines from standard
 * input, process them and print to standard output until input closes.
 * There are 2 possible configuration in regard to main cycle.
 *
 * 1. The main cycle is on C++ side. Program should be run with
 * --main-cycle-in-cpp option. Script must declare a function named
 * "ProcessLine". The main cycle in C++ reads lines and calls this function
 * for processing every time. This is a sample script:

function ProcessLine(input_line) {
  return ">>>" + input_line + "<<<";
}

 *
 * 2. The main cycle is in JavaScript. Program should be run with
 * --main-cycle-in-js option. Script gets run one time at all and gets
 * API of 2 global functions: "read_line" and "print". It should read input
 * and print converted lines to output itself. This a sample script:

while (true) {
  var line = read_line();
  if (!line) {
    break;
  }
  var res = line + " | " + line;
  print(res);
}

 *
 * When run with "-p" argument, the program starts V8 Debugger Agent and
 * allows remote debugger to attach and debug JavaScript code.
 *
 * Interesting aspects:
 * 1. Wait for remote debugger to attach
 * Normally the program compiles custom script and immediately runs it.
 * If programmer needs to debug script from the very beginning, he should
 * run this sample program with "--wait-for-connection" command line parameter.
 * This way V8 will suspend on the first statement and wait for
 * debugger to attach.
 *
 * 2. Unresponsive V8
 * V8 Debugger Agent holds a connection with remote debugger, but it does
 * respond only when V8 is running some script. In particular, when this program
 * is waiting for input, all requests from debugger get deferred until V8
 * is called again. See how "--callback" command-line parameter in this sample
 * fixes this issue.
 */

enum MainCycleType {
  CycleInCpp,
  CycleInJs
};

const char* ToCString(const v8::String::Utf8Value& value);
void ReportException(v8::Isolate* isolate, v8::TryCatch* handler);
v8::Handle<v8::String> ReadFile(v8::Isolate* isolate, const char* name);
v8::Handle<v8::String> ReadLine();

void Print(const v8::FunctionCallbackInfo<v8::Value>& args);
void ReadLine(const v8::FunctionCallbackInfo<v8::Value>& args);
bool RunCppCycle(v8::Handle<v8::Script> script,
                 v8::Local<v8::Context> context,
                 bool report_exceptions);


#ifdef ENABLE_DEBUGGER_SUPPORT
v8::Persistent<v8::Context> debug_message_context;

void DispatchDebugMessages() {
  // We are in some random thread. We should already have v8::Locker acquired
  // (we requested this when registered this callback). We was called
  // because new debug messages arrived; they may have already been processed,
  // but we shouldn't worry about this.
  //
  // All we have to do is to set context and call ProcessDebugMessages.
  //
  // We should decide which V8 context to use here. This is important for
  // "evaluate" command, because it must be executed some context.
  // In our sample we have only one context, so there is nothing really to
  // think about.
  v8::Isolate* isolate = v8::Isolate::GetCurrent();
  v8::HandleScope handle_scope(isolate);
  v8::Local<v8::Context> context =
      v8::Local<v8::Context>::New(isolate, debug_message_context);
  v8::Context::Scope scope(context);

  v8::Debug::ProcessDebugMessages();
}
#endif  // ENABLE_DEBUGGER_SUPPORT


int RunMain(int argc, char* argv[]) {
  v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
  v8::Isolate* isolate = v8::Isolate::GetCurrent();
  v8::HandleScope handle_scope(isolate);

  v8::Handle<v8::String> script_source;
  v8::Handle<v8::Value> script_name;
  int script_param_counter = 0;

#ifdef ENABLE_DEBUGGER_SUPPORT
  int port_number = -1;
  bool wait_for_connection = false;
  bool support_callback = false;
#endif  // ENABLE_DEBUGGER_SUPPORT

  MainCycleType cycle_type = CycleInCpp;

  for (int i = 1; i < argc; i++) {
    const char* str = argv[i];
    if (strcmp(str, "-f") == 0) {
      // Ignore any -f flags for compatibility with the other stand-
      // alone JavaScript engines.
      continue;
    } else if (strcmp(str, "--main-cycle-in-cpp") == 0) {
      cycle_type = CycleInCpp;
    } else if (strcmp(str, "--main-cycle-in-js") == 0) {
      cycle_type = CycleInJs;
#ifdef ENABLE_DEBUGGER_SUPPORT
    } else if (strcmp(str, "--callback") == 0) {
      support_callback = true;
    } else if (strcmp(str, "--wait-for-connection") == 0) {
      wait_for_connection = true;
    } else if (strcmp(str, "-p") == 0 && i + 1 < argc) {
      port_number = atoi(argv[i + 1]);  // NOLINT
      i++;
#endif  // ENABLE_DEBUGGER_SUPPORT
    } else if (strncmp(str, "--", 2) == 0) {
      printf("Warning: unknown flag %s.\nTry --help for options\n", str);
    } else if (strcmp(str, "-e") == 0 && i + 1 < argc) {
      script_source = v8::String::NewFromUtf8(isolate, argv[i + 1]);
      script_name = v8::String::NewFromUtf8(isolate, "unnamed");
      i++;
      script_param_counter++;
    } else {
      // Use argument as a name of file to load.
      script_source = ReadFile(isolate, str);
      script_name = v8::String::NewFromUtf8(isolate, str);
      if (script_source.IsEmpty()) {
        printf("Error reading '%s'\n", str);
        return 1;
      }
      script_param_counter++;
    }
  }

  if (script_param_counter == 0) {
    printf("Script is not specified\n");
    return 1;
  }
  if (script_param_counter != 1) {
    printf("Only one script may be specified\n");
    return 1;
  }

  // Create a template for the global object.
  v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();

  // Bind the global 'print' function to the C++ Print callback.
  global->Set(v8::String::NewFromUtf8(isolate, "print"),
              v8::FunctionTemplate::New(Print));

  if (cycle_type == CycleInJs) {
    // Bind the global 'read_line' function to the C++ Print callback.
    global->Set(v8::String::NewFromUtf8(isolate, "read_line"),
                v8::FunctionTemplate::New(ReadLine));
  }

  // Create a new execution environment containing the built-in
  // functions
  v8::Handle<v8::Context> context = v8::Context::New(isolate, NULL, global);
  // Enter the newly created execution environment.
  v8::Context::Scope context_scope(context);

#ifdef ENABLE_DEBUGGER_SUPPORT
  debug_message_context.Reset(isolate, context);

  v8::Locker locker(isolate);

  if (support_callback) {
    v8::Debug::SetDebugMessageDispatchHandler(DispatchDebugMessages, true);
  }

  if (port_number != -1) {
    v8::Debug::EnableAgent("lineprocessor", port_number, wait_for_connection);
  }
#endif  // ENABLE_DEBUGGER_SUPPORT

  bool report_exceptions = true;

  v8::Handle<v8::Script> script;
  {
    // Compile script in try/catch context.
    v8::TryCatch try_catch;
    script = v8::Script::Compile(script_source, script_name);
    if (script.IsEmpty()) {
      // Print errors that happened during compilation.
      if (report_exceptions)
        ReportException(isolate, &try_catch);
      return 1;
    }
  }

  {
    v8::TryCatch try_catch;

    script->Run();
    if (try_catch.HasCaught()) {
      if (report_exceptions)
        ReportException(isolate, &try_catch);
      return 1;
    }
  }

  if (cycle_type == CycleInCpp) {
    bool res = RunCppCycle(script,
                           isolate->GetCurrentContext(),
                           report_exceptions);
    return !res;
  } else {
    // All is already done.
  }
  return 0;
}


bool RunCppCycle(v8::Handle<v8::Script> script,
                 v8::Local<v8::Context> context,
                 bool report_exceptions) {
  v8::Isolate* isolate = context->GetIsolate();
#ifdef ENABLE_DEBUGGER_SUPPORT
  v8::Locker lock(isolate);
#endif  // ENABLE_DEBUGGER_SUPPORT

  v8::Handle<v8::String> fun_name =
      v8::String::NewFromUtf8(isolate, "ProcessLine");
  v8::Handle<v8::Value> process_val = context->Global()->Get(fun_name);

  // If there is no Process function, or if it is not a function,
  // bail out
  if (!process_val->IsFunction()) {
    printf("Error: Script does not declare 'ProcessLine' global function.\n");
    return 1;
  }

  // It is a function; cast it to a Function
  v8::Handle<v8::Function> process_fun =
      v8::Handle<v8::Function>::Cast(process_val);


  while (!feof(stdin)) {
    v8::HandleScope handle_scope(isolate);

    v8::Handle<v8::String> input_line = ReadLine();
    if (input_line == v8::Undefined(isolate)) {
      continue;
    }

    const int argc = 1;
    v8::Handle<v8::Value> argv[argc] = { input_line };

    v8::Handle<v8::Value> result;
    {
      v8::TryCatch try_catch;
      result = process_fun->Call(isolate->GetCurrentContext()->Global(),
                                 argc, argv);
      if (try_catch.HasCaught()) {
        if (report_exceptions)
          ReportException(isolate, &try_catch);
        return false;
      }
    }
    v8::String::Utf8Value str(result);
    const char* cstr = ToCString(str);
    printf("%s\n", cstr);
  }

  return true;
}


int main(int argc, char* argv[]) {
  v8::V8::InitializeICU();
  int result = RunMain(argc, argv);
  v8::V8::Dispose();
  return result;
}


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


// Reads a file into a v8 string.
v8::Handle<v8::String> ReadFile(v8::Isolate* isolate, const char* name) {
  FILE* file = fopen(name, "rb");
  if (file == NULL) return v8::Handle<v8::String>();

  fseek(file, 0, SEEK_END);
  int size = ftell(file);
  rewind(file);

  char* chars = new char[size + 1];
  chars[size] = '\0';
  for (int i = 0; i < size;) {
    int read = static_cast<int>(fread(&chars[i], 1, size - i, file));
    i += read;
  }
  fclose(file);
  v8::Handle<v8::String> result =
      v8::String::NewFromUtf8(isolate, chars, v8::String::kNormalString, size);
  delete[] chars;
  return result;
}


void ReportException(v8::Isolate* isolate, v8::TryCatch* try_catch) {
  v8::HandleScope handle_scope(isolate);
  v8::String::Utf8Value exception(try_catch->Exception());
  const char* exception_string = ToCString(exception);
  v8::Handle<v8::Message> message = try_catch->Message();
  if (message.IsEmpty()) {
    // V8 didn't provide any extra information about this error; just
    // print the exception.
    printf("%s\n", exception_string);
  } else {
    // Print (filename):(line number): (message).
    v8::String::Utf8Value filename(message->GetScriptResourceName());
    const char* filename_string = ToCString(filename);
    int linenum = message->GetLineNumber();
    printf("%s:%i: %s\n", filename_string, linenum, exception_string);
    // Print line of source code.
    v8::String::Utf8Value sourceline(message->GetSourceLine());
    const char* sourceline_string = ToCString(sourceline);
    printf("%s\n", sourceline_string);
    // Print wavy underline (GetUnderline is deprecated).
    int start = message->GetStartColumn();
    for (int i = 0; i < start; i++) {
      printf(" ");
    }
    int end = message->GetEndColumn();
    for (int i = start; i < end; i++) {
      printf("^");
    }
    printf("\n");
  }
}


// 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.
void Print(const v8::FunctionCallbackInfo<v8::Value>& args) {
  bool first = true;
  for (int i = 0; i < args.Length(); i++) {
    v8::HandleScope handle_scope(args.GetIsolate());
    if (first) {
      first = false;
    } else {
      printf(" ");
    }
    v8::String::Utf8Value str(args[i]);
    const char* cstr = ToCString(str);
    printf("%s", cstr);
  }
  printf("\n");
  fflush(stdout);
}


// The callback that is invoked by v8 whenever the JavaScript 'read_line'
// function is called. Reads a string from standard input and returns.
void ReadLine(const v8::FunctionCallbackInfo<v8::Value>& args) {
  if (args.Length() > 0) {
    args.GetIsolate()->ThrowException(
        v8::String::NewFromUtf8(args.GetIsolate(), "Unexpected arguments"));
    return;
  }
  args.GetReturnValue().Set(ReadLine());
}


v8::Handle<v8::String> ReadLine() {
  const int kBufferSize = 1024 + 1;
  char buffer[kBufferSize];

  char* res;
  {
#ifdef ENABLE_DEBUGGER_SUPPORT
    v8::Unlocker unlocker(v8::Isolate::GetCurrent());
#endif  // ENABLE_DEBUGGER_SUPPORT
    res = fgets(buffer, kBufferSize, stdin);
  }
  v8::Isolate* isolate = v8::Isolate::GetCurrent();
  if (res == NULL) {
    v8::Handle<v8::Primitive> t = v8::Undefined(isolate);
    return v8::Handle<v8::String>::Cast(t);
  }
  // Remove newline char
  for (char* pos = buffer; *pos != '\0'; pos++) {
    if (*pos == '\n') {
      *pos = '\0';
      break;
    }
  }
  return v8::String::NewFromUtf8(isolate, buffer);
}
