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

#include <algorithm>

#include "xfa/fwl/core/cfwl_themebackground.h"
#include "xfa/fwl/core/cfwl_themepart.h"
#include "xfa/fwl/core/cfwl_themetext.h"
#include "xfa/fwl/theme/cfwl_barcodetp.h"
#include "xfa/fwl/theme/cfwl_carettp.h"
#include "xfa/fwl/theme/cfwl_checkboxtp.h"
#include "xfa/fwl/theme/cfwl_comboboxtp.h"
#include "xfa/fwl/theme/cfwl_datetimepickertp.h"
#include "xfa/fwl/theme/cfwl_edittp.h"
#include "xfa/fwl/theme/cfwl_formtp.h"
#include "xfa/fwl/theme/cfwl_listboxtp.h"
#include "xfa/fwl/theme/cfwl_monthcalendartp.h"
#include "xfa/fwl/theme/cfwl_pictureboxtp.h"
#include "xfa/fwl/theme/cfwl_pushbuttontp.h"
#include "xfa/fwl/theme/cfwl_scrollbartp.h"

CFWL_Theme::CFWL_Theme() {
  m_ThemesArray.push_back(std::unique_ptr<CFWL_WidgetTP>(new CFWL_FormTP));
  m_ThemesArray.push_back(
      std::unique_ptr<CFWL_WidgetTP>(new CFWL_PushButtonTP));
  m_ThemesArray.push_back(std::unique_ptr<CFWL_WidgetTP>(new CFWL_CheckBoxTP));
  m_ThemesArray.push_back(std::unique_ptr<CFWL_WidgetTP>(new CFWL_ListBoxTP));
  m_ThemesArray.push_back(
      std::unique_ptr<CFWL_WidgetTP>(new CFWL_PictureBoxTP));
  m_ThemesArray.push_back(std::unique_ptr<CFWL_WidgetTP>(new CFWL_ScrollBarTP));
  m_ThemesArray.push_back(std::unique_ptr<CFWL_WidgetTP>(new CFWL_EditTP));
  m_ThemesArray.push_back(std::unique_ptr<CFWL_WidgetTP>(new CFWL_ComboBoxTP));
  m_ThemesArray.push_back(std::unique_ptr<CFWL_WidgetTP>(new CFWL_BarcodeTP));
  m_ThemesArray.push_back(
      std::unique_ptr<CFWL_WidgetTP>(new CFWL_DateTimePickerTP));
  m_ThemesArray.push_back(
      std::unique_ptr<CFWL_WidgetTP>(new CFWL_MonthCalendarTP));
  m_ThemesArray.push_back(std::unique_ptr<CFWL_WidgetTP>(new CFWL_CaretTP));
}

CFWL_Theme::~CFWL_Theme() {}

bool CFWL_Theme::IsValidWidget(IFWL_Widget* pWidget) {
  return !!GetTheme(pWidget);
}

uint32_t CFWL_Theme::GetThemeID(IFWL_Widget* pWidget) {
  return GetTheme(pWidget)->GetThemeID(pWidget);
}

uint32_t CFWL_Theme::SetThemeID(IFWL_Widget* pWidget,
                                uint32_t dwThemeID,
                                FX_BOOL bChildren) {
  uint32_t dwID = 0;
  for (const auto& pTheme : m_ThemesArray) {
    dwID = pTheme->GetThemeID(pWidget);
    pTheme->SetThemeID(pWidget, dwThemeID, FALSE);
  }
  return dwID;
}

FWL_Error CFWL_Theme::GetThemeMatrix(IFWL_Widget* pWidget, CFX_Matrix& matrix) {
  return FWL_Error::Succeeded;
}

FWL_Error CFWL_Theme::SetThemeMatrix(IFWL_Widget* pWidget,
                                     const CFX_Matrix& matrix) {
  return FWL_Error::Succeeded;
}

FX_BOOL CFWL_Theme::DrawBackground(CFWL_ThemeBackground* pParams) {
  return GetTheme(pParams->m_pWidget)->DrawBackground(pParams);
}

FX_BOOL CFWL_Theme::DrawText(CFWL_ThemeText* pParams) {
  return GetTheme(pParams->m_pWidget)->DrawText(pParams);
}

void* CFWL_Theme::GetCapacity(CFWL_ThemePart* pThemePart,
                              CFWL_WidgetCapacity dwCapacity) {
  return GetTheme(pThemePart->m_pWidget)->GetCapacity(pThemePart, dwCapacity);
}

FX_BOOL CFWL_Theme::IsCustomizedLayout(IFWL_Widget* pWidget) {
  return GetTheme(pWidget)->IsCustomizedLayout(pWidget);
}

FWL_Error CFWL_Theme::GetPartRect(CFWL_ThemePart* pThemePart,
                                  CFX_RectF& rtPart) {
  return GetTheme(pThemePart->m_pWidget)->GetPartRect(pThemePart, rtPart);
}

FX_BOOL CFWL_Theme::IsInPart(CFWL_ThemePart* pThemePart,
                             FX_FLOAT fx,
                             FX_FLOAT fy) {
  return GetTheme(pThemePart->m_pWidget)->IsInPart(pThemePart, fx, fy);
}

FX_BOOL CFWL_Theme::CalcTextRect(CFWL_ThemeText* pParams, CFX_RectF& rect) {
  return GetTheme(pParams->m_pWidget)->CalcTextRect(pParams, rect);
}

FWL_Error CFWL_Theme::Initialize() {
  for (const auto& pTheme : m_ThemesArray)
    pTheme->Initialize();

  FWLTHEME_Init();
  return FWL_Error::Succeeded;
}

FWL_Error CFWL_Theme::Finalize() {
  for (const auto& pTheme : m_ThemesArray)
    pTheme->Finalize();

  FWLTHEME_Release();
  return FWL_Error::Succeeded;
}

FWL_Error CFWL_Theme::SetFont(IFWL_Widget* pWidget,
                              const FX_WCHAR* strFont,
                              FX_FLOAT fFontSize,
                              FX_ARGB rgbFont) {
  for (const auto& pTheme : m_ThemesArray)
    pTheme->SetFont(pWidget, strFont, fFontSize, rgbFont);

  return FWL_Error::Succeeded;
}

CFWL_WidgetTP* CFWL_Theme::GetTheme(IFWL_Widget* pWidget) {
  for (const auto& pTheme : m_ThemesArray) {
    if (pTheme->IsValidWidget(pWidget))
      return pTheme.get();
  }
  return nullptr;
}
