// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "bin/vmservice_impl.h"

#include "include/dart_api.h"

#include "bin/builtin.h"
#include "bin/dartutils.h"
#include "bin/isolate_data.h"
#include "bin/resources.h"
#include "bin/thread.h"

#include "vm/dart_api_impl.h"
#include "vm/dart_entry.h"
#include "vm/isolate.h"
#include "vm/message.h"
#include "vm/native_entry.h"
#include "vm/native_arguments.h"
#include "vm/object.h"
#include "vm/port.h"
#include "vm/snapshot.h"

namespace dart {
namespace bin {

// snapshot_buffer points to a snapshot if we link in a snapshot otherwise
// it is initialized to NULL.
extern const uint8_t* snapshot_buffer;
#define RETURN_ERROR_HANDLE(handle)                             \
  if (Dart_IsError(handle)) {                                   \
    return handle;                                              \
  }

#define SHUTDOWN_ON_ERROR(handle)                               \
  if (Dart_IsError(handle)) {                                   \
    error_msg_ = strdup(Dart_GetError(handle));                 \
    Dart_ExitScope();                                           \
    Dart_ShutdownIsolate();                                     \
    return false;                                               \
  }

#define kLibraryResourceNamePrefix "/vmservice"
static const char* kVMServiceIOLibraryScriptResourceName =
    kLibraryResourceNamePrefix "/vmservice_io.dart";
static const char* kVMServiceLibraryName =
    kLibraryResourceNamePrefix "/vmservice.dart";

#define kClientResourceNamePrefix "/client/web/out"

Dart_Isolate VmService::isolate_ = NULL;
Dart_Port VmService::port_ = ILLEGAL_PORT;
dart::Monitor* VmService::monitor_ = NULL;
const char* VmService::error_msg_ = NULL;

// These must be kept in sync with vmservice/constants.dart
#define VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID 1
#define VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID 2


static Dart_NativeFunction VmServiceNativeResolver(Dart_Handle name,
                                                   int num_arguments);


bool VmService::Start(intptr_t server_port) {
  monitor_ = new dart::Monitor();
  ASSERT(monitor_ != NULL);
  error_msg_ = NULL;


  {
    // Take lock before spawning new thread.
    MonitorLocker ml(monitor_);
    // Spawn new thread.
    dart::Thread::Start(ThreadMain, server_port);
    // Wait until service is running on spawned thread.
    ml.Wait();
  }
  return port_ != ILLEGAL_PORT;
}


bool VmService::_Start(intptr_t server_port) {
  ASSERT(isolate_ == NULL);
  char* error = NULL;
  isolate_ = Dart_CreateIsolate("vmservice:", "main", snapshot_buffer,
                                new IsolateData(),
                                &error);
  if (isolate_ == NULL) {
    error_msg_ = error;
    return false;
  }

  Dart_EnterScope();

  if (snapshot_buffer != NULL) {
    // Setup the native resolver as the snapshot does not carry it.
    Builtin::SetNativeResolver(Builtin::kBuiltinLibrary);
    Builtin::SetNativeResolver(Builtin::kIOLibrary);
  }

  // Set up the library tag handler for this isolate.
  Dart_Handle result = Dart_SetLibraryTagHandler(LibraryTagHandler);
  SHUTDOWN_ON_ERROR(result);

  // Load the specified application script into the newly created isolate.

  // Prepare builtin and its dependent libraries for use to resolve URIs.
  // The builtin library is part of the core snapshot and would already be
  // available here in the case of script snapshot loading.
  Dart_Handle builtin_lib =
      Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
  SHUTDOWN_ON_ERROR(builtin_lib);

  // Prepare for script loading by setting up the 'print' and 'timer'
  // closures and setting up 'package root' for URI resolution.
  result = DartUtils::PrepareForScriptLoading("", builtin_lib);
  SHUTDOWN_ON_ERROR(result);

  {
    // Load source into service isolate.
    Dart_Handle library = LoadScript(kVMServiceIOLibraryScriptResourceName);
    SHUTDOWN_ON_ERROR(library);
  }

  // Make the isolate runnable so that it is ready to handle messages.
  Dart_ExitScope();
  Dart_ExitIsolate();

  bool retval = Dart_IsolateMakeRunnable(isolate_);
  if (!retval) {
    Dart_EnterIsolate(isolate_);
    Dart_ShutdownIsolate();
    error_msg_ = "Invalid isolate state - Unable to make it runnable.";
    return false;
  }

  Dart_EnterIsolate(isolate_);
  Dart_EnterScope();


  Dart_Handle library = Dart_RootLibrary();
  // Set requested port.
  DartUtils::SetIntegerField(library, "_port", server_port);
  result = Dart_Invoke(library, DartUtils::NewString("main"), 0, NULL);
  SHUTDOWN_ON_ERROR(result);

  result = LoadResources(library);
  SHUTDOWN_ON_ERROR(result);
  result = Dart_CompileAll();
  SHUTDOWN_ON_ERROR(result);

  port_ = Dart_GetMainPortId();

  Dart_ExitScope();
  Dart_ExitIsolate();

  return true;
}


void VmService::_Stop() {
  port_ = ILLEGAL_PORT;
}


const char* VmService::GetErrorMessage() {
  return error_msg_ == NULL ? "No error." : error_msg_;
}


Dart_Port VmService::port() {
  return port_;
}


bool VmService::IsRunning() {
  return port_ != ILLEGAL_PORT;
}


Dart_Handle VmService::GetSource(const char* name) {
  const char* vmservice_source = NULL;
  int r = Resources::ResourceLookup(name, &vmservice_source);
  ASSERT(r != Resources::kNoSuchInstance);
  return Dart_NewStringFromCString(vmservice_source);
}


Dart_Handle VmService::LoadScript(const char* name) {
  Dart_Handle url = Dart_NewStringFromCString(name);
  Dart_Handle source = GetSource(name);
  return Dart_LoadScript(url, source, 0, 0);
}


Dart_Handle VmService::LoadSource(Dart_Handle library, const char* name) {
  Dart_Handle url = Dart_NewStringFromCString(name);
  Dart_Handle source = GetSource(name);
  return Dart_LoadSource(library, url, source);
}


Dart_Handle VmService::LoadSources(Dart_Handle library, const char* names[]) {
  Dart_Handle result = Dart_Null();
  for (int i = 0; names[i] != NULL; i++) {
    result = LoadSource(library, names[i]);
    if (Dart_IsError(result)) {
      break;
    }
  }
  return result;
}


Dart_Handle VmService::LoadResource(Dart_Handle library,
                                    const char* resource_name,
                                    const char* prefix) {
  intptr_t prefix_len = strlen(prefix);
  // Prepare for invoke call.
  Dart_Handle name = Dart_NewStringFromCString(resource_name+prefix_len);
  RETURN_ERROR_HANDLE(name);
  const char* data_buffer = NULL;
  int data_buffer_length = Resources::ResourceLookup(resource_name,
                                                     &data_buffer);
  if (data_buffer_length == Resources::kNoSuchInstance) {
    printf("Could not find %s %s\n", resource_name, resource_name+prefix_len);
  }
  ASSERT(data_buffer_length != Resources::kNoSuchInstance);
  Dart_Handle data_list = Dart_NewTypedData(Dart_TypedData_kUint8,
                                            data_buffer_length);
  RETURN_ERROR_HANDLE(data_list);
  Dart_TypedData_Type type = Dart_TypedData_kInvalid;
  void* data_list_buffer = NULL;
  intptr_t data_list_buffer_length = 0;
  Dart_Handle result = Dart_TypedDataAcquireData(data_list, &type,
                                                 &data_list_buffer,
                                                 &data_list_buffer_length);
  RETURN_ERROR_HANDLE(result);
  ASSERT(data_buffer_length == data_list_buffer_length);
  ASSERT(data_list_buffer != NULL);
  ASSERT(type = Dart_TypedData_kUint8);
  memmove(data_list_buffer, &data_buffer[0], data_buffer_length);
  result = Dart_TypedDataReleaseData(data_list);
  RETURN_ERROR_HANDLE(result);

  // Make invoke call.
  const intptr_t kNumArgs = 2;
  Dart_Handle args[kNumArgs] = { name, data_list };
  result = Dart_Invoke(library, Dart_NewStringFromCString("_addResource"),
                       kNumArgs, args);
  return result;
}


Dart_Handle VmService::LoadResources(Dart_Handle library) {
  Dart_Handle result = Dart_Null();
  intptr_t prefixLen = strlen(kClientResourceNamePrefix);
  for (intptr_t i = 0; i < Resources::get_resource_count(); i++) {
    const char* path = Resources::get_resource_path(i);
    if (!strncmp(path, kClientResourceNamePrefix, prefixLen)) {
      result = LoadResource(library, path, kClientResourceNamePrefix);
      if (Dart_IsError(result)) {
        break;
      }
    }
  }
  return result;
}


static bool IsVMServiceURL(const char* url) {
  static const intptr_t kLibraryResourceNamePrefixLen =
      strlen(kLibraryResourceNamePrefix);
  return 0 == strncmp(kLibraryResourceNamePrefix, url,
                      kLibraryResourceNamePrefixLen);
}


static bool IsVMServiceLibrary(const char* url) {
  return 0 == strcmp(kVMServiceLibraryName, url);
}


Dart_Handle VmService::LibraryTagHandler(Dart_LibraryTag tag,
                                         Dart_Handle library,
                                         Dart_Handle url) {
  if (!Dart_IsLibrary(library)) {
    return Dart_Error("not a library");
  }
  if (!Dart_IsString(url)) {
    return Dart_Error("url is not a string");
  }
  const char* url_string = NULL;
  Dart_Handle result = Dart_StringToCString(url, &url_string);
  if (Dart_IsError(result)) {
    return result;
  }
  Dart_Handle library_url = Dart_LibraryUrl(library);
  const char* library_url_string = NULL;
  result = Dart_StringToCString(library_url, &library_url_string);
  if (Dart_IsError(result)) {
    return result;
  }
  bool is_vm_service_url = IsVMServiceURL(url_string);
  if (!is_vm_service_url) {
    // Pass to DartUtils.
    return DartUtils::LibraryTagHandler(tag, library, url);
  }
  switch (tag) {
    case Dart_kCanonicalizeUrl:
      // The URL is already canonicalized.
      return url;
    break;
    case Dart_kImportTag: {
      Dart_Handle source = GetSource(url_string);
      if (Dart_IsError(source)) {
        return source;
      }
      Dart_Handle lib = Dart_LoadLibrary(url, source);
      if (Dart_IsError(lib)) {
        return lib;
      }
      if (IsVMServiceLibrary(url_string)) {
        // Install native resolver for this library.
        result = Dart_SetNativeResolver(lib, VmServiceNativeResolver);
        if (Dart_IsError(result)) {
          return result;
        }
      }
      return lib;
    }
    break;
    case Dart_kSourceTag: {
      Dart_Handle source = GetSource(url_string);
      if (Dart_IsError(source)) {
        return source;
      }
      return Dart_LoadSource(library, url, source);
    }
    break;
    default:
      UNIMPLEMENTED();
    break;
  }
  UNREACHABLE();
  return result;
}


void VmService::ThreadMain(uword parameters) {
  ASSERT(Dart_CurrentIsolate() == NULL);
  ASSERT(isolate_ == NULL);

  intptr_t server_port = static_cast<intptr_t>(parameters);
  ASSERT(server_port >= 0);

  // Lock scope.
  {
    MonitorLocker ml(monitor_);
    bool r = _Start(server_port);
    if (!r) {
      port_ = ILLEGAL_PORT;
      monitor_->Notify();
      return;
    }

    Dart_EnterIsolate(isolate_);
    Dart_EnterScope();

    Dart_Handle receievePort = Dart_GetReceivePort(port_);
    ASSERT(!Dart_IsError(receievePort));
    monitor_->Notify();
  }

  // Keep handling messages until the last active receive port is closed.
  Dart_Handle result = Dart_RunLoop();
  if (Dart_IsError(result)) {
    printf("VmService has exited with an error:\n%s\n", Dart_GetError(result));
  }

  _Stop();

  Dart_ExitScope();
  Dart_ExitIsolate();
}


static Dart_Handle MakeServiceControlMessage(Dart_Port port, intptr_t code) {
  Dart_Handle result;
  Dart_Handle list = Dart_NewList(3);
  ASSERT(!Dart_IsError(list));
  Dart_Handle codeHandle = Dart_NewInteger(code);
  ASSERT(!Dart_IsError(codeHandle));
  result = Dart_ListSetAt(list, 0, codeHandle);
  ASSERT(!Dart_IsError(result));
  Dart_Handle sendPort = Dart_NewSendPort(port);
  ASSERT(!Dart_IsError(sendPort));
  result = Dart_ListSetAt(list, 1, sendPort);
  ASSERT(!Dart_IsError(result));
  return list;
}


bool VmService::SendIsolateStartupMessage(Dart_Port port, Dart_Handle name) {
  if (!IsRunning()) {
    return false;
  }
  Dart_Isolate isolate = Dart_CurrentIsolate();
  ASSERT(isolate != NULL);
  ASSERT(Dart_GetMainPortId() == port);
  Dart_Handle list =
      MakeServiceControlMessage(port, VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID);
  ASSERT(!Dart_IsError(list));
  Dart_Handle result = Dart_ListSetAt(list, 2, name);
  ASSERT(!Dart_IsError(result));
  return Dart_Post(port_, list);
}


bool VmService::SendIsolateShutdownMessage(Dart_Port port) {
  if (!IsRunning()) {
    return false;
  }
  Dart_Isolate isolate = Dart_CurrentIsolate();
  ASSERT(isolate != NULL);
  ASSERT(Dart_GetMainPortId() == port);
  Dart_Handle list =
      MakeServiceControlMessage(port, VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID);
  ASSERT(!Dart_IsError(list));
  return Dart_Post(port_, list);
}


void VmService::VmServiceShutdownCallback(void* callback_data) {
  ASSERT(Dart_CurrentIsolate() != NULL);
  Dart_EnterScope();
  VmService::SendIsolateShutdownMessage(Dart_GetMainPortId());
  Dart_ExitScope();
}


static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) {
  void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size);
  return reinterpret_cast<uint8_t*>(new_ptr);
}


static void SendServiceMessage(Dart_NativeArguments args) {
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  Isolate* isolate = arguments->isolate();
  StackZone zone(isolate);
  HANDLESCOPE(isolate);
  GET_NON_NULL_NATIVE_ARGUMENT(Instance, sp, arguments->NativeArgAt(0));
  GET_NON_NULL_NATIVE_ARGUMENT(Instance, rp, arguments->NativeArgAt(1));
  GET_NON_NULL_NATIVE_ARGUMENT(Instance, message, arguments->NativeArgAt(2));

  // Extract SendPort port id.
  const Object& sp_id_obj = Object::Handle(DartLibraryCalls::PortGetId(sp));
  if (sp_id_obj.IsError()) {
    Exceptions::PropagateError(Error::Cast(sp_id_obj));
  }
  Integer& id = Integer::Handle();
  id ^= sp_id_obj.raw();
  Dart_Port sp_id = static_cast<Dart_Port>(id.AsInt64Value());

  // Extract ReceivePort port id.
  const Object& rp_id_obj = Object::Handle(DartLibraryCalls::PortGetId(rp));
  if (rp_id_obj.IsError()) {
    Exceptions::PropagateError(Error::Cast(rp_id_obj));
  }
  ASSERT(rp_id_obj.IsSmi() || rp_id_obj.IsMint());
  id ^= rp_id_obj.raw();
  Dart_Port rp_id = static_cast<Dart_Port>(id.AsInt64Value());

  // Both are valid ports.
  ASSERT(sp_id != ILLEGAL_PORT);
  ASSERT(rp_id != ILLEGAL_PORT);

  // Serialize message.
  uint8_t* data = NULL;
  MessageWriter writer(&data, &allocator);
  writer.WriteMessage(message);

  // TODO(turnidge): Throw an exception when the return value is false?
  PortMap::PostMessage(new Message(sp_id, rp_id, data, writer.BytesWritten(),
                                   Message::kOOBPriority));
}


struct VmServiceNativeEntry {
  const char* name;
  int num_arguments;
  Dart_NativeFunction function;
};


static VmServiceNativeEntry _VmServiceNativeEntries[] = {
  {"SendServiceMessage", 3, SendServiceMessage}
};


static Dart_NativeFunction VmServiceNativeResolver(Dart_Handle name,
                                                   int num_arguments) {
  const Object& obj = Object::Handle(Api::UnwrapHandle(name));
  if (!obj.IsString()) {
    return NULL;
  }
  const char* function_name = obj.ToCString();
  ASSERT(function_name != NULL);
  intptr_t n =
      sizeof(_VmServiceNativeEntries) / sizeof(_VmServiceNativeEntries[0]);
  for (intptr_t i = 0; i < n; i++) {
    VmServiceNativeEntry entry = _VmServiceNativeEntries[i];
    if (!strcmp(function_name, entry.name) &&
        (num_arguments == entry.num_arguments)) {
      return entry.function;
    }
  }
  return NULL;
}

}  // namespace bin
}  // namespace dart
