// 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/formfiller/FormFiller.h"
#include "../../include/formfiller/FFL_FormFiller.h"
#include "../../include/formfiller/FFL_Notify.h"
// #include "../../include/formfiller/FFL_ComboBox.h"
// #include "../../include/formfiller/FFL_Module.h"

/* -------------------------------- CFFL_Notify ------------------------------
 */

//#pragma warning(disable: 4800)

CFFL_Notify::CFFL_Notify(CFFL_FormFiller* pFormFiller)
    : m_bDoActioning(FALSE), m_nNotifyFlag(0) {
  ASSERT(pFormFiller != NULL);
}

CFFL_Notify::~CFFL_Notify() {}

void CFFL_Notify::BeforeNotify() {
  m_nNotifyFlag++;
}

void CFFL_Notify::AfterNotify() {
  m_nNotifyFlag--;
}

FX_BOOL CFFL_Notify::OnMouseUp(FX_BOOL& bExit) {
  BeforeNotify();
  FX_BOOL bRet =
      FALSE;  // DoAAction(CPDF_AAction::AActionType::ButtonUp, bExit);
  AfterNotify();
  return bRet;
}

FX_BOOL CFFL_Notify::OnMouseDown(FX_BOOL& bExit) {
  BeforeNotify();
  FX_BOOL bRet =
      FALSE;  // DoAAction(CPDF_AAction::AActionType::ButtonDown, bExit);
  AfterNotify();
  return bRet;
}

FX_BOOL CFFL_Notify::OnMouseEnter(FX_BOOL& bExit) {
  BeforeNotify();
  FX_BOOL bRet =
      FALSE;  // DoAAction(CPDF_AAction::AActionType::CursorEnter, bExit);
  AfterNotify();
  return bRet;
}

FX_BOOL CFFL_Notify::OnMouseExit(FX_BOOL& bExit) {
  BeforeNotify();
  FX_BOOL bRet =
      FALSE;  // DoAAction(CPDF_AAction::AActionType::CursorExit, bExit);
  AfterNotify();
  return bRet;
}

FX_BOOL CFFL_Notify::OnSetFocus(FX_BOOL& bExit) {
  BeforeNotify();
  FX_BOOL bRet =
      FALSE;  // DoAAction(CPDF_AAction::AActionType::GetFocus, bExit);
  AfterNotify();
  return bRet;
}

FX_BOOL CFFL_Notify::OnKillFocus(FX_BOOL& bExit) {
  BeforeNotify();
  FX_BOOL bRet =
      FALSE;  // DoAAction(CPDF_AAction::AActionType::LoseFocus, bExit);
  AfterNotify();
  return bRet;
}

FX_BOOL CFFL_Notify::OnCalculate() {
  return TRUE;
}

FX_BOOL CFFL_Notify::OnFormat(int iCommitKey) {
  return TRUE;
}

FX_BOOL CFFL_Notify::OnKeyStroke(CPDF_FormField* pFormField,
                                 int nCommitKey,
                                 CFX_WideString& strValue,
                                 CFX_WideString& strChange,
                                 const CFX_WideString& strChangeEx,
                                 FX_BOOL bKeyDown,
                                 FX_BOOL bModifier,
                                 FX_BOOL bShift,
                                 FX_BOOL bWillCommit,
                                 FX_BOOL bFieldFull,
                                 int& nSelStart,
                                 int& nSelEnd,
                                 FX_BOOL& bRC) {
  return TRUE;
}

FX_BOOL CFFL_Notify::OnValidate(CPDF_FormField* pFormField,
                                CFX_WideString& strValue,
                                CFX_WideString& strChange,
                                const CFX_WideString& strChangeEx,
                                FX_BOOL bKeyDown,
                                FX_BOOL bModifier,
                                FX_BOOL bShift,
                                FX_BOOL& bRC) {
  return TRUE;
}

FX_BOOL CFFL_Notify::DoAAction(CPDF_AAction::AActionType eAAT, FX_BOOL& bExit) {
  if (m_bDoActioning)
    return FALSE;

  CPDF_Action action;
  if (!FindAAction(eAAT, action))
    return FALSE;

  m_bDoActioning = TRUE;
  ExecuteActionTree(eAAT, action, bExit);
  m_bDoActioning = FALSE;
  return TRUE;
}

FX_BOOL CFFL_Notify::ExecuteActionTree(CPDF_AAction::AActionType eAAT,
                                       CPDF_Action& action,
                                       FX_BOOL& bExit) {
  if (!ExecuteAction(eAAT, action, bExit))
    return FALSE;
  if (bExit)
    return TRUE;

  for (int32_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) {
    CPDF_Action subaction = action.GetSubAction(i);
    if (!ExecuteActionTree(eAAT, subaction, bExit))
      return FALSE;
    if (bExit)
      break;
  }

  return TRUE;
}

FX_BOOL CFFL_Notify::FindAAction(CPDF_AAction::AActionType eAAT,
                                 CPDF_Action& action) {
  return FALSE;
}

FX_BOOL CFFL_Notify::FindAAction(CPDF_AAction aaction,
                                 CPDF_AAction::AActionType eAAT,
                                 CPDF_Action& action) {
  CPDF_Action MyAction;

  if (aaction.ActionExist(eAAT)) {
    MyAction = aaction.GetAction(eAAT);
  } else
    return FALSE;

  if (MyAction.GetType() == CPDF_Action::Unknown)
    return FALSE;

  action = MyAction;

  return TRUE;
}

FX_BOOL CFFL_Notify::ExecuteAction(CPDF_AAction::AActionType eAAT,
                                   CPDF_Action& action,
                                   FX_BOOL& bExit) {
  return FALSE;
}
//#pragma warning(default: 4800)
