// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#if !defined(_WIN32) && !defined(_WIN64)
#include <unistd.h>  // NOLINT
#endif               // !defined(_WIN32) && !defined(_WIN64)

#include <locale.h>
#include <string>
#include <vector>

#include "include/libplatform/libplatform.h"
#include "include/v8.h"

#include "src/base/platform/platform.h"
#include "src/flags/flags.h"
#include "src/heap/read-only-heap.h"
#include "src/utils/utils.h"
#include "src/utils/vector.h"

#include "test/inspector/isolate-data.h"
#include "test/inspector/task-runner.h"

namespace v8 {
namespace internal {

extern void DisableEmbeddedBlobRefcounting();
extern void FreeCurrentEmbeddedBlob();

extern v8::StartupData CreateSnapshotDataBlobInternal(
    v8::SnapshotCreator::FunctionCodeHandling function_code_handling,
    const char* embedded_source, v8::Isolate* isolate);
extern v8::StartupData WarmUpSnapshotDataBlobInternal(
    v8::StartupData cold_snapshot_blob, const char* warmup_source);

}  // namespace internal
}  // namespace v8

namespace {

std::vector<TaskRunner*> task_runners;

void Terminate() {
  for (size_t i = 0; i < task_runners.size(); ++i) {
    task_runners[i]->Terminate();
    task_runners[i]->Join();
  }
  std::vector<TaskRunner*> empty;
  task_runners.swap(empty);
}

void Exit() {
  fflush(stdout);
  fflush(stderr);
  Terminate();
}

std::vector<uint16_t> ToVector(v8::Isolate* isolate,
                               v8::Local<v8::String> str) {
  std::vector<uint16_t> buffer(str->Length());
  str->Write(isolate, buffer.data(), 0, str->Length());
  return buffer;
}

std::vector<uint8_t> ToBytes(v8::Isolate* isolate, v8::Local<v8::String> str) {
  std::vector<uint8_t> buffer(str->Length());
  str->WriteOneByte(isolate, buffer.data(), 0, str->Length());
  return buffer;
}

v8::Local<v8::String> ToV8String(v8::Isolate* isolate, const char* str) {
  return v8::String::NewFromUtf8(isolate, str, v8::NewStringType::kNormal)
      .ToLocalChecked();
}

v8::Local<v8::String> ToV8String(v8::Isolate* isolate,
                                 const std::vector<uint8_t>& bytes) {
  return v8::String::NewFromOneByte(isolate, bytes.data(),
                                    v8::NewStringType::kNormal,
                                    static_cast<int>(bytes.size()))
      .ToLocalChecked();
}

v8::Local<v8::String> ToV8String(v8::Isolate* isolate,
                                 const std::string& buffer) {
  int length = static_cast<int>(buffer.size());
  return v8::String::NewFromUtf8(isolate, buffer.data(),
                                 v8::NewStringType::kNormal, length)
      .ToLocalChecked();
}

v8::Local<v8::String> ToV8String(v8::Isolate* isolate,
                                 const std::vector<uint16_t>& buffer) {
  int length = static_cast<int>(buffer.size());
  return v8::String::NewFromTwoByte(isolate, buffer.data(),
                                    v8::NewStringType::kNormal, length)
      .ToLocalChecked();
}

std::vector<uint16_t> ToVector(const v8_inspector::StringView& string) {
  std::vector<uint16_t> buffer(string.length());
  for (size_t i = 0; i < string.length(); i++) {
    if (string.is8Bit())
      buffer[i] = string.characters8()[i];
    else
      buffer[i] = string.characters16()[i];
  }
  return buffer;
}

class FrontendChannelImpl : public v8_inspector::V8Inspector::Channel {
 public:
  FrontendChannelImpl(TaskRunner* task_runner, int context_group_id,
                      v8::Isolate* isolate, v8::Local<v8::Function> function)
      : task_runner_(task_runner),
        context_group_id_(context_group_id),
        function_(isolate, function) {}
  ~FrontendChannelImpl() override = default;

  void set_session_id(int session_id) { session_id_ = session_id; }

 private:
  void sendResponse(
      int callId,
      std::unique_ptr<v8_inspector::StringBuffer> message) override {
    task_runner_->Append(
        new SendMessageTask(this, ToVector(message->string())));
  }
  void sendNotification(
      std::unique_ptr<v8_inspector::StringBuffer> message) override {
    task_runner_->Append(
        new SendMessageTask(this, ToVector(message->string())));
  }
  void flushProtocolNotifications() override {}

  class SendMessageTask : public TaskRunner::Task {
   public:
    SendMessageTask(FrontendChannelImpl* channel,
                    const std::vector<uint16_t>& message)
        : channel_(channel), message_(message) {}
    ~SendMessageTask() override = default;
    bool is_priority_task() final { return false; }

   private:
    void Run(IsolateData* data) override {
      v8::MicrotasksScope microtasks_scope(data->isolate(),
                                           v8::MicrotasksScope::kRunMicrotasks);
      v8::HandleScope handle_scope(data->isolate());
      v8::Local<v8::Context> context =
          data->GetContext(channel_->context_group_id_);
      v8::Context::Scope context_scope(context);
      v8::Local<v8::Value> message = ToV8String(data->isolate(), message_);
      v8::MaybeLocal<v8::Value> result;
      result = channel_->function_.Get(data->isolate())
                   ->Call(context, context->Global(), 1, &message);
    }
    FrontendChannelImpl* channel_;
    std::vector<uint16_t> message_;
  };

  TaskRunner* task_runner_;
  int context_group_id_;
  v8::Global<v8::Function> function_;
  int session_id_;
  DISALLOW_COPY_AND_ASSIGN(FrontendChannelImpl);
};

template <typename T>
void RunSyncTask(TaskRunner* task_runner, T callback) {
  class SyncTask : public TaskRunner::Task {
   public:
    SyncTask(v8::base::Semaphore* ready_semaphore, T callback)
        : ready_semaphore_(ready_semaphore), callback_(callback) {}
    ~SyncTask() override = default;
    bool is_priority_task() final { return true; }

   private:
    void Run(IsolateData* data) override {
      callback_(data);
      if (ready_semaphore_) ready_semaphore_->Signal();
    }

    v8::base::Semaphore* ready_semaphore_;
    T callback_;
  };

  v8::base::Semaphore ready_semaphore(0);
  task_runner->Append(new SyncTask(&ready_semaphore, callback));
  ready_semaphore.Wait();
}

class SendMessageToBackendTask : public TaskRunner::Task {
 public:
  SendMessageToBackendTask(int session_id, const std::vector<uint16_t>& message)
      : session_id_(session_id), message_(message) {}
  bool is_priority_task() final { return true; }

 private:
  void Run(IsolateData* data) override {
    v8_inspector::StringView message_view(message_.data(), message_.size());
    data->SendMessage(session_id_, message_view);
  }

  int session_id_;
  std::vector<uint16_t> message_;
};

void RunAsyncTask(TaskRunner* task_runner,
                  const v8_inspector::StringView& task_name,
                  TaskRunner::Task* task) {
  class AsyncTask : public TaskRunner::Task {
   public:
    explicit AsyncTask(TaskRunner::Task* inner) : inner_(inner) {}
    ~AsyncTask() override = default;
    bool is_priority_task() override { return inner_->is_priority_task(); }
    void Run(IsolateData* data) override {
      data->AsyncTaskStarted(inner_.get());
      inner_->Run(data);
      data->AsyncTaskFinished(inner_.get());
    }

   private:
    std::unique_ptr<TaskRunner::Task> inner_;
    DISALLOW_COPY_AND_ASSIGN(AsyncTask);
  };

  task_runner->data()->AsyncTaskScheduled(task_name, task, false);
  task_runner->Append(new AsyncTask(task));
}

class ExecuteStringTask : public TaskRunner::Task {
 public:
  ExecuteStringTask(v8::Isolate* isolate, int context_group_id,
                    const std::vector<uint16_t>& expression,
                    v8::Local<v8::String> name,
                    v8::Local<v8::Integer> line_offset,
                    v8::Local<v8::Integer> column_offset,
                    v8::Local<v8::Boolean> is_module)
      : expression_(expression),
        name_(ToVector(isolate, name)),
        line_offset_(line_offset.As<v8::Int32>()->Value()),
        column_offset_(column_offset.As<v8::Int32>()->Value()),
        is_module_(is_module->Value()),
        context_group_id_(context_group_id) {}
  ExecuteStringTask(const std::string& expression, int context_group_id)
      : expression_utf8_(expression), context_group_id_(context_group_id) {}

  ~ExecuteStringTask() override = default;
  bool is_priority_task() override { return false; }
  void Run(IsolateData* data) override {
    v8::MicrotasksScope microtasks_scope(data->isolate(),
                                         v8::MicrotasksScope::kRunMicrotasks);
    v8::HandleScope handle_scope(data->isolate());
    v8::Local<v8::Context> context = data->GetContext(context_group_id_);
    v8::Context::Scope context_scope(context);
    v8::ScriptOrigin origin(
        ToV8String(data->isolate(), name_),
        v8::Integer::New(data->isolate(), line_offset_),
        v8::Integer::New(data->isolate(), column_offset_),
        /* resource_is_shared_cross_origin */ v8::Local<v8::Boolean>(),
        /* script_id */ v8::Local<v8::Integer>(),
        /* source_map_url */ v8::Local<v8::Value>(),
        /* resource_is_opaque */ v8::Local<v8::Boolean>(),
        /* is_wasm */ v8::Local<v8::Boolean>(),
        v8::Boolean::New(data->isolate(), is_module_));
    v8::Local<v8::String> source;
    if (expression_.size() != 0)
      source = ToV8String(data->isolate(), expression_);
    else
      source = ToV8String(data->isolate(), expression_utf8_);

    v8::ScriptCompiler::Source scriptSource(source, origin);
    v8::Isolate::SafeForTerminationScope allowTermination(data->isolate());
    if (!is_module_) {
      v8::Local<v8::Script> script;
      if (!v8::ScriptCompiler::Compile(context, &scriptSource).ToLocal(&script))
        return;
      v8::MaybeLocal<v8::Value> result;
      result = script->Run(context);
    } else {
      // Register Module takes ownership of {buffer}, so we need to make a copy.
      int length = static_cast<int>(name_.size());
      v8::internal::Vector<uint16_t> buffer =
          v8::internal::Vector<uint16_t>::New(length);
      std::copy(name_.begin(), name_.end(), buffer.begin());
      data->RegisterModule(context, buffer, &scriptSource);
    }
  }

 private:
  std::vector<uint16_t> expression_;
  std::string expression_utf8_;
  std::vector<uint16_t> name_;
  int32_t line_offset_ = 0;
  int32_t column_offset_ = 0;
  bool is_module_ = false;
  int context_group_id_;

  DISALLOW_COPY_AND_ASSIGN(ExecuteStringTask);
};

class UtilsExtension : public IsolateData::SetupGlobalTask {
 public:
  ~UtilsExtension() override = default;
  void Run(v8::Isolate* isolate,
           v8::Local<v8::ObjectTemplate> global) override {
    v8::Local<v8::ObjectTemplate> utils = v8::ObjectTemplate::New(isolate);
    utils->Set(ToV8String(isolate, "print"),
               v8::FunctionTemplate::New(isolate, &UtilsExtension::Print));
    utils->Set(ToV8String(isolate, "quit"),
               v8::FunctionTemplate::New(isolate, &UtilsExtension::Quit));
    utils->Set(ToV8String(isolate, "setlocale"),
               v8::FunctionTemplate::New(isolate, &UtilsExtension::Setlocale));
    utils->Set(ToV8String(isolate, "read"),
               v8::FunctionTemplate::New(isolate, &UtilsExtension::Read));
    utils->Set(ToV8String(isolate, "load"),
               v8::FunctionTemplate::New(isolate, &UtilsExtension::Load));
    utils->Set(ToV8String(isolate, "compileAndRunWithOrigin"),
               v8::FunctionTemplate::New(
                   isolate, &UtilsExtension::CompileAndRunWithOrigin));
    utils->Set(ToV8String(isolate, "setCurrentTimeMSForTest"),
               v8::FunctionTemplate::New(
                   isolate, &UtilsExtension::SetCurrentTimeMSForTest));
    utils->Set(ToV8String(isolate, "setMemoryInfoForTest"),
               v8::FunctionTemplate::New(
                   isolate, &UtilsExtension::SetMemoryInfoForTest));
    utils->Set(ToV8String(isolate, "schedulePauseOnNextStatement"),
               v8::FunctionTemplate::New(
                   isolate, &UtilsExtension::SchedulePauseOnNextStatement));
    utils->Set(ToV8String(isolate, "cancelPauseOnNextStatement"),
               v8::FunctionTemplate::New(
                   isolate, &UtilsExtension::CancelPauseOnNextStatement));
    utils->Set(ToV8String(isolate, "setLogConsoleApiMessageCalls"),
               v8::FunctionTemplate::New(
                   isolate, &UtilsExtension::SetLogConsoleApiMessageCalls));
    utils->Set(
        ToV8String(isolate, "setLogMaxAsyncCallStackDepthChanged"),
        v8::FunctionTemplate::New(
            isolate, &UtilsExtension::SetLogMaxAsyncCallStackDepthChanged));
    utils->Set(ToV8String(isolate, "createContextGroup"),
               v8::FunctionTemplate::New(isolate,
                                         &UtilsExtension::CreateContextGroup));
    utils->Set(
        ToV8String(isolate, "resetContextGroup"),
        v8::FunctionTemplate::New(isolate, &UtilsExtension::ResetContextGroup));
    utils->Set(
        ToV8String(isolate, "connectSession"),
        v8::FunctionTemplate::New(isolate, &UtilsExtension::ConnectSession));
    utils->Set(
        ToV8String(isolate, "disconnectSession"),
        v8::FunctionTemplate::New(isolate, &UtilsExtension::DisconnectSession));
    utils->Set(ToV8String(isolate, "sendMessageToBackend"),
               v8::FunctionTemplate::New(
                   isolate, &UtilsExtension::SendMessageToBackend));
    global->Set(ToV8String(isolate, "utils"), utils);
  }

  static void set_backend_task_runner(TaskRunner* runner) {
    backend_runner_ = runner;
  }

  static void ClearAllSessions() { channels_.clear(); }

 private:
  static TaskRunner* backend_runner_;

  static void Print(const v8::FunctionCallbackInfo<v8::Value>& args) {
    for (int i = 0; i < args.Length(); i++) {
      v8::HandleScope handle_scope(args.GetIsolate());
      if (i != 0) {
        printf(" ");
      }

      // Explicitly catch potential exceptions in toString().
      v8::TryCatch try_catch(args.GetIsolate());
      v8::Local<v8::Value> arg = args[i];
      v8::Local<v8::String> str_obj;

      if (arg->IsSymbol()) {
        arg = v8::Local<v8::Symbol>::Cast(arg)->Name();
      }
      if (!arg->ToString(args.GetIsolate()->GetCurrentContext())
               .ToLocal(&str_obj)) {
        try_catch.ReThrow();
        return;
      }

      v8::String::Utf8Value str(args.GetIsolate(), str_obj);
      int n =
          static_cast<int>(fwrite(*str, sizeof(**str), str.length(), stdout));
      if (n != str.length()) {
        printf("Error in fwrite\n");
        Quit(args);
      }
    }
    printf("\n");
    fflush(stdout);
  }

  static void Quit(const v8::FunctionCallbackInfo<v8::Value>& args) { Exit(); }

  static void Setlocale(const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 1 || !args[0]->IsString()) {
      fprintf(stderr, "Internal error: setlocale get one string argument.");
      Exit();
    }

    v8::String::Utf8Value str(args.GetIsolate(), args[1]);
    setlocale(LC_NUMERIC, *str);
  }

  static bool ReadFile(v8::Isolate* isolate, v8::Local<v8::Value> name,
                       std::string* chars) {
    v8::String::Utf8Value str(isolate, name);
    bool exists = false;
    std::string filename(*str, str.length());
    *chars = v8::internal::ReadFile(filename.c_str(), &exists);
    if (!exists) {
      isolate->ThrowException(ToV8String(isolate, "Error reading file"));
      return false;
    }
    return true;
  }

  static void Read(const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 1 || !args[0]->IsString()) {
      fprintf(stderr, "Internal error: read gets one string argument.");
      Exit();
    }
    std::string chars;
    v8::Isolate* isolate = args.GetIsolate();
    if (ReadFile(isolate, args[0], &chars)) {
      args.GetReturnValue().Set(ToV8String(isolate, chars));
    }
  }

  static void Load(const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 1 || !args[0]->IsString()) {
      fprintf(stderr, "Internal error: load gets one string argument.");
      Exit();
    }
    std::string chars;
    v8::Isolate* isolate = args.GetIsolate();
    v8::Local<v8::Context> context = isolate->GetCurrentContext();
    IsolateData* data = IsolateData::FromContext(context);
    int context_group_id = data->GetContextGroupId(context);
    if (ReadFile(isolate, args[0], &chars)) {
      ExecuteStringTask(chars, context_group_id).Run(data);
    }
  }

  static void CompileAndRunWithOrigin(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 6 || !args[0]->IsInt32() || !args[1]->IsString() ||
        !args[2]->IsString() || !args[3]->IsInt32() || !args[4]->IsInt32() ||
        !args[5]->IsBoolean()) {
      fprintf(stderr,
              "Internal error: compileAndRunWithOrigin(context_group_id, "
              "source, name, line, "
              "column, is_module).");
      Exit();
    }

    backend_runner_->Append(new ExecuteStringTask(
        args.GetIsolate(), args[0].As<v8::Int32>()->Value(),
        ToVector(args.GetIsolate(), args[1].As<v8::String>()),
        args[2].As<v8::String>(), args[3].As<v8::Int32>(),
        args[4].As<v8::Int32>(), args[5].As<v8::Boolean>()));
  }

  static void SetCurrentTimeMSForTest(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 1 || !args[0]->IsNumber()) {
      fprintf(stderr, "Internal error: setCurrentTimeMSForTest(time).");
      Exit();
    }
    backend_runner_->data()->SetCurrentTimeMS(
        args[0].As<v8::Number>()->Value());
  }

  static void SetMemoryInfoForTest(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 1) {
      fprintf(stderr, "Internal error: setMemoryInfoForTest(value).");
      Exit();
    }
    backend_runner_->data()->SetMemoryInfo(args[0]);
  }

  static void SchedulePauseOnNextStatement(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 3 || !args[0]->IsInt32() || !args[1]->IsString() ||
        !args[2]->IsString()) {
      fprintf(stderr,
              "Internal error: schedulePauseOnNextStatement(context_group_id, "
              "'reason', 'details').");
      Exit();
    }
    std::vector<uint16_t> reason =
        ToVector(args.GetIsolate(), args[1].As<v8::String>());
    std::vector<uint16_t> details =
        ToVector(args.GetIsolate(), args[2].As<v8::String>());
    int context_group_id = args[0].As<v8::Int32>()->Value();
    RunSyncTask(backend_runner_,
                [&context_group_id, &reason, &details](IsolateData* data) {
                  data->SchedulePauseOnNextStatement(
                      context_group_id,
                      v8_inspector::StringView(reason.data(), reason.size()),
                      v8_inspector::StringView(details.data(), details.size()));
                });
  }

  static void CancelPauseOnNextStatement(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 1 || !args[0]->IsInt32()) {
      fprintf(stderr,
              "Internal error: cancelPauseOnNextStatement(context_group_id).");
      Exit();
    }
    int context_group_id = args[0].As<v8::Int32>()->Value();
    RunSyncTask(backend_runner_, [&context_group_id](IsolateData* data) {
      data->CancelPauseOnNextStatement(context_group_id);
    });
  }

  static void SetLogConsoleApiMessageCalls(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 1 || !args[0]->IsBoolean()) {
      fprintf(stderr, "Internal error: setLogConsoleApiMessageCalls(bool).");
      Exit();
    }
    backend_runner_->data()->SetLogConsoleApiMessageCalls(
        args[0].As<v8::Boolean>()->Value());
  }

  static void SetLogMaxAsyncCallStackDepthChanged(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 1 || !args[0]->IsBoolean()) {
      fprintf(stderr,
              "Internal error: setLogMaxAsyncCallStackDepthChanged(bool).");
      Exit();
    }
    backend_runner_->data()->SetLogMaxAsyncCallStackDepthChanged(
        args[0].As<v8::Boolean>()->Value());
  }

  static void CreateContextGroup(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 0) {
      fprintf(stderr, "Internal error: createContextGroup().");
      Exit();
    }
    int context_group_id = 0;
    RunSyncTask(backend_runner_, [&context_group_id](IsolateData* data) {
      context_group_id = data->CreateContextGroup();
    });
    args.GetReturnValue().Set(
        v8::Int32::New(args.GetIsolate(), context_group_id));
  }

  static void ResetContextGroup(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 1 || !args[0]->IsInt32()) {
      fprintf(stderr, "Internal error: resetContextGroup(context_group_id).");
      Exit();
    }
    int context_group_id = args[0].As<v8::Int32>()->Value();
    RunSyncTask(backend_runner_, [&context_group_id](IsolateData* data) {
      data->ResetContextGroup(context_group_id);
    });
  }

  static void ConnectSession(const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 3 || !args[0]->IsInt32() || !args[1]->IsString() ||
        !args[2]->IsFunction()) {
      fprintf(stderr,
              "Internal error: connectionSession(context_group_id, state, "
              "dispatch).");
      Exit();
    }
    v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    FrontendChannelImpl* channel = new FrontendChannelImpl(
        IsolateData::FromContext(context)->task_runner(),
        IsolateData::FromContext(context)->GetContextGroupId(context),
        args.GetIsolate(), args[2].As<v8::Function>());

    std::vector<uint8_t> state =
        ToBytes(args.GetIsolate(), args[1].As<v8::String>());
    int context_group_id = args[0].As<v8::Int32>()->Value();
    int session_id = 0;
    RunSyncTask(backend_runner_, [&context_group_id, &session_id, &channel,
                                  &state](IsolateData* data) {
      session_id = data->ConnectSession(
          context_group_id,
          v8_inspector::StringView(state.data(), state.size()), channel);
      channel->set_session_id(session_id);
    });

    channels_[session_id].reset(channel);
    args.GetReturnValue().Set(v8::Int32::New(args.GetIsolate(), session_id));
  }

  static void DisconnectSession(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 1 || !args[0]->IsInt32()) {
      fprintf(stderr, "Internal error: disconnectionSession(session_id).");
      Exit();
    }
    int session_id = args[0].As<v8::Int32>()->Value();
    std::vector<uint8_t> state;
    RunSyncTask(backend_runner_, [&session_id, &state](IsolateData* data) {
      state = data->DisconnectSession(session_id);
    });
    channels_.erase(session_id);
    args.GetReturnValue().Set(ToV8String(args.GetIsolate(), state));
  }

  static void SendMessageToBackend(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 2 || !args[0]->IsInt32() || !args[1]->IsString()) {
      fprintf(stderr,
              "Internal error: sendMessageToBackend(session_id, message).");
      Exit();
    }
    backend_runner_->Append(new SendMessageToBackendTask(
        args[0].As<v8::Int32>()->Value(),
        ToVector(args.GetIsolate(), args[1].As<v8::String>())));
  }

  static std::map<int, std::unique_ptr<FrontendChannelImpl>> channels_;
};

TaskRunner* UtilsExtension::backend_runner_ = nullptr;
std::map<int, std::unique_ptr<FrontendChannelImpl>> UtilsExtension::channels_;

class SetTimeoutTask : public TaskRunner::Task {
 public:
  SetTimeoutTask(int context_group_id, v8::Isolate* isolate,
                 v8::Local<v8::Function> function)
      : function_(isolate, function), context_group_id_(context_group_id) {}
  ~SetTimeoutTask() override = default;
  bool is_priority_task() final { return false; }

 private:
  void Run(IsolateData* data) override {
    v8::MicrotasksScope microtasks_scope(data->isolate(),
                                         v8::MicrotasksScope::kRunMicrotasks);
    v8::HandleScope handle_scope(data->isolate());
    v8::Local<v8::Context> context = data->GetContext(context_group_id_);
    v8::Context::Scope context_scope(context);

    v8::Local<v8::Function> function = function_.Get(data->isolate());
    v8::MaybeLocal<v8::Value> result;
    result = function->Call(context, context->Global(), 0, nullptr);
  }

  v8::Global<v8::Function> function_;
  int context_group_id_;
};

class SetTimeoutExtension : public IsolateData::SetupGlobalTask {
 public:
  void Run(v8::Isolate* isolate,
           v8::Local<v8::ObjectTemplate> global) override {
    global->Set(
        ToV8String(isolate, "setTimeout"),
        v8::FunctionTemplate::New(isolate, &SetTimeoutExtension::SetTimeout));
  }

 private:
  static void SetTimeout(const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 2 || !args[1]->IsNumber() ||
        (!args[0]->IsFunction() && !args[0]->IsString()) ||
        args[1].As<v8::Number>()->Value() != 0.0) {
      fprintf(
          stderr,
          "Internal error: only setTimeout(function|code, 0) is supported.");
      Exit();
    }
    v8::Isolate* isolate = args.GetIsolate();
    v8::Local<v8::Context> context = isolate->GetCurrentContext();
    IsolateData* data = IsolateData::FromContext(context);
    int context_group_id = data->GetContextGroupId(context);
    const char* task_name = "setTimeout";
    v8_inspector::StringView task_name_view(
        reinterpret_cast<const uint8_t*>(task_name), strlen(task_name));
    if (args[0]->IsFunction()) {
      RunAsyncTask(data->task_runner(), task_name_view,
                   new SetTimeoutTask(context_group_id, isolate,
                                      v8::Local<v8::Function>::Cast(args[0])));
    } else {
      RunAsyncTask(
          data->task_runner(), task_name_view,
          new ExecuteStringTask(
              isolate, context_group_id,
              ToVector(isolate, args[0].As<v8::String>()),
              v8::String::Empty(isolate), v8::Integer::New(isolate, 0),
              v8::Integer::New(isolate, 0), v8::Boolean::New(isolate, false)));
    }
  }
};

bool StrictAccessCheck(v8::Local<v8::Context> accessing_context,
                       v8::Local<v8::Object> accessed_object,
                       v8::Local<v8::Value> data) {
  CHECK(accessing_context.IsEmpty());
  return accessing_context.IsEmpty();
}

class InspectorExtension : public IsolateData::SetupGlobalTask {
 public:
  ~InspectorExtension() override = default;
  void Run(v8::Isolate* isolate,
           v8::Local<v8::ObjectTemplate> global) override {
    v8::Local<v8::ObjectTemplate> inspector = v8::ObjectTemplate::New(isolate);
    inspector->Set(ToV8String(isolate, "fireContextCreated"),
                   v8::FunctionTemplate::New(
                       isolate, &InspectorExtension::FireContextCreated));
    inspector->Set(ToV8String(isolate, "fireContextDestroyed"),
                   v8::FunctionTemplate::New(
                       isolate, &InspectorExtension::FireContextDestroyed));
    inspector->Set(
        ToV8String(isolate, "freeContext"),
        v8::FunctionTemplate::New(isolate, &InspectorExtension::FreeContext));
    inspector->Set(ToV8String(isolate, "addInspectedObject"),
                   v8::FunctionTemplate::New(
                       isolate, &InspectorExtension::AddInspectedObject));
    inspector->Set(ToV8String(isolate, "setMaxAsyncTaskStacks"),
                   v8::FunctionTemplate::New(
                       isolate, &InspectorExtension::SetMaxAsyncTaskStacks));
    inspector->Set(
        ToV8String(isolate, "dumpAsyncTaskStacksStateForTest"),
        v8::FunctionTemplate::New(
            isolate, &InspectorExtension::DumpAsyncTaskStacksStateForTest));
    inspector->Set(
        ToV8String(isolate, "breakProgram"),
        v8::FunctionTemplate::New(isolate, &InspectorExtension::BreakProgram));
    inspector->Set(
        ToV8String(isolate, "createObjectWithStrictCheck"),
        v8::FunctionTemplate::New(
            isolate, &InspectorExtension::CreateObjectWithStrictCheck));
    inspector->Set(ToV8String(isolate, "callWithScheduledBreak"),
                   v8::FunctionTemplate::New(
                       isolate, &InspectorExtension::CallWithScheduledBreak));
    inspector->Set(ToV8String(isolate, "allowAccessorFormatting"),
                   v8::FunctionTemplate::New(
                       isolate, &InspectorExtension::AllowAccessorFormatting));
    inspector->Set(
        ToV8String(isolate, "markObjectAsNotInspectable"),
        v8::FunctionTemplate::New(
            isolate, &InspectorExtension::MarkObjectAsNotInspectable));
    inspector->Set(ToV8String(isolate, "createObjectWithAccessor"),
                   v8::FunctionTemplate::New(
                       isolate, &InspectorExtension::CreateObjectWithAccessor));
    inspector->Set(ToV8String(isolate, "storeCurrentStackTrace"),
                   v8::FunctionTemplate::New(
                       isolate, &InspectorExtension::StoreCurrentStackTrace));
    inspector->Set(ToV8String(isolate, "externalAsyncTaskStarted"),
                   v8::FunctionTemplate::New(
                       isolate, &InspectorExtension::ExternalAsyncTaskStarted));
    inspector->Set(
        ToV8String(isolate, "externalAsyncTaskFinished"),
        v8::FunctionTemplate::New(
            isolate, &InspectorExtension::ExternalAsyncTaskFinished));
    inspector->Set(ToV8String(isolate, "scheduleWithAsyncStack"),
                   v8::FunctionTemplate::New(
                       isolate, &InspectorExtension::ScheduleWithAsyncStack));
    inspector->Set(
        ToV8String(isolate, "setAllowCodeGenerationFromStrings"),
        v8::FunctionTemplate::New(
            isolate, &InspectorExtension::SetAllowCodeGenerationFromStrings));
    inspector->Set(ToV8String(isolate, "setResourceNamePrefix"),
                   v8::FunctionTemplate::New(
                       isolate, &InspectorExtension::SetResourceNamePrefix));
    global->Set(ToV8String(isolate, "inspector"), inspector);
  }

 private:
  static void FireContextCreated(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    IsolateData* data = IsolateData::FromContext(context);
    data->FireContextCreated(context, data->GetContextGroupId(context));
  }

  static void FireContextDestroyed(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    IsolateData* data = IsolateData::FromContext(context);
    data->FireContextDestroyed(context);
  }

  static void FreeContext(const v8::FunctionCallbackInfo<v8::Value>& args) {
    v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    IsolateData* data = IsolateData::FromContext(context);
    data->FreeContext(context);
  }

  static void AddInspectedObject(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 2 || !args[0]->IsInt32()) {
      fprintf(stderr,
              "Internal error: addInspectedObject(session_id, object).");
      Exit();
    }
    v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    IsolateData* data = IsolateData::FromContext(context);
    data->AddInspectedObject(args[0].As<v8::Int32>()->Value(), args[1]);
  }

  static void SetMaxAsyncTaskStacks(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 1 || !args[0]->IsInt32()) {
      fprintf(stderr, "Internal error: setMaxAsyncTaskStacks(max).");
      Exit();
    }
    IsolateData::FromContext(args.GetIsolate()->GetCurrentContext())
        ->SetMaxAsyncTaskStacksForTest(args[0].As<v8::Int32>()->Value());
  }

  static void DumpAsyncTaskStacksStateForTest(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 0) {
      fprintf(stderr, "Internal error: dumpAsyncTaskStacksStateForTest().");
      Exit();
    }
    IsolateData::FromContext(args.GetIsolate()->GetCurrentContext())
        ->DumpAsyncTaskStacksStateForTest();
  }

  static void BreakProgram(const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsString()) {
      fprintf(stderr, "Internal error: breakProgram('reason', 'details').");
      Exit();
    }
    v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    IsolateData* data = IsolateData::FromContext(context);
    std::vector<uint16_t> reason =
        ToVector(args.GetIsolate(), args[0].As<v8::String>());
    v8_inspector::StringView reason_view(reason.data(), reason.size());
    std::vector<uint16_t> details =
        ToVector(args.GetIsolate(), args[1].As<v8::String>());
    v8_inspector::StringView details_view(details.data(), details.size());
    data->BreakProgram(data->GetContextGroupId(context), reason_view,
                       details_view);
  }

  static void CreateObjectWithStrictCheck(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 0) {
      fprintf(stderr, "Internal error: createObjectWithStrictCheck().");
      Exit();
    }
    v8::Local<v8::ObjectTemplate> templ =
        v8::ObjectTemplate::New(args.GetIsolate());
    templ->SetAccessCheckCallback(&StrictAccessCheck);
    args.GetReturnValue().Set(
        templ->NewInstance(args.GetIsolate()->GetCurrentContext())
            .ToLocalChecked());
  }

  static void CallWithScheduledBreak(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 3 || !args[0]->IsFunction() || !args[1]->IsString() ||
        !args[2]->IsString()) {
      fprintf(stderr,
              "Internal error: callWithScheduledBreak('reason', 'details').");
      Exit();
    }
    std::vector<uint16_t> reason =
        ToVector(args.GetIsolate(), args[1].As<v8::String>());
    v8_inspector::StringView reason_view(reason.data(), reason.size());
    std::vector<uint16_t> details =
        ToVector(args.GetIsolate(), args[2].As<v8::String>());
    v8_inspector::StringView details_view(details.data(), details.size());
    v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    IsolateData* data = IsolateData::FromContext(context);
    int context_group_id = data->GetContextGroupId(context);
    data->SchedulePauseOnNextStatement(context_group_id, reason_view,
                                       details_view);
    v8::MaybeLocal<v8::Value> result;
    result = args[0].As<v8::Function>()->Call(context, context->Global(), 0,
                                              nullptr);
    data->CancelPauseOnNextStatement(context_group_id);
  }

  static void AllowAccessorFormatting(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 1 || !args[0]->IsObject()) {
      fprintf(stderr, "Internal error: allowAccessorFormatting('object').");
      Exit();
    }
    v8::Local<v8::Object> object = args[0].As<v8::Object>();
    v8::Isolate* isolate = args.GetIsolate();
    v8::Local<v8::Private> shouldFormatAccessorsPrivate = v8::Private::ForApi(
        isolate, ToV8String(isolate, "allowAccessorFormatting"));
    object
        ->SetPrivate(isolate->GetCurrentContext(), shouldFormatAccessorsPrivate,
                     v8::Null(isolate))
        .ToChecked();
  }

  static void MarkObjectAsNotInspectable(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 1 || !args[0]->IsObject()) {
      fprintf(stderr, "Internal error: markObjectAsNotInspectable(object).");
      Exit();
    }
    v8::Local<v8::Object> object = args[0].As<v8::Object>();
    v8::Isolate* isolate = args.GetIsolate();
    v8::Local<v8::Private> notInspectablePrivate =
        v8::Private::ForApi(isolate, ToV8String(isolate, "notInspectable"));
    object
        ->SetPrivate(isolate->GetCurrentContext(), notInspectablePrivate,
                     v8::True(isolate))
        .ToChecked();
  }

  static void CreateObjectWithAccessor(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsBoolean()) {
      fprintf(stderr,
              "Internal error: createObjectWithAccessor('accessor name', "
              "hasSetter)\n");
      Exit();
    }
    v8::Isolate* isolate = args.GetIsolate();
    v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
    if (args[1].As<v8::Boolean>()->Value()) {
      templ->SetAccessor(v8::Local<v8::String>::Cast(args[0]), AccessorGetter,
                         AccessorSetter);
    } else {
      templ->SetAccessor(v8::Local<v8::String>::Cast(args[0]), AccessorGetter);
    }
    args.GetReturnValue().Set(
        templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked());
  }

  static void AccessorGetter(v8::Local<v8::String> property,
                             const v8::PropertyCallbackInfo<v8::Value>& info) {
    v8::Isolate* isolate = info.GetIsolate();
    isolate->ThrowException(ToV8String(isolate, "Getter is called"));
  }

  static void AccessorSetter(v8::Local<v8::String> property,
                             v8::Local<v8::Value> value,
                             const v8::PropertyCallbackInfo<void>& info) {
    v8::Isolate* isolate = info.GetIsolate();
    isolate->ThrowException(ToV8String(isolate, "Setter is called"));
  }

  static void StoreCurrentStackTrace(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 1 || !args[0]->IsString()) {
      fprintf(stderr,
              "Internal error: storeCurrentStackTrace('description')\n");
      Exit();
    }
    v8::Isolate* isolate = args.GetIsolate();
    v8::Local<v8::Context> context = isolate->GetCurrentContext();
    IsolateData* data = IsolateData::FromContext(context);
    std::vector<uint16_t> description =
        ToVector(isolate, args[0].As<v8::String>());
    v8_inspector::StringView description_view(description.data(),
                                              description.size());
    v8_inspector::V8StackTraceId id =
        data->StoreCurrentStackTrace(description_view);
    v8::Local<v8::ArrayBuffer> buffer =
        v8::ArrayBuffer::New(isolate, sizeof(id));
    *static_cast<v8_inspector::V8StackTraceId*>(buffer->GetContents().Data()) =
        id;
    args.GetReturnValue().Set(buffer);
  }

  static void ExternalAsyncTaskStarted(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 1 || !args[0]->IsArrayBuffer()) {
      fprintf(stderr, "Internal error: externalAsyncTaskStarted(id)\n");
      Exit();
    }
    v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    IsolateData* data = IsolateData::FromContext(context);
    v8_inspector::V8StackTraceId* id =
        static_cast<v8_inspector::V8StackTraceId*>(
            args[0].As<v8::ArrayBuffer>()->GetContents().Data());
    data->ExternalAsyncTaskStarted(*id);
  }

  static void ExternalAsyncTaskFinished(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 1 || !args[0]->IsArrayBuffer()) {
      fprintf(stderr, "Internal error: externalAsyncTaskFinished(id)\n");
      Exit();
    }
    v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    IsolateData* data = IsolateData::FromContext(context);
    v8_inspector::V8StackTraceId* id =
        static_cast<v8_inspector::V8StackTraceId*>(
            args[0].As<v8::ArrayBuffer>()->GetContents().Data());
    data->ExternalAsyncTaskFinished(*id);
  }

  static void ScheduleWithAsyncStack(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 3 || !args[0]->IsFunction() || !args[1]->IsString() ||
        !args[2]->IsBoolean()) {
      fprintf(stderr,
              "Internal error: scheduleWithAsyncStack(function, "
              "'task-name', with_empty_stack).");
      Exit();
    }
    v8::Isolate* isolate = args.GetIsolate();
    v8::Local<v8::Context> context = isolate->GetCurrentContext();
    IsolateData* data = IsolateData::FromContext(context);
    int context_group_id = data->GetContextGroupId(context);
    bool with_empty_stack = args[2].As<v8::Boolean>()->Value();
    if (with_empty_stack) context->Exit();

    std::vector<uint16_t> task_name =
        ToVector(isolate, args[1].As<v8::String>());
    v8_inspector::StringView task_name_view(task_name.data(), task_name.size());

    RunAsyncTask(data->task_runner(), task_name_view,
                 new SetTimeoutTask(context_group_id, isolate,
                                    v8::Local<v8::Function>::Cast(args[0])));
    if (with_empty_stack) context->Enter();
  }

  static void SetAllowCodeGenerationFromStrings(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 1 || !args[0]->IsBoolean()) {
      fprintf(stderr,
              "Internal error: setAllowCodeGenerationFromStrings(allow).");
      Exit();
    }
    args.GetIsolate()->GetCurrentContext()->AllowCodeGenerationFromStrings(
        args[0].As<v8::Boolean>()->Value());
  }

  static void SetResourceNamePrefix(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 1 || !args[0]->IsString()) {
      fprintf(stderr, "Internal error: setResourceNamePrefix('prefix').");
      Exit();
    }
    v8::Isolate* isolate = args.GetIsolate();
    v8::Local<v8::Context> context = isolate->GetCurrentContext();
    IsolateData* data = IsolateData::FromContext(context);
    data->SetResourceNamePrefix(v8::Local<v8::String>::Cast(args[0]));
  }
};

}  //  namespace

int main(int argc, char* argv[]) {
  v8::V8::InitializeICUDefaultLocation(argv[0]);
  std::unique_ptr<v8::Platform> platform(v8::platform::NewDefaultPlatform());
  v8::V8::InitializePlatform(platform.get());
  v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
  v8::V8::InitializeExternalStartupData(argv[0]);
  v8::V8::Initialize();
  i::DisableEmbeddedBlobRefcounting();

  v8::base::Semaphore ready_semaphore(0);

  v8::StartupData startup_data = {nullptr, 0};
  for (int i = 1; i < argc; ++i) {
    if (strcmp(argv[i], "--embed") == 0) {
      argv[i++] = nullptr;
      printf("Embedding script '%s'\n", argv[i]);
      startup_data = i::CreateSnapshotDataBlobInternal(
          v8::SnapshotCreator::FunctionCodeHandling::kClear, argv[i], nullptr);
      v8::internal::ReadOnlyHeap::ClearSharedHeapForTest();
      argv[i] = nullptr;
    }
  }

  {
    IsolateData::SetupGlobalTasks frontend_extensions;
    frontend_extensions.emplace_back(new UtilsExtension());
    TaskRunner frontend_runner(
        std::move(frontend_extensions), true, &ready_semaphore,
        startup_data.data ? &startup_data : nullptr, false);
    ready_semaphore.Wait();

    int frontend_context_group_id = 0;
    RunSyncTask(&frontend_runner,
                [&frontend_context_group_id](IsolateData* data) {
                  frontend_context_group_id = data->CreateContextGroup();
                });

    IsolateData::SetupGlobalTasks backend_extensions;
    backend_extensions.emplace_back(new SetTimeoutExtension());
    backend_extensions.emplace_back(new InspectorExtension());
    TaskRunner backend_runner(
        std::move(backend_extensions), false, &ready_semaphore,
        startup_data.data ? &startup_data : nullptr, true);
    ready_semaphore.Wait();
    UtilsExtension::set_backend_task_runner(&backend_runner);

    task_runners.push_back(&frontend_runner);
    task_runners.push_back(&backend_runner);

    for (int i = 1; i < argc; ++i) {
      // Ignore unknown flags.
      if (argv[i] == nullptr || argv[i][0] == '-') continue;

      bool exists = false;
      std::string chars = v8::internal::ReadFile(argv[i], &exists, true);
      if (!exists) {
        fprintf(stderr, "Internal error: script file doesn't exists: %s\n",
                argv[i]);
        Exit();
      }
      frontend_runner.Append(
          new ExecuteStringTask(chars, frontend_context_group_id));
    }

    frontend_runner.Join();
    backend_runner.Join();

    UtilsExtension::ClearAllSessions();
    delete startup_data.data;

    // TaskRunners go out of scope here, which causes Isolate teardown and all
    // running background tasks to be properly joined.
  }

  i::FreeCurrentEmbeddedBlob();
  return 0;
}
