// Copyright (c) 2015, 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_dartium.h"

#include "bin/builtin.h"
#include "bin/dartutils.h"
#include "bin/eventhandler.h"
#include "bin/platform.h"
#include "bin/thread.h"
#include "bin/vmservice_impl.h"

namespace dart {
namespace bin {

#define CHECK_RESULT(result)                                                   \
  if (Dart_IsError(result)) {                                                  \
    fprintf(stderr, "CHECK_RESULT failed: %s", Dart_GetError(result));         \
    Dart_ExitScope();                                                          \
    Dart_ShutdownIsolate();                                                    \
    return 0;                                                                  \
  }                                                                            \



// isolate_snapshot_buffer points to a snapshot if we link in a snapshot
// otherwise it is initialized to NULL.
extern const uint8_t* isolate_snapshot_buffer;

static const char* DEFAULT_VM_SERVICE_SERVER_IP = "127.0.0.1";
static const int DEFAULT_VM_SERVICE_SERVER_PORT = 0;

void VmServiceServer::Bootstrap() {
  if (!Platform::Initialize()) {
    fprintf(stderr, "Platform::Initialize() failed\n");
  }
  DartUtils::SetOriginalWorkingDirectory();
  Thread::InitOnce();
  EventHandler::Start();
}


Dart_Isolate VmServiceServer::CreateIsolate() {
  ASSERT(isolate_snapshot_buffer != NULL);
  // Create the isolate.
  char* error = 0;
  Dart_Isolate isolate = Dart_CreateIsolate(DART_VM_SERVICE_ISOLATE_NAME,
                                            "main",
                                            dart::bin::isolate_snapshot_buffer,
                                            NULL,
                                            &error);
  if (!isolate) {
    fprintf(stderr, "Dart_CreateIsolate failed: %s\n", error);
    return 0;
  }

  Dart_EnterScope();
  Builtin::SetNativeResolver(Builtin::kBuiltinLibrary);
  Builtin::SetNativeResolver(Builtin::kIOLibrary);

  Dart_Handle builtin_lib =
      Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
  CHECK_RESULT(builtin_lib);

  Dart_Handle result;

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

  ASSERT(Dart_IsServiceIsolate(isolate));
  if (!VmService::Setup(DEFAULT_VM_SERVICE_SERVER_IP,
                        DEFAULT_VM_SERVICE_SERVER_PORT)) {
    fprintf(stderr,
            "Vmservice::Setup failed: %s\n", VmService::GetErrorMessage());
    isolate = NULL;
  }
  Dart_ExitScope();
  Dart_ExitIsolate();
  return isolate;
}


const char* VmServiceServer::GetServerIP() {
  return VmService::GetServerIP();
}


intptr_t VmServiceServer::GetServerPort() {
  return VmService::GetServerPort();
}


/* DISALLOW_ALLOCATION */
void VmServiceServer::operator delete(void* pointer)  {
  fprintf(stderr, "unreachable code\n");
  abort();
}

}  // namespace bin
}  // namespace dart
