// 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 "fpdfsdk/formfiller/cffl_combobox.h"

#include <utility>

#include "constants/form_flags.h"
#include "core/fpdfdoc/cpdf_bafontmap.h"
#include "fpdfsdk/cpdfsdk_widget.h"
#include "fpdfsdk/formfiller/cffl_interactiveformfiller.h"
#include "fpdfsdk/formfiller/cffl_perwindowdata.h"
#include "fpdfsdk/pwl/cpwl_combo_box.h"
#include "fpdfsdk/pwl/cpwl_edit.h"

CFFL_ComboBox::CFFL_ComboBox(CFFL_InteractiveFormFiller* pFormFiller,
                             CPDFSDK_Widget* pWidget)
    : CFFL_TextObject(pFormFiller, pWidget) {}

CFFL_ComboBox::~CFFL_ComboBox() {
  for (const auto& it : m_Maps)
    it.second->InvalidateFocusHandler(this);

  // See comment in cffl_formfiller.h.
  // The font map should be stored somewhere more appropriate so it will live
  // until the PWL_Edit is done with it. pdfium:566
  DestroyWindows();
}

CPWL_Wnd::CreateParams CFFL_ComboBox::GetCreateParam() {
  CPWL_Wnd::CreateParams cp = CFFL_TextObject::GetCreateParam();
  if (m_pWidget->GetFieldFlags() & pdfium::form_flags::kChoiceEdit)
    cp.dwFlags |= PCBS_ALLOWCUSTOMTEXT;

  cp.pFontMap = GetOrCreateFontMap();
  cp.pFocusHandler = this;
  return cp;
}

std::unique_ptr<CPWL_Wnd> CFFL_ComboBox::NewPWLWindow(
    const CPWL_Wnd::CreateParams& cp,
    std::unique_ptr<IPWL_FillerNotify::PerWindowData> pAttachedData) {
  static_cast<CFFL_PerWindowData*>(pAttachedData.get())->SetFormField(this);
  auto pWnd = std::make_unique<CPWL_ComboBox>(cp, std::move(pAttachedData));
  pWnd->Realize();
  pWnd->SetFillerNotify(m_pFormFiller.Get());

  int32_t nCurSel = m_pWidget->GetSelectedIndex(0);
  WideString swText;
  if (nCurSel < 0)
    swText = m_pWidget->GetValue();
  else
    swText = m_pWidget->GetOptionLabel(nCurSel);

  for (int32_t i = 0, sz = m_pWidget->CountOptions(); i < sz; i++)
    pWnd->AddString(m_pWidget->GetOptionLabel(i));

  pWnd->SetSelect(nCurSel);
  pWnd->SetText(swText);
  return std::move(pWnd);
}

bool CFFL_ComboBox::OnChar(CPDFSDK_Widget* pWidget,
                           uint32_t nChar,
                           Mask<FWL_EVENTFLAG> nFlags) {
  return CFFL_TextObject::OnChar(pWidget, nChar, nFlags);
}

bool CFFL_ComboBox::IsDataChanged(const CPDFSDK_PageView* pPageView) {
  auto* pWnd = GetPWLComboBox(pPageView);
  if (!pWnd)
    return false;

  int32_t nCurSel = pWnd->GetSelect();
  if (!(m_pWidget->GetFieldFlags() & pdfium::form_flags::kChoiceEdit))
    return nCurSel != m_pWidget->GetSelectedIndex(0);

  if (nCurSel >= 0)
    return nCurSel != m_pWidget->GetSelectedIndex(0);

  return pWnd->GetText() != m_pWidget->GetValue();
}

void CFFL_ComboBox::SaveData(const CPDFSDK_PageView* pPageView) {
  CPWL_ComboBox* pWnd = GetPWLComboBox(pPageView);
  if (!pWnd)
    return;

  WideString swText = pWnd->GetText();
  int32_t nCurSel = pWnd->GetSelect();
  bool bSetValue = false;
  if (m_pWidget->GetFieldFlags() & pdfium::form_flags::kChoiceEdit)
    bSetValue = (nCurSel < 0) || (swText != m_pWidget->GetOptionLabel(nCurSel));

  if (bSetValue) {
    m_pWidget->SetValue(swText);
  } else {
    m_pWidget->GetSelectedIndex(0);
    m_pWidget->SetOptionSelection(nCurSel);
  }
  ObservedPtr<CPDFSDK_Widget> observed_widget(m_pWidget.Get());
  ObservedPtr<CFFL_ComboBox> observed_this(this);
  m_pWidget->ResetFieldAppearance();
  if (!observed_widget)
    return;

  m_pWidget->UpdateField();
  if (!observed_widget || !observed_this)
    return;

  SetChangeMark();
}

void CFFL_ComboBox::GetActionData(const CPDFSDK_PageView* pPageView,
                                  CPDF_AAction::AActionType type,
                                  CFFL_FieldAction& fa) {
  switch (type) {
    case CPDF_AAction::kKeyStroke:
      if (CPWL_ComboBox* pComboBox = GetPWLComboBox(pPageView)) {
        if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
          fa.bFieldFull = pEdit->IsTextFull();
          std::tie(fa.nSelStart, fa.nSelEnd) = pEdit->GetSelection();
          fa.sValue = pEdit->GetText();
          fa.sChangeEx = GetSelectExportText();

          if (fa.bFieldFull) {
            fa.sChange.clear();
            fa.sChangeEx.clear();
          }
        }
      }
      break;
    case CPDF_AAction::kValidate:
      if (CPWL_ComboBox* pComboBox = GetPWLComboBox(pPageView)) {
        if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
          fa.sValue = pEdit->GetText();
        }
      }
      break;
    case CPDF_AAction::kLoseFocus:
    case CPDF_AAction::kGetFocus:
      fa.sValue = m_pWidget->GetValue();
      break;
    default:
      break;
  }
}

void CFFL_ComboBox::SetActionData(const CPDFSDK_PageView* pPageView,
                                  CPDF_AAction::AActionType type,
                                  const CFFL_FieldAction& fa) {
  switch (type) {
    case CPDF_AAction::kKeyStroke:
      if (CPWL_ComboBox* pComboBox = GetPWLComboBox(pPageView)) {
        if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
          pEdit->SetSelection(fa.nSelStart, fa.nSelEnd);
          pEdit->ReplaceSelection(fa.sChange);
        }
      }
      break;
    default:
      break;
  }
}

void CFFL_ComboBox::SavePWLWindowState(const CPDFSDK_PageView* pPageView) {
  CPWL_ComboBox* pComboBox = GetPWLComboBox(pPageView);
  if (!pComboBox)
    return;

  m_State.nIndex = pComboBox->GetSelect();

  CPWL_Edit* pEdit = pComboBox->GetEdit();
  if (!pEdit)
    return;

  std::tie(m_State.nStart, m_State.nEnd) = pEdit->GetSelection();
  m_State.sValue = pEdit->GetText();
}

void CFFL_ComboBox::RecreatePWLWindowFromSavedState(
    const CPDFSDK_PageView* pPageView) {
  CPWL_ComboBox* pComboBox = CreateOrUpdatePWLComboBox(pPageView);
  if (!pComboBox)
    return;

  if (m_State.nIndex >= 0) {
    pComboBox->SetSelect(m_State.nIndex);
    return;
  }

  CPWL_Edit* pEdit = pComboBox->GetEdit();
  if (!pEdit)
    return;

  pEdit->SetText(m_State.sValue);
  pEdit->SetSelection(m_State.nStart, m_State.nEnd);
}

bool CFFL_ComboBox::SetIndexSelected(int index, bool selected) {
  if (!IsValid() || !selected)
    return false;

  if (index < 0 || index >= m_pWidget->CountOptions())
    return false;

  CPWL_ComboBox* pWnd = GetPWLComboBox(GetCurPageView());
  if (!pWnd)
    return false;

  pWnd->SetSelect(index);
  return true;
}

bool CFFL_ComboBox::IsIndexSelected(int index) {
  if (!IsValid())
    return false;

  if (index < 0 || index >= m_pWidget->CountOptions())
    return false;

  CPWL_ComboBox* pWnd = GetPWLComboBox(GetCurPageView());
  return pWnd && index == pWnd->GetSelect();
}

#ifdef PDF_ENABLE_XFA
bool CFFL_ComboBox::IsFieldFull(const CPDFSDK_PageView* pPageView) {
  CPWL_ComboBox* pComboBox = GetPWLComboBox(pPageView);
  if (!pComboBox)
    return false;

  CPWL_Edit* pEdit = pComboBox->GetEdit();
  return pEdit && pEdit->IsTextFull();
}
#endif  // PDF_ENABLE_XFA

void CFFL_ComboBox::OnSetFocus(CPWL_Edit* pEdit) {
  pEdit->SetCharSet(FX_Charset::kChineseSimplified);
  pEdit->SetReadyToInput();
  m_pFormFiller->GetCallbackIface()->OnSetFieldInputFocus(pEdit->GetText());
}

WideString CFFL_ComboBox::GetSelectExportText() {
  WideString swRet;

  CPWL_ComboBox* pComboBox = GetPWLComboBox(GetCurPageView());
  int nExport = pComboBox ? pComboBox->GetSelect() : -1;

  if (nExport >= 0) {
    if (CPDF_FormField* pFormField = m_pWidget->GetFormField()) {
      swRet = pFormField->GetOptionValue(nExport);
      if (swRet.IsEmpty())
        swRet = pFormField->GetOptionLabel(nExport);
    }
  }

  return swRet;
}

CPWL_ComboBox* CFFL_ComboBox::GetPWLComboBox(
    const CPDFSDK_PageView* pPageView) const {
  return static_cast<CPWL_ComboBox*>(GetPWLWindow(pPageView));
}

CPWL_ComboBox* CFFL_ComboBox::CreateOrUpdatePWLComboBox(
    const CPDFSDK_PageView* pPageView) {
  return static_cast<CPWL_ComboBox*>(CreateOrUpdatePWLWindow(pPageView));
}
