// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/script/v8c/v8c_engine.h"

#include <algorithm>
#include <string>

#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "cobalt/base/c_val.h"
#include "cobalt/browser/stack_size_constants.h"
#include "cobalt/script/v8c/v8c_global_environment.h"
#include "starboard/once.h"
#include "v8/include/libplatform/libplatform.h"
#include "v8/include/v8.h"

namespace cobalt {
namespace script {
namespace v8c {
namespace {

SbOnceControl g_js_init_once_control = SB_ONCE_INITIALIZER;
v8::Platform* g_platform = nullptr;
v8::ArrayBuffer::Allocator* g_array_buffer_allocator = nullptr;

void ShutDown(void*) {
  v8::V8::Dispose();
  v8::V8::ShutdownPlatform();

  DCHECK(g_platform);
  delete g_platform;
  g_platform = nullptr;

  DCHECK(g_array_buffer_allocator);
  delete g_array_buffer_allocator;
  g_array_buffer_allocator = nullptr;
}

void InitializeAndRegisterShutDownOnce() {
  // TODO: Initialize V8 ICU stuff here as well.
  g_platform = v8::platform::CreateDefaultPlatform();
  v8::V8::InitializePlatform(g_platform);
  v8::V8::Initialize();
  g_array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();

  base::AtExitManager::RegisterCallback(ShutDown, nullptr);
}

}  // namespace

v8::Platform* GetPlatform() { return g_platform; }

V8cEngine::V8cEngine(const Options& options)
    : accumulated_extra_memory_cost_(0), options_(options) {
  TRACE_EVENT0("cobalt::script", "V8cEngine::V8cEngine()");
  SbOnce(&g_js_init_once_control, InitializeAndRegisterShutDownOnce);
  DCHECK(g_platform);
  DCHECK(g_array_buffer_allocator);

  v8::Isolate::CreateParams params;
  params.array_buffer_allocator = g_array_buffer_allocator;

  isolate_ = v8::Isolate::New(params);
  CHECK(isolate_);
  // There are 2 total isolate data slots, one for the sole |V8cEngine| (us),
  // and one for the |V8cGlobalEnvironment|.
  const int kTotalIsolateDataSlots = 2;
  DCHECK_GE(v8::Isolate::GetNumberOfDataSlots(), kTotalIsolateDataSlots);
  isolate_->SetData(kIsolateDataIndex, this);

  v8c_heap_tracer_.reset(new V8cHeapTracer(isolate_));
  isolate_->SetEmbedderHeapTracer(v8c_heap_tracer_.get());
}

V8cEngine::~V8cEngine() {
  TRACE_EVENT0("cobalt::script", "V8cEngine::~V8cEngine");
  DCHECK(thread_checker_.CalledOnValidThread());

  // This next GC is to GC everything (mostly for ASan), so we actually don't
  // want our wrappers and wrappables to stay alive.
  isolate_->SetEmbedderHeapTracer(nullptr);

  // Send a low memory notification to V8 in order to force a garbage
  // collection before shut down.  This is required to run weak callbacks that
  // are responsible for freeing native objects that live in the internal
  // fields of V8 objects.  In the future, we should consider investigating if
  // there are startup performance wins to be made by delaying this work until
  // later (e.g., does the GC of the splash screen web module dying hurt us?).
  isolate_->LowMemoryNotification();
  isolate_->Dispose();
  isolate_ = nullptr;
}

scoped_refptr<GlobalEnvironment> V8cEngine::CreateGlobalEnvironment() {
  TRACE_EVENT0("cobalt::script", "V8cEngine::CreateGlobalEnvironment()");
  DCHECK(thread_checker_.CalledOnValidThread());
  return new V8cGlobalEnvironment(isolate_);
}

void V8cEngine::CollectGarbage() {
  TRACE_EVENT0("cobalt::script", "V8cEngine::CollectGarbage()");
  DCHECK(thread_checker_.CalledOnValidThread());
  isolate_->LowMemoryNotification();
}

void V8cEngine::ReportExtraMemoryCost(size_t bytes) {
  DCHECK(thread_checker_.CalledOnValidThread());
  accumulated_extra_memory_cost_ += bytes;

  const bool do_collect_garbage =
      accumulated_extra_memory_cost_ > options_.gc_threshold_bytes;
  if (do_collect_garbage) {
    accumulated_extra_memory_cost_ = 0;
    CollectGarbage();
  }
}

bool V8cEngine::RegisterErrorHandler(JavaScriptEngine::ErrorHandler handler) {
  error_handler_ = handler;
  return true;
}

void V8cEngine::SetGcThreshold(int64_t bytes) { NOTIMPLEMENTED(); }

}  // namespace v8c

// static
scoped_ptr<JavaScriptEngine> JavaScriptEngine::CreateEngine(
    const JavaScriptEngine::Options& options) {
  TRACE_EVENT0("cobalt::script", "JavaScriptEngine::CreateEngine()");
  return make_scoped_ptr<JavaScriptEngine>(new v8c::V8cEngine(options));
}

// static
size_t JavaScriptEngine::UpdateMemoryStatsAndReturnReserved() {
  NOTIMPLEMENTED();
  return 0;
}

}  // namespace script
}  // namespace cobalt
