// 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 "xfa/fwl/cfwl_datetimepicker.h"

#include <utility>

#include "xfa/fwl/cfwl_app.h"
#include "xfa/fwl/cfwl_event.h"
#include "xfa/fwl/cfwl_eventselectchanged.h"
#include "xfa/fwl/cfwl_messagemouse.h"
#include "xfa/fwl/cfwl_messagesetfocus.h"
#include "xfa/fwl/cfwl_notedriver.h"
#include "xfa/fwl/cfwl_themebackground.h"
#include "xfa/fwl/cfwl_widgetmgr.h"
#include "xfa/fwl/ifwl_themeprovider.h"

namespace {

const int kDateTimePickerHeight = 20;

}  // namespace
CFWL_DateTimePicker::CFWL_DateTimePicker(CFWL_App* app)
    : CFWL_Widget(app,
                  Properties{0, FWL_STYLEEXT_DTP_ShortDateFormat, 0},
                  nullptr),
      m_pEdit(cppgc::MakeGarbageCollected<CFWL_DateTimeEdit>(
          app->GetHeap()->GetAllocationHandle(),
          app,
          Properties(),
          this)),
      m_pMonthCal(cppgc::MakeGarbageCollected<CFWL_MonthCalendar>(
          app->GetHeap()->GetAllocationHandle(),
          app,
          Properties{FWL_WGTSTYLE_Popup | FWL_WGTSTYLE_Border, 0,
                     FWL_WGTSTATE_Invisible},
          this)) {
  m_pMonthCal->SetWidgetRect(
      CFX_RectF(0, 0, m_pMonthCal->GetAutosizedWidgetRect().Size()));

  RegisterEventTarget(m_pMonthCal);
  RegisterEventTarget(m_pEdit);
}

CFWL_DateTimePicker::~CFWL_DateTimePicker() = default;

void CFWL_DateTimePicker::PreFinalize() {
  UnregisterEventTarget();
  CFWL_Widget::PreFinalize();
}

void CFWL_DateTimePicker::Trace(cppgc::Visitor* visitor) const {
  CFWL_Widget::Trace(visitor);
  visitor->Trace(m_pEdit);
  visitor->Trace(m_pMonthCal);
}

FWL_Type CFWL_DateTimePicker::GetClassID() const {
  return FWL_Type::DateTimePicker;
}

void CFWL_DateTimePicker::Update() {
  if (IsLocked())
    return;

  m_ClientRect = GetClientRect();
  m_pEdit->SetWidgetRect(m_ClientRect);
  ResetEditAlignment();
  m_pEdit->Update();

  m_fBtn = GetThemeProvider()->GetScrollBarWidth();
  CFX_RectF rtMonthCal = m_pMonthCal->GetAutosizedWidgetRect();
  CFX_RectF rtPopUp(rtMonthCal.left, rtMonthCal.top + kDateTimePickerHeight,
                    rtMonthCal.width, rtMonthCal.height);
  m_pMonthCal->SetWidgetRect(rtPopUp);
  m_pMonthCal->Update();
}

FWL_WidgetHit CFWL_DateTimePicker::HitTest(const CFX_PointF& point) {
  CFX_RectF rect(0, 0, m_WidgetRect.width, m_WidgetRect.height);
  if (rect.Contains(point))
    return FWL_WidgetHit::Edit;
  if (NeedsToShowButton())
    rect.width += m_fBtn;
  if (rect.Contains(point))
    return FWL_WidgetHit::Client;
  if (IsMonthCalendarVisible()) {
    if (m_pMonthCal->GetWidgetRect().Contains(point))
      return FWL_WidgetHit::Client;
  }
  return FWL_WidgetHit::Unknown;
}

void CFWL_DateTimePicker::DrawWidget(CXFA_Graphics* pGraphics,
                                     const CFX_Matrix& matrix) {
  if (!pGraphics)
    return;

  if (HasBorder())
    DrawBorder(pGraphics, CFWL_Part::Border, matrix);

  if (!m_BtnRect.IsEmpty())
    DrawDropDownButton(pGraphics, &matrix);

  if (m_pEdit) {
    CFX_RectF rtEdit = m_pEdit->GetWidgetRect();
    CFX_Matrix mt(1, 0, 0, 1, rtEdit.left, rtEdit.top);
    mt.Concat(matrix);
    m_pEdit->DrawWidget(pGraphics, mt);
  }
  if (!IsMonthCalendarVisible())
    return;

  CFX_RectF rtMonth = m_pMonthCal->GetWidgetRect();
  CFX_Matrix mt(1, 0, 0, 1, rtMonth.left, rtMonth.top);
  mt.Concat(matrix);
  m_pMonthCal->DrawWidget(pGraphics, mt);
}

void CFWL_DateTimePicker::GetCurSel(int32_t& iYear,
                                    int32_t& iMonth,
                                    int32_t& iDay) {
  iYear = m_iYear;
  iMonth = m_iMonth;
  iDay = m_iDay;
}

void CFWL_DateTimePicker::SetCurSel(int32_t iYear,
                                    int32_t iMonth,
                                    int32_t iDay) {
  if (iYear <= 0 || iYear >= 3000)
    return;
  if (iMonth <= 0 || iMonth >= 13)
    return;
  if (iDay <= 0 || iDay >= 32)
    return;

  m_iYear = iYear;
  m_iMonth = iMonth;
  m_iDay = iDay;
  m_pMonthCal->SetSelect(iYear, iMonth, iDay);
}

void CFWL_DateTimePicker::SetEditText(const WideString& wsText) {
  if (!m_pEdit)
    return;

  m_pEdit->SetText(wsText);
  RepaintRect(m_ClientRect);

  CFWL_Event ev(CFWL_Event::Type::EditChanged);
  DispatchEvent(&ev);
}

WideString CFWL_DateTimePicker::GetEditText() const {
  return m_pEdit ? m_pEdit->GetText() : WideString();
}

int32_t CFWL_DateTimePicker::GetEditTextLength() const {
  return m_pEdit ? m_pEdit->GetTextLength() : 0;
}

CFX_RectF CFWL_DateTimePicker::GetBBox() const {
  CFX_RectF rect = m_WidgetRect;
  if (NeedsToShowButton())
    rect.width += m_fBtn;
  if (!IsMonthCalendarVisible())
    return rect;

  CFX_RectF rtMonth = m_pMonthCal->GetWidgetRect();
  rtMonth.Offset(m_WidgetRect.left, m_WidgetRect.top);
  rect.Union(rtMonth);
  return rect;
}

void CFWL_DateTimePicker::ModifyEditStylesEx(uint32_t dwStylesExAdded,
                                             uint32_t dwStylesExRemoved) {
  m_pEdit->ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
}

void CFWL_DateTimePicker::DrawDropDownButton(CXFA_Graphics* pGraphics,
                                             const CFX_Matrix* pMatrix) {
  CFWL_ThemeBackground param;
  param.m_pWidget = this;
  param.m_iPart = CFWL_Part::DropDownButton;
  param.m_dwStates = m_iBtnState;
  param.m_pGraphics = pGraphics;
  param.m_PartRect = m_BtnRect;
  if (pMatrix)
    param.m_matrix.Concat(*pMatrix);
  GetThemeProvider()->DrawBackground(param);
}

WideString CFWL_DateTimePicker::FormatDateString(int32_t iYear,
                                                 int32_t iMonth,
                                                 int32_t iDay) {
  if (m_Properties.m_dwStyleExes & FWL_STYLEEXT_DTP_ShortDateFormat)
    return WideString::Format(L"%d-%d-%d", iYear, iMonth, iDay);

  return WideString::Format(L"%d Year %d Month %d Day", iYear, iMonth, iDay);
}

void CFWL_DateTimePicker::ShowMonthCalendar(bool bActivate) {
  if (IsMonthCalendarVisible() == bActivate)
    return;

  if (bActivate) {
    CFX_RectF rtMonthCal = m_pMonthCal->GetAutosizedWidgetRect();
    float fPopupMin = rtMonthCal.height;
    float fPopupMax = rtMonthCal.height;
    CFX_RectF rtAnchor = m_WidgetRect;
    rtAnchor.width = rtMonthCal.width;
    rtMonthCal.left = m_ClientRect.left;
    rtMonthCal.top = rtAnchor.Height();
    GetPopupPos(fPopupMin, fPopupMax, rtAnchor, &rtMonthCal);
    m_pMonthCal->SetWidgetRect(rtMonthCal);
    if (m_iYear > 0 && m_iMonth > 0 && m_iDay > 0)
      m_pMonthCal->SetSelect(m_iYear, m_iMonth, m_iDay);
    m_pMonthCal->Update();
  }
  if (bActivate)
    m_pMonthCal->RemoveStates(FWL_WGTSTATE_Invisible);
  else
    m_pMonthCal->SetStates(FWL_WGTSTATE_Invisible);

  if (bActivate) {
    CFWL_MessageSetFocus msg(m_pEdit, m_pMonthCal);
    m_pEdit->GetDelegate()->OnProcessMessage(&msg);
  }

  CFX_RectF rtInvalidate(0, 0, m_WidgetRect.width, m_WidgetRect.height);
  CFX_RectF rtCal = m_pMonthCal->GetWidgetRect();
  rtInvalidate.Union(rtCal);
  rtInvalidate.Inflate(2, 2);
  RepaintRect(rtInvalidate);
}

bool CFWL_DateTimePicker::IsMonthCalendarVisible() const {
  return m_pMonthCal && m_pMonthCal->IsVisible();
}

void CFWL_DateTimePicker::ResetEditAlignment() {
  if (!m_pEdit)
    return;

  uint32_t dwAdd = 0;
  switch (m_Properties.m_dwStyleExes & FWL_STYLEEXT_DTP_EditHAlignMask) {
    case FWL_STYLEEXT_DTP_EditHCenter: {
      dwAdd |= FWL_STYLEEXT_EDT_HCenter;
      break;
    }
    case FWL_STYLEEXT_DTP_EditHFar: {
      dwAdd |= FWL_STYLEEXT_EDT_HFar;
      break;
    }
    default: {
      dwAdd |= FWL_STYLEEXT_EDT_HNear;
      break;
    }
  }
  switch (m_Properties.m_dwStyleExes & FWL_STYLEEXT_DTP_EditVAlignMask) {
    case FWL_STYLEEXT_DTP_EditVCenter: {
      dwAdd |= FWL_STYLEEXT_EDT_VCenter;
      break;
    }
    case FWL_STYLEEXT_DTP_EditVFar: {
      dwAdd |= FWL_STYLEEXT_EDT_VFar;
      break;
    }
    default: {
      dwAdd |= FWL_STYLEEXT_EDT_VNear;
      break;
    }
  }
  if (m_Properties.m_dwStyleExes & FWL_STYLEEXT_DTP_EditJustified)
    dwAdd |= FWL_STYLEEXT_EDT_Justified;

  m_pEdit->ModifyStylesEx(dwAdd, FWL_STYLEEXT_EDT_HAlignMask |
                                     FWL_STYLEEXT_EDT_HAlignModeMask |
                                     FWL_STYLEEXT_EDT_VAlignMask);
}

void CFWL_DateTimePicker::ProcessSelChanged(int32_t iYear,
                                            int32_t iMonth,
                                            int32_t iDay) {
  m_iYear = iYear;
  m_iMonth = iMonth;
  m_iDay = iDay;
  m_pEdit->SetText(FormatDateString(m_iYear, m_iMonth, m_iDay));
  m_pEdit->Update();
  RepaintRect(m_ClientRect);

  CFWL_EventSelectChanged ev(this);
  ev.iYear = m_iYear;
  ev.iMonth = m_iMonth;
  ev.iDay = m_iDay;
  DispatchEvent(&ev);
}

bool CFWL_DateTimePicker::NeedsToShowButton() const {
  return m_Properties.m_dwStates & FWL_WGTSTATE_Focused ||
         m_pMonthCal->GetStates() & FWL_WGTSTATE_Focused ||
         m_pEdit->GetStates() & FWL_WGTSTATE_Focused;
}

void CFWL_DateTimePicker::OnProcessMessage(CFWL_Message* pMessage) {
  switch (pMessage->GetType()) {
    case CFWL_Message::Type::kSetFocus:
      OnFocusChanged(pMessage, true);
      break;
    case CFWL_Message::Type::kKillFocus:
      OnFocusChanged(pMessage, false);
      break;
    case CFWL_Message::Type::kMouse: {
      CFWL_MessageMouse* pMouse = static_cast<CFWL_MessageMouse*>(pMessage);
      switch (pMouse->m_dwCmd) {
        case FWL_MouseCommand::LeftButtonDown:
          OnLButtonDown(pMouse);
          break;
        case FWL_MouseCommand::LeftButtonUp:
          OnLButtonUp(pMouse);
          break;
        case FWL_MouseCommand::Move:
          OnMouseMove(pMouse);
          break;
        case FWL_MouseCommand::Leave:
          OnMouseLeave(pMouse);
          break;
        default:
          break;
      }
      break;
    }
    case CFWL_Message::Type::kKey: {
      if (m_pEdit->GetStates() & FWL_WGTSTATE_Focused) {
        m_pEdit->GetDelegate()->OnProcessMessage(pMessage);
        return;
      }
      break;
    }
    default:
      break;
  }
  // Dst target could be |this|, continue only if not destroyed by above.
  if (pMessage->GetDstTarget())
    CFWL_Widget::OnProcessMessage(pMessage);
}

void CFWL_DateTimePicker::OnDrawWidget(CXFA_Graphics* pGraphics,
                                       const CFX_Matrix& matrix) {
  DrawWidget(pGraphics, matrix);
}

void CFWL_DateTimePicker::OnFocusChanged(CFWL_Message* pMsg, bool bSet) {
  if (!pMsg)
    return;

  CFX_RectF rtInvalidate(m_BtnRect);
  if (bSet) {
    m_Properties.m_dwStates |= FWL_WGTSTATE_Focused;
    if (m_pEdit && !(m_pEdit->GetStylesEx() & FWL_STYLEEXT_EDT_ReadOnly)) {
      m_BtnRect =
          CFX_RectF(m_WidgetRect.width, 0, m_fBtn, m_WidgetRect.height - 1);
    }
    rtInvalidate = m_BtnRect;
    pMsg->SetDstTarget(m_pEdit);
    m_pEdit->GetDelegate()->OnProcessMessage(pMsg);
  } else {
    m_Properties.m_dwStates &= ~FWL_WGTSTATE_Focused;
    m_BtnRect = CFX_RectF();
    if (IsMonthCalendarVisible())
      ShowMonthCalendar(false);
    if (m_pEdit->GetStates() & FWL_WGTSTATE_Focused) {
      pMsg->SetSrcTarget(m_pEdit);
      m_pEdit->GetDelegate()->OnProcessMessage(pMsg);
    }
  }
  rtInvalidate.Inflate(2, 2);
  RepaintRect(rtInvalidate);
}

void CFWL_DateTimePicker::OnLButtonDown(CFWL_MessageMouse* pMsg) {
  if (!pMsg)
    return;
  if (!m_BtnRect.Contains(pMsg->m_pos))
    return;

  if (IsMonthCalendarVisible()) {
    ShowMonthCalendar(false);
    return;
  }
  ShowMonthCalendar(true);

  m_bLBtnDown = true;
  RepaintRect(m_ClientRect);
}

void CFWL_DateTimePicker::OnLButtonUp(CFWL_MessageMouse* pMsg) {
  if (!pMsg)
    return;

  m_bLBtnDown = false;
  if (m_BtnRect.Contains(pMsg->m_pos))
    m_iBtnState = CFWL_PartState_Hovered;
  else
    m_iBtnState = CFWL_PartState_Normal;
  RepaintRect(m_BtnRect);
}

void CFWL_DateTimePicker::OnMouseMove(CFWL_MessageMouse* pMsg) {
  if (!m_BtnRect.Contains(pMsg->m_pos))
    m_iBtnState = CFWL_PartState_Normal;
  RepaintRect(m_BtnRect);
}

void CFWL_DateTimePicker::OnMouseLeave(CFWL_MessageMouse* pMsg) {
  if (!pMsg)
    return;
  m_iBtnState = CFWL_PartState_Normal;
  RepaintRect(m_BtnRect);
}

void CFWL_DateTimePicker::GetPopupPos(float fMinHeight,
                                      float fMaxHeight,
                                      const CFX_RectF& rtAnchor,
                                      CFX_RectF* pPopupRect) {
  GetWidgetMgr()->GetAdapterPopupPos(this, fMinHeight, fMaxHeight, rtAnchor,
                                     pPopupRect);
}

void CFWL_DateTimePicker::ClearText() {
  m_pEdit->ClearText();
}

void CFWL_DateTimePicker::SelectAll() {
  m_pEdit->SelectAll();
}

void CFWL_DateTimePicker::ClearSelection() {
  m_pEdit->ClearSelection();
}

Optional<WideString> CFWL_DateTimePicker::Copy() {
  return m_pEdit->Copy();
}

Optional<WideString> CFWL_DateTimePicker::Cut() {
  return m_pEdit->Cut();
}

bool CFWL_DateTimePicker::Paste(const WideString& wsPaste) {
  return m_pEdit->Paste(wsPaste);
}

bool CFWL_DateTimePicker::Undo() {
  return m_pEdit->Undo();
}

bool CFWL_DateTimePicker::Redo() {
  return m_pEdit->Redo();
}

bool CFWL_DateTimePicker::CanUndo() {
  return m_pEdit->CanUndo();
}

bool CFWL_DateTimePicker::CanRedo() {
  return m_pEdit->CanRedo();
}
