// 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 "JS_Object.h"

#include "../../include/fsdk_mgr.h"  // For CPDFDoc_Environment.
#include "../../include/javascript/IJavaScript.h"
#include "JS_Context.h"
#include "JS_Define.h"

namespace {

int FXJS_MsgBox(CPDFDoc_Environment* pApp,
                const FX_WCHAR* swMsg,
                const FX_WCHAR* swTitle,
                FX_UINT nType,
                FX_UINT nIcon) {
  if (!pApp)
    return 0;

  if (CPDFSDK_Document* pDoc = pApp->GetSDKDocument())
    pDoc->KillFocusAnnot();

  return pApp->JS_appAlert(swMsg, swTitle, nType, nIcon);
}

}  // namespace

CJS_EmbedObj::CJS_EmbedObj(CJS_Object* pJSObject) : m_pJSObject(pJSObject) {}

CJS_EmbedObj::~CJS_EmbedObj() {
  m_pJSObject = NULL;
}

int CJS_EmbedObj::MsgBox(CPDFDoc_Environment* pApp,
                         const FX_WCHAR* swMsg,
                         const FX_WCHAR* swTitle,
                         FX_UINT nType,
                         FX_UINT nIcon) {
  return FXJS_MsgBox(pApp, swMsg, swTitle, nType, nIcon);
}

void CJS_EmbedObj::Alert(CJS_Context* pContext, const FX_WCHAR* swMsg) {
  CJS_Object::Alert(pContext, swMsg);
}

void FreeObject(const v8::WeakCallbackInfo<CJS_Object>& data) {
  CJS_Object* pJSObj = data.GetParameter();
  pJSObj->ExitInstance();
  delete pJSObj;
  FXJS_FreePrivate(data.GetInternalField(0));
}

void DisposeObject(const v8::WeakCallbackInfo<CJS_Object>& data) {
  CJS_Object* pJSObj = data.GetParameter();
  pJSObj->Dispose();
  data.SetSecondPassCallback(FreeObject);
}

CJS_Object::CJS_Object(v8::Local<v8::Object> pObject) {
  m_pIsolate = pObject->GetIsolate();
  m_pV8Object.Reset(m_pIsolate, pObject);
}

CJS_Object::~CJS_Object() {
}

void CJS_Object::MakeWeak() {
  m_pV8Object.SetWeak(this, DisposeObject,
                      v8::WeakCallbackType::kInternalFields);
}

void CJS_Object::Dispose() {
  m_pV8Object.Reset();
}

int CJS_Object::MsgBox(CPDFDoc_Environment* pApp,
                       const FX_WCHAR* swMsg,
                       const FX_WCHAR* swTitle,
                       FX_UINT nType,
                       FX_UINT nIcon) {
  return FXJS_MsgBox(pApp, swMsg, swTitle, nType, nIcon);
}

void CJS_Object::Alert(CJS_Context* pContext, const FX_WCHAR* swMsg) {
  ASSERT(pContext != NULL);

  if (pContext->IsMsgBoxEnabled()) {
    CPDFDoc_Environment* pApp = pContext->GetReaderApp();
    if (pApp)
      pApp->JS_appAlert(swMsg, NULL, 0, 3);
  }
}

CJS_Timer::CJS_Timer(CJS_EmbedObj* pObj,
                     CPDFDoc_Environment* pApp,
                     CJS_Runtime* pRuntime,
                     int nType,
                     const CFX_WideString& script,
                     FX_DWORD dwElapse,
                     FX_DWORD dwTimeOut)
    : m_nTimerID(0),
      m_pEmbedObj(pObj),
      m_bProcessing(false),
      m_bValid(true),
      m_nType(nType),
      m_dwTimeOut(dwTimeOut),
      m_swJScript(script),
      m_pRuntime(pRuntime),
      m_pApp(pApp) {
  IFX_SystemHandler* pHandler = m_pApp->GetSysHandler();
  m_nTimerID = pHandler->SetTimer(dwElapse, TimerProc);
  (*GetGlobalTimerMap())[m_nTimerID] = this;
  m_pRuntime->AddObserver(this);
}

CJS_Timer::~CJS_Timer() {
  CJS_Runtime* pRuntime = GetRuntime();
  if (pRuntime)
    pRuntime->RemoveObserver(this);
  KillJSTimer();
}

void CJS_Timer::KillJSTimer() {
  if (m_nTimerID) {
    if (m_bValid) {
      IFX_SystemHandler* pHandler = m_pApp->GetSysHandler();
      pHandler->KillTimer(m_nTimerID);
    }
    GetGlobalTimerMap()->erase(m_nTimerID);
    m_nTimerID = 0;
  }
}

// static
void CJS_Timer::TimerProc(int idEvent) {
  const auto it = GetGlobalTimerMap()->find(idEvent);
  if (it != GetGlobalTimerMap()->end()) {
    CJS_Timer* pTimer = it->second;
    if (!pTimer->m_bProcessing) {
      CFX_AutoRestorer<bool> scoped_processing(&pTimer->m_bProcessing);
      pTimer->m_bProcessing = true;
      if (pTimer->m_pEmbedObj)
        pTimer->m_pEmbedObj->TimerProc(pTimer);
    }
  }
}

// static
CJS_Timer::TimerMap* CJS_Timer::GetGlobalTimerMap() {
  // Leak the timer array at shutdown.
  static auto* s_TimerMap = new TimerMap;
  return s_TimerMap;
}

void CJS_Timer::OnDestroyed() {
  m_bValid = false;
}
