// Copyright 2008 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 "d8.h"
#include "d8-debug.h"
#include "platform.h"
#include "debug-agent.h"


namespace v8 {

void PrintPrompt() {
  printf("dbg> ");
  fflush(stdout);
}


void HandleDebugEvent(DebugEvent event,
                      Handle<Object> exec_state,
                      Handle<Object> event_data,
                      Handle<Value> data) {
  HandleScope scope;

  // Check for handled event.
  if (event != Break && event != Exception && event != AfterCompile) {
    return;
  }

  TryCatch try_catch;

  // Get the toJSONProtocol function on the event and get the JSON format.
  Local<String> to_json_fun_name = String::New("toJSONProtocol");
  Local<Function> to_json_fun =
      Function::Cast(*event_data->Get(to_json_fun_name));
  Local<Value> event_json = to_json_fun->Call(event_data, 0, NULL);
  if (try_catch.HasCaught()) {
    Shell::ReportException(&try_catch);
    return;
  }

  // Print the event details.
  Handle<Object> details =
      Shell::DebugMessageDetails(Handle<String>::Cast(event_json));
  if (try_catch.HasCaught()) {
    Shell::ReportException(&try_catch);
    return;
  }
  String::Utf8Value str(details->Get(String::New("text")));
  if (str.length() == 0) {
    // Empty string is used to signal not to process this event.
    return;
  }
  printf("%s\n", *str);

  // Get the debug command processor.
  Local<String> fun_name = String::New("debugCommandProcessor");
  Local<Function> fun = Function::Cast(*exec_state->Get(fun_name));
  Local<Object> cmd_processor =
      Object::Cast(*fun->Call(exec_state, 0, NULL));
  if (try_catch.HasCaught()) {
    Shell::ReportException(&try_catch);
    return;
  }

  static const int kBufferSize = 256;
  bool running = false;
  while (!running) {
    char command[kBufferSize];
    PrintPrompt();
    char* str = fgets(command, kBufferSize, stdin);
    if (str == NULL) break;

    // Ignore empty commands.
    if (strlen(command) == 0) continue;

    TryCatch try_catch;

    // Convert the debugger command to a JSON debugger request.
    Handle<Value> request =
        Shell::DebugCommandToJSONRequest(String::New(command));
    if (try_catch.HasCaught()) {
      Shell::ReportException(&try_catch);
      continue;
    }

    // If undefined is returned the command was handled internally and there is
    // no JSON to send.
    if (request->IsUndefined()) {
      continue;
    }

    Handle<String> fun_name;
    Handle<Function> fun;
    // All the functions used below take one argument.
    static const int kArgc = 1;
    Handle<Value> args[kArgc];

    // Invoke the JavaScript to convert the debug command line to a JSON
    // request, invoke the JSON request and convert the JSON respose to a text
    // representation.
    fun_name = String::New("processDebugRequest");
    fun = Handle<Function>::Cast(cmd_processor->Get(fun_name));
    args[0] = request;
    Handle<Value> response_val = fun->Call(cmd_processor, kArgc, args);
    if (try_catch.HasCaught()) {
      Shell::ReportException(&try_catch);
      continue;
    }
    Handle<String> response = Handle<String>::Cast(response_val);

    // Convert the debugger response into text details and the running state.
    Handle<Object> response_details = Shell::DebugMessageDetails(response);
    if (try_catch.HasCaught()) {
      Shell::ReportException(&try_catch);
      continue;
    }
    String::Utf8Value text_str(response_details->Get(String::New("text")));
    if (text_str.length() > 0) {
      printf("%s\n", *text_str);
    }
    running =
        response_details->Get(String::New("running"))->ToBoolean()->Value();
  }
}


void RunRemoteDebugger(int port) {
  RemoteDebugger debugger(port);
  debugger.Run();
}


void RemoteDebugger::Run() {
  bool ok;

  // Make sure that socket support is initialized.
  ok = i::Socket::Setup();
  if (!ok) {
    printf("Unable to initialize socket support %d\n", i::Socket::LastError());
    return;
  }

  // Connect to the debugger agent.
  conn_ = i::OS::CreateSocket();
  static const int kPortStrSize = 6;
  char port_str[kPortStrSize];
  i::OS::SNPrintF(i::Vector<char>(port_str, kPortStrSize), "%d", port_);
  ok = conn_->Connect("localhost", port_str);
  if (!ok) {
    printf("Unable to connect to debug agent %d\n", i::Socket::LastError());
    return;
  }

  // Start the receiver thread.
  ReceiverThread receiver(this);
  receiver.Start();

  // Start the keyboard thread.
  KeyboardThread keyboard(this);
  keyboard.Start();
  PrintPrompt();

  // Process events received from debugged VM and from the keyboard.
  bool terminate = false;
  while (!terminate) {
    event_available_->Wait();
    RemoteDebuggerEvent* event = GetEvent();
    switch (event->type()) {
      case RemoteDebuggerEvent::kMessage:
        HandleMessageReceived(event->data());
        break;
      case RemoteDebuggerEvent::kKeyboard:
        HandleKeyboardCommand(event->data());
        break;
      case RemoteDebuggerEvent::kDisconnect:
        terminate = true;
        break;

      default:
        UNREACHABLE();
    }
    delete event;
  }

  // Wait for the receiver thread to end.
  receiver.Join();
}


void RemoteDebugger::MessageReceived(i::SmartPointer<char> message) {
  RemoteDebuggerEvent* event =
      new RemoteDebuggerEvent(RemoteDebuggerEvent::kMessage, message);
  AddEvent(event);
}


void RemoteDebugger::KeyboardCommand(i::SmartPointer<char> command) {
  RemoteDebuggerEvent* event =
      new RemoteDebuggerEvent(RemoteDebuggerEvent::kKeyboard, command);
  AddEvent(event);
}


void RemoteDebugger::ConnectionClosed() {
  RemoteDebuggerEvent* event =
      new RemoteDebuggerEvent(RemoteDebuggerEvent::kDisconnect,
                              i::SmartPointer<char>());
  AddEvent(event);
}


void RemoteDebugger::AddEvent(RemoteDebuggerEvent* event) {
  i::ScopedLock lock(event_access_);
  if (head_ == NULL) {
    ASSERT(tail_ == NULL);
    head_ = event;
    tail_ = event;
  } else {
    ASSERT(tail_ != NULL);
    tail_->set_next(event);
    tail_ = event;
  }
  event_available_->Signal();
}


RemoteDebuggerEvent* RemoteDebugger::GetEvent() {
  i::ScopedLock lock(event_access_);
  ASSERT(head_ != NULL);
  RemoteDebuggerEvent* result = head_;
  head_ = head_->next();
  if (head_ == NULL) {
    ASSERT(tail_ == result);
    tail_ = NULL;
  }
  return result;
}


void RemoteDebugger::HandleMessageReceived(char* message) {
  HandleScope scope;

  // Print the event details.
  TryCatch try_catch;
  Handle<Object> details =
      Shell::DebugMessageDetails(Handle<String>::Cast(String::New(message)));
  if (try_catch.HasCaught()) {
    Shell::ReportException(&try_catch);
    PrintPrompt();
    return;
  }
  String::Utf8Value str(details->Get(String::New("text")));
  if (str.length() == 0) {
    // Empty string is used to signal not to process this event.
    return;
  }
  if (*str != NULL) {
    printf("%s\n", *str);
  } else {
    printf("???\n");
  }
  PrintPrompt();
}


void RemoteDebugger::HandleKeyboardCommand(char* command) {
  HandleScope scope;

  // Convert the debugger command to a JSON debugger request.
  TryCatch try_catch;
  Handle<Value> request =
      Shell::DebugCommandToJSONRequest(String::New(command));
  if (try_catch.HasCaught()) {
    v8::String::Utf8Value exception(try_catch.Exception());
    const char* exception_string = Shell::ToCString(exception);
    printf("%s\n", exception_string);
    PrintPrompt();
    return;
  }

  // If undefined is returned the command was handled internally and there is
  // no JSON to send.
  if (request->IsUndefined()) {
    PrintPrompt();
    return;
  }

  // Send the JSON debugger request.
  i::DebuggerAgentUtil::SendMessage(conn_, Handle<String>::Cast(request));
}


void ReceiverThread::Run() {
  // Receive the connect message (with empty body).
  i::SmartPointer<char> message =
    i::DebuggerAgentUtil::ReceiveMessage(remote_debugger_->conn());
  ASSERT(*message == NULL);

  while (true) {
    // Receive a message.
    i::SmartPointer<char> message =
      i::DebuggerAgentUtil::ReceiveMessage(remote_debugger_->conn());
    if (*message == NULL) {
      remote_debugger_->ConnectionClosed();
      return;
    }

    // Pass the message to the main thread.
    remote_debugger_->MessageReceived(message);
  }
}


void KeyboardThread::Run() {
  static const int kBufferSize = 256;
  while (true) {
    // read keyboard input.
    char command[kBufferSize];
    char* str = fgets(command, kBufferSize, stdin);
    if (str == NULL) {
      break;
    }

    // Pass the keyboard command to the main thread.
    remote_debugger_->KeyboardCommand(
        i::SmartPointer<char>(i::StrDup(command)));
  }
}


}  // namespace v8
