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

#include <memory>
#include <utility>

#include "xfa/fde/cfde_textout.h"
#include "xfa/fwl/cfwl_event.h"
#include "xfa/fwl/cfwl_eventmouse.h"
#include "xfa/fwl/cfwl_messagekey.h"
#include "xfa/fwl/cfwl_messagemouse.h"
#include "xfa/fwl/cfwl_notedriver.h"
#include "xfa/fwl/cfwl_themebackground.h"
#include "xfa/fwl/cfwl_themetext.h"
#include "xfa/fwl/fwl_widgetdef.h"
#include "xfa/fwl/ifwl_themeprovider.h"

CFWL_PushButton::CFWL_PushButton(const CFWL_App* app)
    : CFWL_Widget(app, std::make_unique<CFWL_WidgetProperties>(), nullptr) {}

CFWL_PushButton::~CFWL_PushButton() = default;

FWL_Type CFWL_PushButton::GetClassID() const {
  return FWL_Type::PushButton;
}

void CFWL_PushButton::SetStates(uint32_t dwStates) {
  if (dwStates & FWL_WGTSTATE_Disabled) {
    GetProperties()->m_dwStates = FWL_WGTSTATE_Disabled;
    return;
  }
  CFWL_Widget::SetStates(dwStates);
}

void CFWL_PushButton::Update() {
  if (IsLocked())
    return;
  if (!GetProperties()->m_pThemeProvider)
    GetProperties()->m_pThemeProvider = GetAvailableTheme();

  m_ClientRect = GetClientRect();
  m_CaptionRect = m_ClientRect;
}

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

  IFWL_ThemeProvider* pTheme = GetProperties()->m_pThemeProvider.Get();
  if (!pTheme)
    return;

  if (HasBorder())
    DrawBorder(pGraphics, CFWL_Part::Border, pTheme, matrix);
  DrawBkground(pGraphics, pTheme, &matrix);
}

void CFWL_PushButton::DrawBkground(CXFA_Graphics* pGraphics,
                                   IFWL_ThemeProvider* pTheme,
                                   const CFX_Matrix* pMatrix) {
  CFWL_ThemeBackground param;
  param.m_pWidget = this;
  param.m_iPart = CFWL_Part::Background;
  param.m_dwStates = GetPartStates();
  param.m_pGraphics = pGraphics;
  if (pMatrix)
    param.m_matrix.Concat(*pMatrix);
  param.m_PartRect = m_ClientRect;
  if (GetProperties()->m_dwStates & FWL_WGTSTATE_Focused)
    param.m_pRtData = &m_CaptionRect;
  pTheme->DrawBackground(param);
}

uint32_t CFWL_PushButton::GetPartStates() {
  uint32_t dwStates = CFWL_PartState_Normal;
  if (GetProperties()->m_dwStates & FWL_WGTSTATE_Focused)
    dwStates |= CFWL_PartState_Focused;
  if (GetProperties()->m_dwStates & FWL_WGTSTATE_Disabled)
    dwStates = CFWL_PartState_Disabled;
  else if (GetProperties()->m_dwStates & FWL_STATE_PSB_Pressed)
    dwStates |= CFWL_PartState_Pressed;
  else if (GetProperties()->m_dwStates & FWL_STATE_PSB_Hovered)
    dwStates |= CFWL_PartState_Hovered;
  return dwStates;
}

void CFWL_PushButton::OnProcessMessage(CFWL_Message* pMessage) {
  if (!pMessage)
    return;
  if (!IsEnabled())
    return;

  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* pMsg = static_cast<CFWL_MessageMouse*>(pMessage);
      switch (pMsg->m_dwCmd) {
        case FWL_MouseCommand::LeftButtonDown:
          OnLButtonDown(pMsg);
          break;
        case FWL_MouseCommand::LeftButtonUp:
          OnLButtonUp(pMsg);
          break;
        case FWL_MouseCommand::Move:
          OnMouseMove(pMsg);
          break;
        case FWL_MouseCommand::Leave:
          OnMouseLeave(pMsg);
          break;
        default:
          break;
      }
      break;
    }
    case CFWL_Message::Type::kKey: {
      CFWL_MessageKey* pKey = static_cast<CFWL_MessageKey*>(pMessage);
      if (pKey->m_dwCmd == CFWL_MessageKey::Type::kKeyDown)
        OnKeyDown(pKey);
      break;
    }
    default:
      break;
  }
  // Dst target could be |this|, continue only if not destroyed by above.
  if (pMessage->GetDstTarget())
    CFWL_Widget::OnProcessMessage(pMessage);
}

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

void CFWL_PushButton::OnFocusChanged(CFWL_Message* pMsg, bool bSet) {
  if (bSet)
    GetProperties()->m_dwStates |= FWL_WGTSTATE_Focused;
  else
    GetProperties()->m_dwStates &= ~FWL_WGTSTATE_Focused;

  RepaintRect(m_ClientRect);
}

void CFWL_PushButton::OnLButtonDown(CFWL_MessageMouse* pMsg) {
  m_bBtnDown = true;
  GetProperties()->m_dwStates |= FWL_STATE_PSB_Hovered;
  GetProperties()->m_dwStates |= FWL_STATE_PSB_Pressed;
  RepaintRect(m_ClientRect);
}

void CFWL_PushButton::OnLButtonUp(CFWL_MessageMouse* pMsg) {
  m_bBtnDown = false;
  if (m_ClientRect.Contains(pMsg->m_pos)) {
    GetProperties()->m_dwStates &= ~FWL_STATE_PSB_Pressed;
    GetProperties()->m_dwStates |= FWL_STATE_PSB_Hovered;
  } else {
    GetProperties()->m_dwStates &= ~FWL_STATE_PSB_Hovered;
    GetProperties()->m_dwStates &= ~FWL_STATE_PSB_Pressed;
  }
  if (m_ClientRect.Contains(pMsg->m_pos)) {
    CFWL_Event wmClick(CFWL_Event::Type::Click, this);
    DispatchEvent(&wmClick);
  }
  RepaintRect(m_ClientRect);
}

void CFWL_PushButton::OnMouseMove(CFWL_MessageMouse* pMsg) {
  bool bRepaint = false;
  if (m_bBtnDown) {
    if (m_ClientRect.Contains(pMsg->m_pos)) {
      if ((GetProperties()->m_dwStates & FWL_STATE_PSB_Pressed) == 0) {
        GetProperties()->m_dwStates |= FWL_STATE_PSB_Pressed;
        bRepaint = true;
      }
      if (GetProperties()->m_dwStates & FWL_STATE_PSB_Hovered) {
        GetProperties()->m_dwStates &= ~FWL_STATE_PSB_Hovered;
        bRepaint = true;
      }
    } else {
      if (GetProperties()->m_dwStates & FWL_STATE_PSB_Pressed) {
        GetProperties()->m_dwStates &= ~FWL_STATE_PSB_Pressed;
        bRepaint = true;
      }
      if ((GetProperties()->m_dwStates & FWL_STATE_PSB_Hovered) == 0) {
        GetProperties()->m_dwStates |= FWL_STATE_PSB_Hovered;
        bRepaint = true;
      }
    }
  } else {
    if (!m_ClientRect.Contains(pMsg->m_pos))
      return;
    if ((GetProperties()->m_dwStates & FWL_STATE_PSB_Hovered) == 0) {
      GetProperties()->m_dwStates |= FWL_STATE_PSB_Hovered;
      bRepaint = true;
    }
  }
  if (bRepaint)
    RepaintRect(m_ClientRect);
}

void CFWL_PushButton::OnMouseLeave(CFWL_MessageMouse* pMsg) {
  m_bBtnDown = false;
  GetProperties()->m_dwStates &= ~FWL_STATE_PSB_Hovered;
  GetProperties()->m_dwStates &= ~FWL_STATE_PSB_Pressed;
  RepaintRect(m_ClientRect);
}

void CFWL_PushButton::OnKeyDown(CFWL_MessageKey* pMsg) {
  if (pMsg->m_dwKeyCode != XFA_FWL_VKEY_Return)
    return;

  CFWL_EventMouse wmMouse(this);
  wmMouse.m_dwCmd = FWL_MouseCommand::LeftButtonUp;
  DispatchEvent(&wmMouse);
  if (!wmMouse.GetSrcTarget())
    return;

  CFWL_Event wmClick(CFWL_Event::Type::Click, this);
  DispatchEvent(&wmClick);
}
