// Copyright (c) 2012, 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 "platform/assert.h"
#include "vm/bootstrap_natives.h"
#include "vm/class_finalizer.h"
#include "vm/dart.h"
#include "vm/dart_api_impl.h"
#include "vm/dart_entry.h"
#include "vm/exceptions.h"
#include "vm/longjump.h"
#include "vm/message_handler.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/port.h"
#include "vm/resolver.h"
#include "vm/snapshot.h"
#include "vm/symbols.h"
#include "vm/thread.h"

namespace dart {

class IsolateStartData {
 public:
  IsolateStartData(char* library_url,
                   char* class_name,
                   intptr_t port_id)
      : library_url_(library_url),
        class_name_(class_name),
        port_id_(port_id) {}

  char* library_url_;
  char* class_name_;
  intptr_t port_id_;
};


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 StoreError(Isolate* isolate, const Object& obj) {
  ASSERT(obj.IsError());
  Error& error = Error::Handle();
  error ^= obj.raw();
  isolate->object_store()->set_sticky_error(error);
}


// TODO(turnidge): Move to DartLibraryCalls.
static RawObject* ReceivePortCreate(intptr_t port_id) {
  Isolate* isolate = Isolate::Current();
  Function& func =
      Function::Handle(isolate,
                       isolate->object_store()->receive_port_create_function());
  const int kNumArguments = 1;
  if (func.IsNull()) {
    Library& isolate_lib = Library::Handle(Library::IsolateLibrary());
    ASSERT(!isolate_lib.IsNull());
    const String& class_name =
        String::Handle(isolate_lib.PrivateName(Symbols::_ReceivePortImpl()));
    func = Resolver::ResolveStatic(isolate_lib,
                                   class_name,
                                   Symbols::_get_or_create(),
                                   kNumArguments,
                                   Object::empty_array(),
                                   Resolver::kIsQualified);
    isolate->object_store()->set_receive_port_create_function(func);
  }
  const Array& args = Array::Handle(isolate, Array::New(kNumArguments));
  args.SetAt(0, Integer::Handle(isolate, Integer::New(port_id)));
  const Object& result =
      Object::Handle(isolate, DartEntry::InvokeStatic(func, args));
  if (!result.IsError()) {
    PortMap::SetLive(port_id);
  }
  return result.raw();
}


static void ShutdownIsolate(uword parameter) {
  Isolate* isolate = reinterpret_cast<Isolate*>(parameter);
  {
    // Print the error if there is one.  This may execute dart code to
    // print the exception object, so we need to use a StartIsolateScope.
    StartIsolateScope start_scope(isolate);
    StackZone zone(isolate);
    HandleScope handle_scope(isolate);
    Error& error = Error::Handle();
    error = isolate->object_store()->sticky_error();
    if (!error.IsNull()) {
      OS::PrintErr("in ShutdownIsolate: %s\n", error.ToErrorCString());
    }
  }
  {
    // Shut the isolate down.
    SwitchIsolateScope switch_scope(isolate);
    Dart::ShutdownIsolate();
  }
}


static char* GetRootScriptUri(Isolate* isolate) {
  const Library& library =
      Library::Handle(isolate->object_store()->root_library());
  ASSERT(!library.IsNull());
  const String& script_name = String::Handle(library.url());
  return isolate->current_zone()->MakeCopyOfString(script_name.ToCString());
}


DEFINE_NATIVE_ENTRY(ReceivePortImpl_factory, 1) {
  ASSERT(AbstractTypeArguments::CheckedHandle(
      arguments->NativeArgAt(0)).IsNull());
  intptr_t port_id =
      PortMap::CreatePort(arguments->isolate()->message_handler());
  const Object& port = Object::Handle(ReceivePortCreate(port_id));
  if (port.IsError()) {
    Exceptions::PropagateError(Error::Cast(port));
  }
  return port.raw();
}


DEFINE_NATIVE_ENTRY(ReceivePortImpl_closeInternal, 1) {
  GET_NON_NULL_NATIVE_ARGUMENT(Smi, id, arguments->NativeArgAt(0));
  PortMap::ClosePort(id.Value());
  return Object::null();
}


DEFINE_NATIVE_ENTRY(SendPortImpl_sendInternal_, 3) {
  GET_NON_NULL_NATIVE_ARGUMENT(Smi, send_id, arguments->NativeArgAt(0));
  GET_NON_NULL_NATIVE_ARGUMENT(Smi, reply_id, arguments->NativeArgAt(1));
  // TODO(iposva): Allow for arbitrary messages to be sent.
  GET_NON_NULL_NATIVE_ARGUMENT(Instance, obj, arguments->NativeArgAt(2));

  uint8_t* data = NULL;
  MessageWriter writer(&data, &allocator);
  writer.WriteMessage(obj);

  // TODO(turnidge): Throw an exception when the return value is false?
  PortMap::PostMessage(new Message(send_id.Value(), reply_id.Value(),
                                   data, writer.BytesWritten(),
                                   Message::kNormalPriority));
  return Object::null();
}


static void ThrowIllegalArgException(const String& message) {
  const Array& args = Array::Handle(Array::New(1));
  args.SetAt(0, message);
  Exceptions::ThrowByType(Exceptions::kArgument, args);
}


static void ThrowIsolateSpawnException(const String& message) {
  const Array& args = Array::Handle(Array::New(1));
  args.SetAt(0, message);
  Exceptions::ThrowByType(Exceptions::kIsolateSpawn, args);
}


static bool CanonicalizeUri(Isolate* isolate,
                            const Library& library,
                            const String& uri,
                            char** canonical_uri,
                            char** error) {
  Zone* zone = isolate->current_zone();
  Dart_LibraryTagHandler handler = isolate->library_tag_handler();
  if (handler == NULL) {
    *error = zone->PrintToString(
        "Unable to canonicalize uri '%s': no library tag handler found.",
        uri.ToCString());
    return false;
  }
  Dart_Handle result = handler(kCanonicalizeUrl,
                               Api::NewHandle(isolate, library.raw()),
                               Api::NewHandle(isolate, uri.raw()));
  const Object& obj = Object::Handle(Api::UnwrapHandle(result));
  if (obj.IsError()) {
    Error& error_obj = Error::Handle();
    error_obj ^= obj.raw();
    *error = zone->PrintToString("Unable to canonicalize uri '%s': %s",
                                 uri.ToCString(), error_obj.ToErrorCString());
    return false;
  } else if (obj.IsString()) {
    String& string_obj = String::Handle();
    string_obj ^= obj.raw();
    *canonical_uri = zone->MakeCopyOfString(string_obj.ToCString());
    return true;
  } else {
    *error = zone->PrintToString("Unable to canonicalize uri '%s': "
                                 "library tag handler returned wrong type",
                                 uri.ToCString());
    return false;
  }
}


class SpawnState {
 public:
  SpawnState(const Function& func, const Function& callback_func)
      : isolate_(NULL),
        script_url_(NULL),
        library_url_(NULL),
        function_name_(NULL),
        exception_callback_name_(NULL) {
    script_url_ = strdup(GetRootScriptUri(Isolate::Current()));
    const Class& cls = Class::Handle(func.Owner());
    ASSERT(cls.IsTopLevel());
    const Library& lib = Library::Handle(cls.library());
    const String& lib_url = String::Handle(lib.url());
    library_url_ = strdup(lib_url.ToCString());

    const String& func_name = String::Handle(func.name());
    function_name_ = strdup(func_name.ToCString());
    if (!callback_func.IsNull()) {
      const String& callback_name = String::Handle(callback_func.name());
      exception_callback_name_ = strdup(callback_name.ToCString());
    } else {
      exception_callback_name_ = strdup("_unhandledExceptionCallback");
    }
  }

  explicit SpawnState(const char* script_url)
      : isolate_(NULL),
        library_url_(NULL),
        function_name_(NULL),
        exception_callback_name_(NULL) {
    script_url_ = strdup(script_url);
    library_url_ = NULL;
    function_name_ = strdup("main");
    exception_callback_name_ = strdup("_unhandledExceptionCallback");
  }

  ~SpawnState() {
    free(script_url_);
    free(library_url_);
    free(function_name_);
    free(exception_callback_name_);
  }

  Isolate* isolate() const { return isolate_; }
  void set_isolate(Isolate* value) { isolate_ = value; }
  char* script_url() const { return script_url_; }
  char* library_url() const { return library_url_; }
  char* function_name() const { return function_name_; }
  char* exception_callback_name() const { return exception_callback_name_; }

  RawObject* ResolveFunction() {
    // Resolve the library.
    Library& lib = Library::Handle();
    if (library_url()) {
      const String& lib_url = String::Handle(String::New(library_url()));
      lib = Library::LookupLibrary(lib_url);
      if (lib.IsNull() || lib.IsError()) {
        const String& msg = String::Handle(String::NewFormatted(
            "Unable to find library '%s'.", library_url()));
        return LanguageError::New(msg);
      }
    } else {
      lib = isolate()->object_store()->root_library();
    }
    ASSERT(!lib.IsNull());

    // Resolve the function.
    const String& func_name =
        String::Handle(String::New(function_name()));
    const Function& func = Function::Handle(lib.LookupLocalFunction(func_name));
    if (func.IsNull()) {
      const String& msg = String::Handle(String::NewFormatted(
          "Unable to resolve function '%s' in library '%s'.",
          function_name(), (library_url() ? library_url() : script_url())));
      return LanguageError::New(msg);
    }
    return func.raw();
  }

  void Cleanup() {
    SwitchIsolateScope switch_scope(isolate());
    Dart::ShutdownIsolate();
  }

 private:
  Isolate* isolate_;
  char* script_url_;
  char* library_url_;
  char* function_name_;
  char* exception_callback_name_;
};


static bool CreateIsolate(SpawnState* state, char** error) {
  Isolate* parent_isolate = Isolate::Current();

  Dart_IsolateCreateCallback callback = Isolate::CreateCallback();
  if (callback == NULL) {
    *error = strdup("Null callback specified for isolate creation\n");
    Isolate::SetCurrent(parent_isolate);
    return false;
  }

  void* init_data = parent_isolate->init_callback_data();
  bool retval = (callback)(state->script_url(),
                           state->function_name(),
                           init_data,
                           error);
  if (!retval) {
    Isolate::SetCurrent(parent_isolate);
    return false;
  }

  Isolate* child_isolate = Isolate::Current();
  ASSERT(child_isolate);
  state->set_isolate(child_isolate);

  // Attempt to resolve the entry function now, so that we fail fast
  // in the case that the function cannot be resolved.
  //
  // TODO(turnidge): Revisit this once we have an isolate death api.
  bool resolve_error = false;
  {
    StackZone zone(child_isolate);
    HandleScope handle_scope(child_isolate);
    const Object& result = Object::Handle(state->ResolveFunction());
    if (result.IsError()) {
      Error& errobj = Error::Handle();
      errobj ^= result.raw();
      *error = strdup(errobj.ToErrorCString());
      resolve_error = true;
    } else {
      const String& callback_name =
          String::Handle(child_isolate,
                         String::New(state->exception_callback_name()));
      child_isolate->object_store()->
          set_unhandled_exception_handler(callback_name);
    }
  }
  if (resolve_error) {
    Dart::ShutdownIsolate();
    Isolate::SetCurrent(parent_isolate);
    return false;
  }

  Isolate::SetCurrent(parent_isolate);
  return true;
}


static bool RunIsolate(uword parameter) {
  Isolate* isolate = reinterpret_cast<Isolate*>(parameter);
  SpawnState* state = reinterpret_cast<SpawnState*>(isolate->spawn_data());
  isolate->set_spawn_data(0);
  {
    StartIsolateScope start_scope(isolate);
    StackZone zone(isolate);
    HandleScope handle_scope(isolate);
    if (!ClassFinalizer::FinalizePendingClasses()) {
      // Error is in sticky error already.
      return false;
    }

    Object& result = Object::Handle();
    result = state->ResolveFunction();
    delete state;
    state = NULL;
    if (result.IsError()) {
      StoreError(isolate, result);
      return false;
    }
    ASSERT(result.IsFunction());
    Function& func = Function::Handle(isolate);
    func ^= result.raw();
    result = DartEntry::InvokeStatic(func, Object::empty_array());
    if (result.IsError()) {
      StoreError(isolate, result);
      return false;
    }
  }
  return true;
}


static RawObject* Spawn(NativeArguments* arguments, SpawnState* state) {
  // Create a new isolate.
  char* error = NULL;
  if (!CreateIsolate(state, &error)) {
    delete state;
    const String& msg = String::Handle(String::New(error));
    free(error);
    ThrowIsolateSpawnException(msg);
  }

  // Try to create a SendPort for the new isolate.
  const Object& port = Object::Handle(
      DartLibraryCalls::NewSendPort(state->isolate()->main_port()));
  if (port.IsError()) {
    state->Cleanup();
    delete state;
    Exceptions::PropagateError(Error::Cast(port));
  }

  // Start the new isolate.
  state->isolate()->set_spawn_data(reinterpret_cast<uword>(state));
  state->isolate()->message_handler()->Run(
      Dart::thread_pool(), RunIsolate, ShutdownIsolate,
      reinterpret_cast<uword>(state->isolate()));

  return port.raw();
}


DEFINE_NATIVE_ENTRY(isolate_spawnFunction, 2) {
  GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(0));
  bool throw_exception = false;
  Function& func = Function::Handle();
  if (closure.IsClosure()) {
    func ^= Closure::function(closure);
    const Class& cls = Class::Handle(func.Owner());
    if (!func.IsClosureFunction() || !func.is_static() || !cls.IsTopLevel()) {
      throw_exception = true;
    }
  } else {
    throw_exception = true;
  }
  if (throw_exception) {
    const String& msg = String::Handle(String::New(
        "spawnFunction expects to be passed a closure to a top-level static "
        "function"));
    ThrowIllegalArgException(msg);
  }

  GET_NATIVE_ARGUMENT(Instance, callback, arguments->NativeArgAt(1));
  Function& callback_func = Function::Handle();
  if (callback.IsClosure()) {
    callback_func ^= Closure::function(callback);
    const Class& cls = Class::Handle(callback_func.Owner());
    if (!callback_func.IsClosureFunction() || !callback_func.is_static() ||
        !cls.IsTopLevel()) {
      throw_exception = true;
    }
  } else if (!callback.IsNull()) {
    throw_exception = true;
  }
  if (throw_exception) {
    const String& msg = String::Handle(String::New(
        "spawnFunction expects to be passed either a unhandled exception "
        "callback to a top-level static function, or null"));
    ThrowIllegalArgException(msg);
  }

#if defined(DEBUG)
  Context& ctx = Context::Handle();
  ctx = Closure::context(closure);
  ASSERT(ctx.num_variables() == 0);
  if (!callback.IsNull()) {
    ctx = Closure::context(callback);
    ASSERT(ctx.num_variables() == 0);
  }
#endif

  return Spawn(arguments, new SpawnState(func, callback_func));
}


DEFINE_NATIVE_ENTRY(isolate_spawnUri, 1) {
  GET_NON_NULL_NATIVE_ARGUMENT(String, uri, arguments->NativeArgAt(0));

  // Canonicalize the uri with respect to the current isolate.
  char* error = NULL;
  char* canonical_uri = NULL;
  const Library& root_lib =
      Library::Handle(arguments->isolate()->object_store()->root_library());
  if (!CanonicalizeUri(arguments->isolate(), root_lib, uri,
                       &canonical_uri, &error)) {
    const String& msg = String::Handle(String::New(error));
    free(error);
    ThrowIsolateSpawnException(msg);
  }

  return Spawn(arguments, new SpawnState(canonical_uri));
}


DEFINE_NATIVE_ENTRY(isolate_getPortInternal, 0) {
  const Object& port = Object::Handle(ReceivePortCreate(isolate->main_port()));
  if (port.IsError()) {
    Exceptions::PropagateError(Error::Cast(port));
  }
  return port.raw();
}

}  // namespace dart
