// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "fxjs/cjs_runtime.h"

#include <math.h>

#include <algorithm>

#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
#include "fxjs/cfx_globaldata.h"
#include "fxjs/cjs_annot.h"
#include "fxjs/cjs_app.h"
#include "fxjs/cjs_border.h"
#include "fxjs/cjs_color.h"
#include "fxjs/cjs_console.h"
#include "fxjs/cjs_display.h"
#include "fxjs/cjs_document.h"
#include "fxjs/cjs_event.h"
#include "fxjs/cjs_event_context.h"
#include "fxjs/cjs_field.h"
#include "fxjs/cjs_font.h"
#include "fxjs/cjs_global.h"
#include "fxjs/cjs_globalarrays.h"
#include "fxjs/cjs_globalconsts.h"
#include "fxjs/cjs_highlight.h"
#include "fxjs/cjs_icon.h"
#include "fxjs/cjs_object.h"
#include "fxjs/cjs_position.h"
#include "fxjs/cjs_publicmethods.h"
#include "fxjs/cjs_scalehow.h"
#include "fxjs/cjs_scalewhen.h"
#include "fxjs/cjs_style.h"
#include "fxjs/cjs_timerobj.h"
#include "fxjs/cjs_util.h"
#include "fxjs/cjs_zoomtype.h"
#include "fxjs/fxv8.h"
#include "fxjs/js_define.h"
#include "third_party/base/check_op.h"
#include "v8/include/v8-context.h"
#include "v8/include/v8-exception.h"
#include "v8/include/v8-isolate.h"

CJS_Runtime::CJS_Runtime(CPDFSDK_FormFillEnvironment* pFormFillEnv)
    : m_pFormFillEnv(pFormFillEnv) {
  v8::Isolate* pIsolate = nullptr;
  IPDF_JSPLATFORM* pPlatform = m_pFormFillEnv->GetFormFillInfo()->m_pJsPlatform;
  if (pPlatform->version <= 2) {
    // Backwards compatibility - JS now initialized earlier in more modern
    // JSPLATFORM versions.
    unsigned int embedderDataSlot = 0;
    v8::Isolate* pExternalIsolate = nullptr;
    if (pPlatform->version == 2) {
      pExternalIsolate = static_cast<v8::Isolate*>(pPlatform->m_isolate);
      embedderDataSlot = pPlatform->m_v8EmbedderSlot;
    }
    FXJS_Initialize(embedderDataSlot, pExternalIsolate);
  }
  m_isolateManaged = FXJS_GetIsolate(&pIsolate);
  SetIsolate(pIsolate);

  v8::Isolate::Scope isolate_scope(pIsolate);
  v8::HandleScope handle_scope(pIsolate);
  if (m_isolateManaged || FXJS_GlobalIsolateRefCount() == 0)
    DefineJSObjects();

  ScopedEventContext pContext(this);
  InitializeEngine();
  SetFormFillEnvToDocument();
}

CJS_Runtime::~CJS_Runtime() {
  NotifyObservers();
  ReleaseEngine();
  if (m_isolateManaged)
    DisposeIsolate();
}

void CJS_Runtime::DefineJSObjects() {
  v8::Isolate::Scope isolate_scope(GetIsolate());
  v8::HandleScope handle_scope(GetIsolate());
  v8::Local<v8::Context> context = v8::Context::New(GetIsolate());
  v8::Context::Scope context_scope(context);

  // The call order determines the "ObjDefID" assigned to each class.
  // ObjDefIDs 0 - 2
  CJS_Border::DefineJSObjects(this);
  CJS_Display::DefineJSObjects(this);
  CJS_Font::DefineJSObjects(this);

  // ObjDefIDs 3 - 5
  CJS_Highlight::DefineJSObjects(this);
  CJS_Position::DefineJSObjects(this);
  CJS_ScaleHow::DefineJSObjects(this);

  // ObjDefIDs 6 - 8
  CJS_ScaleWhen::DefineJSObjects(this);
  CJS_Style::DefineJSObjects(this);
  CJS_Zoomtype::DefineJSObjects(this);

  // ObjDefIDs 9 - 11
  CJS_App::DefineJSObjects(this);
  CJS_Color::DefineJSObjects(this);
  CJS_Console::DefineJSObjects(this);

  // ObjDefIDs 12 - 14
  CJS_Document::DefineJSObjects(this);
  CJS_Event::DefineJSObjects(this);
  CJS_Field::DefineJSObjects(this);

  // ObjDefIDs 15 - 17
  CJS_Global::DefineJSObjects(this);
  CJS_Icon::DefineJSObjects(this);
  CJS_Util::DefineJSObjects(this);

  // ObjDefIDs 18 - 20 (these can't fail, return void).
  CJS_PublicMethods::DefineJSObjects(this);
  CJS_GlobalConsts::DefineJSObjects(this);
  CJS_GlobalArrays::DefineJSObjects(this);

  // ObjDefIDs 21 - 22.
  CJS_TimerObj::DefineJSObjects(this);
  CJS_Annot::DefineJSObjects(this);
}

IJS_EventContext* CJS_Runtime::NewEventContext() {
  m_EventContextArray.push_back(std::make_unique<CJS_EventContext>(this));
  return m_EventContextArray.back().get();
}

void CJS_Runtime::ReleaseEventContext(IJS_EventContext* pContext) {
  DCHECK_EQ(pContext, m_EventContextArray.back().get());
  m_EventContextArray.pop_back();
}

CJS_EventContext* CJS_Runtime::GetCurrentEventContext() const {
  return m_EventContextArray.empty() ? nullptr
                                     : m_EventContextArray.back().get();
}

CFX_Timer::HandlerIface* CJS_Runtime::GetTimerHandler() const {
  return m_pFormFillEnv ? m_pFormFillEnv->GetTimerHandler() : nullptr;
}

void CJS_Runtime::SetFormFillEnvToDocument() {
  v8::Isolate::Scope isolate_scope(GetIsolate());
  v8::HandleScope handle_scope(GetIsolate());
  v8::Local<v8::Context> context = GetV8Context();
  v8::Context::Scope context_scope(context);

  v8::Local<v8::Object> pThis = GetThisObj();
  if (pThis.IsEmpty())
    return;

  auto pJSDocument = JSGetObject<CJS_Document>(GetIsolate(), pThis);
  if (!pJSDocument)
    return;

  pJSDocument->SetFormFillEnv(m_pFormFillEnv.Get());
}

CPDFSDK_FormFillEnvironment* CJS_Runtime::GetFormFillEnv() const {
  return m_pFormFillEnv.Get();
}

absl::optional<IJS_Runtime::JS_Error> CJS_Runtime::ExecuteScript(
    const WideString& script) {
  return Execute(script);
}

bool CJS_Runtime::AddEventToSet(const FieldEvent& event) {
  return m_FieldEventSet.insert(event).second;
}

void CJS_Runtime::RemoveEventFromSet(const FieldEvent& event) {
  m_FieldEventSet.erase(event);
}

CJS_Runtime* CJS_Runtime::AsCJSRuntime() {
  return this;
}

v8::Local<v8::Value> CJS_Runtime::GetValueByNameFromGlobalObject(
    ByteStringView utf8Name) {
  v8::Isolate::Scope isolate_scope(GetIsolate());
  v8::Local<v8::Context> context = GetV8Context();
  v8::Context::Scope context_scope(context);
  v8::Local<v8::String> str = fxv8::NewStringHelper(GetIsolate(), utf8Name);
  v8::MaybeLocal<v8::Value> maybe_value = context->Global()->Get(context, str);
  if (maybe_value.IsEmpty())
    return v8::Local<v8::Value>();
  return maybe_value.ToLocalChecked();
}

bool CJS_Runtime::SetValueByNameInGlobalObject(ByteStringView utf8Name,
                                               v8::Local<v8::Value> pValue) {
  if (utf8Name.IsEmpty() || pValue.IsEmpty())
    return false;

  v8::Isolate* pIsolate = GetIsolate();
  v8::Isolate::Scope isolate_scope(pIsolate);
  v8::Local<v8::Context> context = GetV8Context();
  v8::Context::Scope context_scope(context);
  v8::Local<v8::String> str = fxv8::NewStringHelper(pIsolate, utf8Name);
  v8::Maybe<bool> result = context->Global()->Set(context, str, pValue);
  return result.IsJust() && result.FromJust();
}

v8::Local<v8::Value> CJS_Runtime::MaybeCoerceToNumber(
    v8::Local<v8::Value> value) {
  bool bAllowNaN = false;
  if (value->IsString()) {
    ByteString bstr = fxv8::ToByteString(GetIsolate(), value.As<v8::String>());
    if (bstr.IsEmpty())
      return value;
    if (bstr == "NaN")
      bAllowNaN = true;
  }

  v8::TryCatch try_catch(GetIsolate());
  v8::MaybeLocal<v8::Number> maybeNum =
      value->ToNumber(GetIsolate()->GetCurrentContext());
  if (maybeNum.IsEmpty())
    return value;

  v8::Local<v8::Number> num = maybeNum.ToLocalChecked();
  if (isnan(num->Value()) && !bAllowNaN)
    return value;

  return num;
}
