// 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 "../include/fsdk_define.h"
#include "../include/fsdk_mgr.h"
#include "../include/fsdk_actionhandler.h"
#include "../include/javascript/IJavaScript.h"

/* -------------------------- CBA_ActionHandler -------------------------- */

CPDFSDK_ActionHandler::CPDFSDK_ActionHandler(CPDFDoc_Environment* pEvi)
    : m_pFormActionHandler(new CPDFSDK_FormActionHandler),
      m_pMediaActionHandler(NULL) {}

void CPDFSDK_ActionHandler::SetMediaActionHandler(
    CPDFSDK_MediaActionHandler* pHandler) {
  ASSERT(pHandler != NULL);
  ASSERT(m_pMediaActionHandler == NULL);
  m_pMediaActionHandler = pHandler;
}

// document open
FX_BOOL CPDFSDK_ActionHandler::DoAction_DocOpen(const CPDF_Action& action,
                                                CPDFSDK_Document* pDocument) {
  CFX_PtrList list;
  return ExecuteDocumentOpenAction(action, pDocument, list);
}

// document open
FX_BOOL CPDFSDK_ActionHandler::DoAction_JavaScript(
    const CPDF_Action& JsAction,
    CFX_WideString csJSName,
    CPDFSDK_Document* pDocument) {
  if (JsAction.GetType() == CPDF_Action::JavaScript) {
    CFX_WideString swJS = JsAction.GetJavaScript();
    if (!swJS.IsEmpty()) {
      RunDocumentOpenJavaScript(pDocument, csJSName, swJS);
      return TRUE;
    }
  }

  return FALSE;
}

FX_BOOL CPDFSDK_ActionHandler::DoAction_FieldJavaScript(
    const CPDF_Action& JsAction,
    CPDF_AAction::AActionType type,
    CPDFSDK_Document* pDocument,
    CPDF_FormField* pFormField,
    PDFSDK_FieldAction& data) {
  CPDFDoc_Environment* pEnv = pDocument->GetEnv();
  ASSERT(pEnv);
  if (pEnv->IsJSInitiated() && JsAction.GetType() == CPDF_Action::JavaScript) {
    CFX_WideString swJS = JsAction.GetJavaScript();
    if (!swJS.IsEmpty()) {
      RunFieldJavaScript(pDocument, pFormField, type, data, swJS);
      return TRUE;
    }
  }
  return FALSE;
}

FX_BOOL CPDFSDK_ActionHandler::DoAction_Page(
    const CPDF_Action& action,
    enum CPDF_AAction::AActionType eType,
    CPDFSDK_Document* pDocument) {
  CFX_PtrList list;
  return ExecuteDocumentPageAction(action, eType, pDocument, list);
}

FX_BOOL CPDFSDK_ActionHandler::DoAction_Document(
    const CPDF_Action& action,
    enum CPDF_AAction::AActionType eType,
    CPDFSDK_Document* pDocument) {
  CFX_PtrList list;
  return ExecuteDocumentPageAction(action, eType, pDocument, list);
}

FX_BOOL CPDFSDK_ActionHandler::DoAction_BookMark(CPDF_Bookmark* pBookMark,
                                                 const CPDF_Action& action,
                                                 CPDF_AAction::AActionType type,
                                                 CPDFSDK_Document* pDocument) {
  CFX_PtrList list;
  return ExecuteBookMark(action, pDocument, pBookMark, list);
}

FX_BOOL CPDFSDK_ActionHandler::DoAction_Screen(const CPDF_Action& action,
                                               CPDF_AAction::AActionType type,
                                               CPDFSDK_Document* pDocument,
                                               CPDFSDK_Annot* pScreen) {
  CFX_PtrList list;
  return ExecuteScreenAction(action, type, pDocument, pScreen, list);
}

FX_BOOL CPDFSDK_ActionHandler::DoAction_Link(const CPDF_Action& action,
                                             CPDFSDK_Document* pDocument) {
  CFX_PtrList list;
  return ExecuteLinkAction(action, pDocument, list);
}

FX_BOOL CPDFSDK_ActionHandler::DoAction_Field(const CPDF_Action& action,
                                              CPDF_AAction::AActionType type,
                                              CPDFSDK_Document* pDocument,
                                              CPDF_FormField* pFormField,
                                              PDFSDK_FieldAction& data) {
  CFX_PtrList list;
  return ExecuteFieldAction(action, type, pDocument, pFormField, data, list);
}

FX_BOOL CPDFSDK_ActionHandler::ExecuteDocumentOpenAction(
    const CPDF_Action& action,
    CPDFSDK_Document* pDocument,
    CFX_PtrList& list) {
  CPDF_Dictionary* pDict = action.GetDict();
  if (list.Find(pDict))
    return FALSE;

  list.AddTail(pDict);

  CPDFDoc_Environment* pEnv = pDocument->GetEnv();
  ASSERT(pEnv);
  if (action.GetType() == CPDF_Action::JavaScript) {
    if (pEnv->IsJSInitiated()) {
      CFX_WideString swJS = action.GetJavaScript();
      if (!swJS.IsEmpty()) {
        RunDocumentOpenJavaScript(pDocument, L"", swJS);
      }
    }
  } else {
    DoAction_NoJs(action, pDocument);
  }

  for (int32_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) {
    CPDF_Action subaction = action.GetSubAction(i);
    if (!ExecuteDocumentOpenAction(subaction, pDocument, list))
      return FALSE;
  }

  return TRUE;
}

FX_BOOL CPDFSDK_ActionHandler::ExecuteLinkAction(const CPDF_Action& action,
                                                 CPDFSDK_Document* pDocument,
                                                 CFX_PtrList& list) {
  ASSERT(pDocument != NULL);

  CPDF_Dictionary* pDict = action.GetDict();
  if (list.Find(pDict))
    return FALSE;

  list.AddTail(pDict);

  CPDFDoc_Environment* pEnv = pDocument->GetEnv();
  ASSERT(pEnv);
  if (action.GetType() == CPDF_Action::JavaScript) {
    if (pEnv->IsJSInitiated()) {
      CFX_WideString swJS = action.GetJavaScript();
      if (!swJS.IsEmpty()) {
        IFXJS_Runtime* pRuntime = pDocument->GetJsRuntime();  //????
        ASSERT(pRuntime != NULL);

        pRuntime->SetReaderDocument(pDocument);

        IFXJS_Context* pContext = pRuntime->NewContext();
        ASSERT(pContext != NULL);

        pContext->OnLink_MouseUp(pDocument);

        CFX_WideString csInfo;
        FX_BOOL bRet = pContext->RunScript(swJS, csInfo);
        if (!bRet) {
          // FIXME: return error.
        }

        pRuntime->ReleaseContext(pContext);
      }
    }
  } else {
    DoAction_NoJs(action, pDocument);
  }

  for (int32_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) {
    CPDF_Action subaction = action.GetSubAction(i);
    if (!ExecuteLinkAction(subaction, pDocument, list))
      return FALSE;
  }

  return TRUE;
}

FX_BOOL CPDFSDK_ActionHandler::ExecuteDocumentPageAction(
    const CPDF_Action& action,
    CPDF_AAction::AActionType type,
    CPDFSDK_Document* pDocument,
    CFX_PtrList& list) {
  ASSERT(pDocument != NULL);

  CPDF_Dictionary* pDict = action.GetDict();
  if (list.Find(pDict))
    return FALSE;

  list.AddTail(pDict);

  CPDFDoc_Environment* pEnv = pDocument->GetEnv();
  ASSERT(pEnv);
  if (action.GetType() == CPDF_Action::JavaScript) {
    if (pEnv->IsJSInitiated()) {
      CFX_WideString swJS = action.GetJavaScript();
      if (!swJS.IsEmpty()) {
        RunDocumentPageJavaScript(pDocument, type, swJS);
      }
    }
  } else {
    DoAction_NoJs(action, pDocument);
  }

  if (!IsValidDocView(pDocument))
    return FALSE;

  for (int32_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) {
    CPDF_Action subaction = action.GetSubAction(i);
    if (!ExecuteDocumentPageAction(subaction, type, pDocument, list))
      return FALSE;
  }

  return TRUE;
}

FX_BOOL CPDFSDK_ActionHandler::IsValidField(CPDFSDK_Document* pDocument,
                                            CPDF_Dictionary* pFieldDict) {
  ASSERT(pDocument != NULL);
  ASSERT(pFieldDict != NULL);

  CPDFSDK_InterForm* pInterForm = pDocument->GetInterForm();
  ASSERT(pInterForm != NULL);

  CPDF_InterForm* pPDFInterForm = pInterForm->GetInterForm();
  ASSERT(pPDFInterForm != NULL);

  return pPDFInterForm->GetFieldByDict(pFieldDict) != NULL;
}

FX_BOOL CPDFSDK_ActionHandler::ExecuteFieldAction(
    const CPDF_Action& action,
    CPDF_AAction::AActionType type,
    CPDFSDK_Document* pDocument,
    CPDF_FormField* pFormField,
    PDFSDK_FieldAction& data,
    CFX_PtrList& list) {
  ASSERT(pDocument != NULL);

  CPDF_Dictionary* pDict = action.GetDict();
  if (list.Find(pDict))
    return FALSE;

  list.AddTail(pDict);

  CPDFDoc_Environment* pEnv = pDocument->GetEnv();
  ASSERT(pEnv);
  if (action.GetType() == CPDF_Action::JavaScript) {
    if (pEnv->IsJSInitiated()) {
      CFX_WideString swJS = action.GetJavaScript();
      if (!swJS.IsEmpty()) {
        RunFieldJavaScript(pDocument, pFormField, type, data, swJS);
        if (!IsValidField(pDocument, pFormField->GetFieldDict()))
          return FALSE;
      }
    }
  } else {
    DoAction_NoJs(action, pDocument);
  }

  for (int32_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) {
    CPDF_Action subaction = action.GetSubAction(i);
    if (!ExecuteFieldAction(subaction, type, pDocument, pFormField, data, list))
      return FALSE;
  }

  return TRUE;
}

FX_BOOL CPDFSDK_ActionHandler::ExecuteScreenAction(
    const CPDF_Action& action,
    CPDF_AAction::AActionType type,
    CPDFSDK_Document* pDocument,
    CPDFSDK_Annot* pScreen,
    CFX_PtrList& list) {
  ASSERT(pDocument != NULL);

  CPDF_Dictionary* pDict = action.GetDict();
  if (list.Find(pDict))
    return FALSE;

  list.AddTail(pDict);

  CPDFDoc_Environment* pEnv = pDocument->GetEnv();
  ASSERT(pEnv);
  if (action.GetType() == CPDF_Action::JavaScript) {
    if (pEnv->IsJSInitiated()) {
      CFX_WideString swJS = action.GetJavaScript();
      if (!swJS.IsEmpty()) {
        IFXJS_Runtime* pRuntime = pDocument->GetJsRuntime();
        ASSERT(pRuntime != NULL);

        pRuntime->SetReaderDocument(pDocument);

        IFXJS_Context* pContext = pRuntime->NewContext();
        ASSERT(pContext != NULL);

        // 			switch (type)
        // 			{
        // 			case CPDF_AAction::CursorEnter:
        // 				pContext->OnScreen_MouseEnter(IsCTRLpressed(),
        // IsSHIFTpressed(), pScreen);
        // 				break;
        // 			case CPDF_AAction::CursorExit:
        // 				pContext->OnScreen_MouseExit(IsCTRLpressed(),
        // IsSHIFTpressed(), pScreen);
        // 				break;
        // 			case CPDF_AAction::ButtonDown:
        // 				pContext->OnScreen_MouseDown(IsCTRLpressed(),
        // IsSHIFTpressed(), pScreen);
        // 				break;
        // 			case CPDF_AAction::ButtonUp:
        // 				pContext->OnScreen_MouseUp(IsCTRLpressed(),
        // IsSHIFTpressed(), pScreen);
        // 				break;
        // 			case CPDF_AAction::GetFocus:
        // 				pContext->OnScreen_Focus(IsCTRLpressed(),
        // IsSHIFTpressed(), pScreen);
        // 				break;
        // 			case CPDF_AAction::LoseFocus:
        // 				pContext->OnScreen_Blur(IsCTRLpressed(),
        // IsSHIFTpressed(), pScreen);
        // 				break;
        // 			case CPDF_AAction::PageOpen:
        // 				pContext->OnScreen_Open(IsCTRLpressed(),
        // IsSHIFTpressed(), pScreen);
        // 				break;
        // 			case CPDF_AAction::PageClose:
        // 				pContext->OnScreen_Close(IsCTRLpressed(),
        // IsSHIFTpressed(), pScreen);
        // 				break;
        // 			case CPDF_AAction::PageVisible:
        // 				pContext->OnScreen_InView(IsCTRLpressed(),
        // IsSHIFTpressed(), pScreen);
        // 				break;
        // 			case CPDF_AAction::PageInvisible:
        // 				pContext->OnScreen_OutView(IsCTRLpressed(),
        // IsSHIFTpressed(), pScreen);
        // 				break;
        // 			default:
        // 				ASSERT(FALSE);
        // 				break;
        // 			}

        CFX_WideString csInfo;
        FX_BOOL bRet = pContext->RunScript(swJS, csInfo);
        if (!bRet) {
          // CBCL_FormNotify::MsgBoxJSError(pPageView->GetPageViewWnd(),
          // csInfo);
        }

        pRuntime->ReleaseContext(pContext);
      }
    }
  } else {
    DoAction_NoJs(action, pDocument);
  }

  for (int32_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) {
    CPDF_Action subaction = action.GetSubAction(i);
    if (!ExecuteScreenAction(subaction, type, pDocument, pScreen, list))
      return FALSE;
  }

  return TRUE;
}

FX_BOOL CPDFSDK_ActionHandler::ExecuteBookMark(const CPDF_Action& action,
                                               CPDFSDK_Document* pDocument,
                                               CPDF_Bookmark* pBookmark,
                                               CFX_PtrList& list) {
  ASSERT(pDocument != NULL);

  CPDF_Dictionary* pDict = action.GetDict();
  if (list.Find(pDict))
    return FALSE;

  list.AddTail(pDict);

  CPDFDoc_Environment* pEnv = pDocument->GetEnv();
  ASSERT(pEnv);
  if (action.GetType() == CPDF_Action::JavaScript) {
    if (pEnv->IsJSInitiated()) {
      CFX_WideString swJS = action.GetJavaScript();
      if (!swJS.IsEmpty()) {
        IFXJS_Runtime* pRuntime = pDocument->GetJsRuntime();
        ASSERT(pRuntime != NULL);

        pRuntime->SetReaderDocument(pDocument);

        IFXJS_Context* pContext = pRuntime->NewContext();
        ASSERT(pContext != NULL);

        pContext->OnBookmark_MouseUp(pBookmark);

        CFX_WideString csInfo;
        FX_BOOL bRet = pContext->RunScript(swJS, csInfo);
        if (!bRet) {
          // CBCL_FormNotify::MsgBoxJSError(pPageView->GetPageViewWnd(),
          // csInfo);
        }

        pRuntime->ReleaseContext(pContext);
      }
    }
  } else {
    DoAction_NoJs(action, pDocument);
  }

  for (int32_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) {
    CPDF_Action subaction = action.GetSubAction(i);
    if (!ExecuteBookMark(subaction, pDocument, pBookmark, list))
      return FALSE;
  }

  return TRUE;
}

void CPDFSDK_ActionHandler::DoAction_NoJs(const CPDF_Action& action,
                                          CPDFSDK_Document* pDocument) {
  ASSERT(pDocument != NULL);

  switch (action.GetType()) {
    case CPDF_Action::GoTo:
      DoAction_GoTo(pDocument, action);
      break;
    case CPDF_Action::GoToR:
      DoAction_GoToR(pDocument, action);
      break;
    case CPDF_Action::GoToE:
      break;
    case CPDF_Action::Launch:
      DoAction_Launch(pDocument, action);
      break;
    case CPDF_Action::Thread:
      break;
    case CPDF_Action::URI:
      DoAction_URI(pDocument, action);
      break;
    case CPDF_Action::Sound:
      if (m_pMediaActionHandler) {
        m_pMediaActionHandler->DoAction_Sound(action, pDocument);
      }
      break;
    case CPDF_Action::Movie:
      if (m_pMediaActionHandler) {
        m_pMediaActionHandler->DoAction_Movie(action, pDocument);
      }
      break;
    case CPDF_Action::Hide:
      if (m_pFormActionHandler) {
        m_pFormActionHandler->DoAction_Hide(action, pDocument);
      }
      break;
    case CPDF_Action::Named:
      DoAction_Named(pDocument, action);
      break;
    case CPDF_Action::SubmitForm:
      if (m_pFormActionHandler) {
        m_pFormActionHandler->DoAction_SubmitForm(action, pDocument);
      }
      break;
    case CPDF_Action::ResetForm:
      if (m_pFormActionHandler) {
        m_pFormActionHandler->DoAction_ResetForm(action, pDocument);
      }
      break;
    case CPDF_Action::ImportData:
      if (m_pFormActionHandler) {
        m_pFormActionHandler->DoAction_ImportData(action, pDocument);
      }
      break;
    case CPDF_Action::JavaScript:
      ASSERT(FALSE);
      break;
    case CPDF_Action::SetOCGState:
      DoAction_SetOCGState(pDocument, action);
      break;
    case CPDF_Action::Rendition:
      if (m_pMediaActionHandler) {
        m_pMediaActionHandler->DoAction_Rendition(action, pDocument);
      }
      break;
    case CPDF_Action::Trans:
      break;
    case CPDF_Action::GoTo3DView:
      break;
    default:
      break;
  }
}

FX_BOOL CPDFSDK_ActionHandler::IsValidDocView(CPDFSDK_Document* pDocument) {
  ASSERT(pDocument != NULL);
  return TRUE;
}

void CPDFSDK_ActionHandler::DoAction_GoTo(CPDFSDK_Document* pDocument,
                                          const CPDF_Action& action) {
  ASSERT(action);

  CPDF_Document* pPDFDocument = pDocument->GetDocument();
  ASSERT(pPDFDocument != NULL);
  CPDFDoc_Environment* pApp = pDocument->GetEnv();
  ASSERT(pApp != NULL);

  CPDF_Dest MyDest = action.GetDest(pPDFDocument);
  int nPageIndex = MyDest.GetPageIndex(pPDFDocument);
  int nFitType = MyDest.GetZoomMode();
  const CPDF_Array* pMyArray = (CPDF_Array*)MyDest.GetObject();
  float* pPosAry = NULL;
  int sizeOfAry = 0;
  if (pMyArray != NULL) {
    pPosAry = new float[pMyArray->GetCount()];
    int j = 0;
    for (int i = 2; i < (int)pMyArray->GetCount(); i++) {
      pPosAry[j++] = pMyArray->GetFloat(i);
    }
    sizeOfAry = j;
  }
  pApp->FFI_DoGoToAction(nPageIndex, nFitType, pPosAry, sizeOfAry);
  if (pPosAry)
    delete[] pPosAry;
}

void CPDFSDK_ActionHandler::DoAction_GoToR(CPDFSDK_Document* pDocument,
                                           const CPDF_Action& action) {}

void CPDFSDK_ActionHandler::DoAction_Launch(CPDFSDK_Document* pDocument,
                                            const CPDF_Action& action) {}

void CPDFSDK_ActionHandler::DoAction_URI(CPDFSDK_Document* pDocument,
                                         const CPDF_Action& action) {
  ASSERT(action);

  CPDFDoc_Environment* pApp = pDocument->GetEnv();
  ASSERT(pApp != NULL);

  CFX_ByteString sURI = action.GetURI(pDocument->GetDocument());
  pApp->FFI_DoURIAction(sURI.c_str());
}

void CPDFSDK_ActionHandler::DoAction_Named(CPDFSDK_Document* pDocument,
                                           const CPDF_Action& action) {
  ASSERT(action);

  CFX_ByteString csName = action.GetNamedAction();
  pDocument->GetEnv()->FFI_ExecuteNamedAction(csName);
}

void CPDFSDK_ActionHandler::DoAction_SetOCGState(CPDFSDK_Document* pDocument,
                                                 const CPDF_Action& action) {}

void CPDFSDK_ActionHandler::RunFieldJavaScript(CPDFSDK_Document* pDocument,
                                               CPDF_FormField* pFormField,
                                               CPDF_AAction::AActionType type,
                                               PDFSDK_FieldAction& data,
                                               const CFX_WideString& script) {
  ASSERT(type != CPDF_AAction::Calculate);
  ASSERT(type != CPDF_AAction::Format);

  ASSERT(pDocument != NULL);

  IFXJS_Runtime* pRuntime = pDocument->GetJsRuntime();
  ASSERT(pRuntime != NULL);

  pRuntime->SetReaderDocument(pDocument);

  IFXJS_Context* pContext = pRuntime->NewContext();
  ASSERT(pContext != NULL);

  switch (type) {
    case CPDF_AAction::CursorEnter:
      pContext->OnField_MouseEnter(data.bModifier, data.bShift, pFormField);
      break;
    case CPDF_AAction::CursorExit:
      pContext->OnField_MouseExit(data.bModifier, data.bShift, pFormField);
      break;
    case CPDF_AAction::ButtonDown:
      pContext->OnField_MouseDown(data.bModifier, data.bShift, pFormField);
      break;
    case CPDF_AAction::ButtonUp:
      pContext->OnField_MouseUp(data.bModifier, data.bShift, pFormField);
      break;
    case CPDF_AAction::GetFocus:
      pContext->OnField_Focus(data.bModifier, data.bShift, pFormField,
                              data.sValue);
      break;
    case CPDF_AAction::LoseFocus:
      pContext->OnField_Blur(data.bModifier, data.bShift, pFormField,
                             data.sValue);
      break;
    case CPDF_AAction::KeyStroke:
      pContext->OnField_Keystroke(data.sChange, data.sChangeEx, data.bKeyDown,
                                  data.bModifier, data.nSelEnd, data.nSelStart,
                                  data.bShift, pFormField, data.sValue,
                                  data.bWillCommit, data.bFieldFull, data.bRC);
      break;
    case CPDF_AAction::Validate:
      pContext->OnField_Validate(data.sChange, data.sChangeEx, data.bKeyDown,
                                 data.bModifier, data.bShift, pFormField,
                                 data.sValue, data.bRC);
      break;
    default:
      ASSERT(FALSE);
      break;
  }

  CFX_WideString csInfo;
  FX_BOOL bRet = pContext->RunScript(script, csInfo);
  if (!bRet) {
    // CBCL_FormNotify::MsgBoxJSError(pPageView->GetPageViewWnd(), csInfo);
  }

  pRuntime->ReleaseContext(pContext);
}

void CPDFSDK_ActionHandler::RunDocumentOpenJavaScript(
    CPDFSDK_Document* pDocument,
    const CFX_WideString& sScriptName,
    const CFX_WideString& script) {
  ASSERT(pDocument != NULL);

  IFXJS_Runtime* pRuntime = pDocument->GetJsRuntime();
  ASSERT(pRuntime != NULL);

  pRuntime->SetReaderDocument(pDocument);

  IFXJS_Context* pContext = pRuntime->NewContext();
  ASSERT(pContext != NULL);

  pContext->OnDoc_Open(pDocument, sScriptName);

  CFX_WideString csInfo;
  FX_BOOL bRet = pContext->RunScript(script, csInfo);
  if (!bRet) {
    // CBCL_FormNotify::MsgBoxJSError(pPageView->GetPageViewWnd(), csInfo);
  }

  pRuntime->ReleaseContext(pContext);
}

void CPDFSDK_ActionHandler::RunDocumentPageJavaScript(
    CPDFSDK_Document* pDocument,
    CPDF_AAction::AActionType type,
    const CFX_WideString& script) {
  ASSERT(pDocument != NULL);

  IFXJS_Runtime* pRuntime = pDocument->GetJsRuntime();
  ASSERT(pRuntime != NULL);

  pRuntime->SetReaderDocument(pDocument);

  IFXJS_Context* pContext = pRuntime->NewContext();
  ASSERT(pContext != NULL);

  switch (type) {
    case CPDF_AAction::OpenPage:
      pContext->OnPage_Open(pDocument);
      break;
    case CPDF_AAction::ClosePage:
      pContext->OnPage_Close(pDocument);
      break;
    case CPDF_AAction::CloseDocument:
      pContext->OnDoc_WillClose(pDocument);
      break;
    case CPDF_AAction::SaveDocument:
      pContext->OnDoc_WillSave(pDocument);
      break;
    case CPDF_AAction::DocumentSaved:
      pContext->OnDoc_DidSave(pDocument);
      break;
    case CPDF_AAction::PrintDocument:
      pContext->OnDoc_WillPrint(pDocument);
      break;
    case CPDF_AAction::DocumentPrinted:
      pContext->OnDoc_DidPrint(pDocument);
      break;
    case CPDF_AAction::PageVisible:
      pContext->OnPage_InView(pDocument);
      break;
    case CPDF_AAction::PageInvisible:
      pContext->OnPage_OutView(pDocument);
      break;
    default:
      ASSERT(FALSE);
      break;
  }

  CFX_WideString csInfo;
  FX_BOOL bRet = pContext->RunScript(script, csInfo);
  if (!bRet) {
    // CBCL_FormNotify::MsgBoxJSError(pPageView->GetPageViewWnd(), csInfo);
  }

  pRuntime->ReleaseContext(pContext);
}

FX_BOOL CPDFSDK_FormActionHandler::DoAction_Hide(const CPDF_Action& action,
                                                 CPDFSDK_Document* pDocument) {
  ASSERT(pDocument != NULL);

  CPDFSDK_InterForm* pInterForm = (CPDFSDK_InterForm*)pDocument->GetInterForm();
  ASSERT(pInterForm != NULL);

  if (pInterForm->DoAction_Hide(action)) {
    pDocument->SetChangeMark();
    return TRUE;
  }

  return FALSE;
}

FX_BOOL CPDFSDK_FormActionHandler::DoAction_SubmitForm(
    const CPDF_Action& action,
    CPDFSDK_Document* pDocument) {
  ASSERT(pDocument != NULL);

  CPDFSDK_InterForm* pInterForm = (CPDFSDK_InterForm*)pDocument->GetInterForm();
  ASSERT(pInterForm != NULL);

  return pInterForm->DoAction_SubmitForm(action);
}

FX_BOOL CPDFSDK_FormActionHandler::DoAction_ResetForm(
    const CPDF_Action& action,
    CPDFSDK_Document* pDocument) {
  ASSERT(pDocument != NULL);

  CPDFSDK_InterForm* pInterForm = (CPDFSDK_InterForm*)pDocument->GetInterForm();
  ASSERT(pInterForm != NULL);

  if (pInterForm->DoAction_ResetForm(action)) {
    return TRUE;
  }

  return FALSE;
}

FX_BOOL CPDFSDK_FormActionHandler::DoAction_ImportData(
    const CPDF_Action& action,
    CPDFSDK_Document* pDocument) {
  ASSERT(pDocument != NULL);

  CPDFSDK_InterForm* pInterForm = (CPDFSDK_InterForm*)pDocument->GetInterForm();
  ASSERT(pInterForm != NULL);

  if (pInterForm->DoAction_ImportData(action)) {
    pDocument->SetChangeMark();
    return TRUE;
  }

  return FALSE;
}

FX_BOOL CPDFSDK_MediaActionHandler::DoAction_Rendition(
    const CPDF_Action& action,
    CPDFSDK_Document* pDocument) {
  return FALSE;
}

FX_BOOL CPDFSDK_MediaActionHandler::DoAction_Sound(
    const CPDF_Action& action,
    CPDFSDK_Document* pDocument) {
  return FALSE;
}

FX_BOOL CPDFSDK_MediaActionHandler::DoAction_Movie(
    const CPDF_Action& action,
    CPDFSDK_Document* pDocument) {
  return FALSE;
}
