// 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 <map>

#include "../../include/pdfwindow/PDFWindow.h"
#include "../../include/pdfwindow/PWL_Wnd.h"
#include "../../include/pdfwindow/PWL_Utils.h"
#include "../../include/pdfwindow/PWL_ScrollBar.h"

/* -------------------------- CPWL_Timer -------------------------- */

static std::map<int32_t, CPWL_Timer*>& GetPWLTimeMap() {
  // Leak the object at shutdown.
  static auto timeMap = new std::map<int32_t, CPWL_Timer*>;
  return *timeMap;
}

CPWL_Timer::CPWL_Timer(CPWL_TimerHandler* pAttached,
                       IFX_SystemHandler* pSystemHandler)
    : m_nTimerID(0), m_pAttached(pAttached), m_pSystemHandler(pSystemHandler) {
  ASSERT(m_pAttached != NULL);
  ASSERT(m_pSystemHandler != NULL);
}

CPWL_Timer::~CPWL_Timer() {
  KillPWLTimer();
}

int32_t CPWL_Timer::SetPWLTimer(int32_t nElapse) {
  if (m_nTimerID != 0)
    KillPWLTimer();
  m_nTimerID = m_pSystemHandler->SetTimer(nElapse, TimerProc);

  GetPWLTimeMap()[m_nTimerID] = this;
  return m_nTimerID;
}

void CPWL_Timer::KillPWLTimer() {
  if (m_nTimerID == 0)
    return;

  m_pSystemHandler->KillTimer(m_nTimerID);
  GetPWLTimeMap().erase(m_nTimerID);
  m_nTimerID = 0;
}

void CPWL_Timer::TimerProc(int32_t idEvent) {
  auto it = GetPWLTimeMap().find(idEvent);
  if (it == GetPWLTimeMap().end())
    return;

  CPWL_Timer* pTimer = it->second;
  if (pTimer->m_pAttached)
    pTimer->m_pAttached->TimerProc();
}

/* -------------------------- CPWL_TimerHandler -------------------------- */

CPWL_TimerHandler::CPWL_TimerHandler() : m_pTimer(NULL) {}

CPWL_TimerHandler::~CPWL_TimerHandler() {
  delete m_pTimer;
}

void CPWL_TimerHandler::BeginTimer(int32_t nElapse) {
  if (!m_pTimer)
    m_pTimer = new CPWL_Timer(this, GetSystemHandler());

  if (m_pTimer)
    m_pTimer->SetPWLTimer(nElapse);
}

void CPWL_TimerHandler::EndTimer() {
  if (m_pTimer)
    m_pTimer->KillPWLTimer();
}

void CPWL_TimerHandler::TimerProc() {}

/* --------------------------- CPWL_MsgControl ---------------------------- */

class CPWL_MsgControl {
  friend class CPWL_Wnd;

 public:
  CPWL_MsgControl(CPWL_Wnd* pWnd) {
    //      PWL_TRACE("new CPWL_MsgControl\n");
    m_pCreatedWnd = pWnd;
    Default();
  }

  ~CPWL_MsgControl() {
    //      PWL_TRACE("~CPWL_MsgControl\n");
    Default();
  }

  void Default() {
    m_aMousePath.RemoveAll();
    m_aKeyboardPath.RemoveAll();
    m_pMainMouseWnd = NULL;
    m_pMainKeyboardWnd = NULL;
  }

  FX_BOOL IsWndCreated(const CPWL_Wnd* pWnd) const {
    return m_pCreatedWnd == pWnd;
  }

  FX_BOOL IsMainCaptureMouse(const CPWL_Wnd* pWnd) const {
    return pWnd == m_pMainMouseWnd;
  }

  FX_BOOL IsWndCaptureMouse(const CPWL_Wnd* pWnd) const {
    if (pWnd)
      for (int32_t i = 0, sz = m_aMousePath.GetSize(); i < sz; i++)
        if (m_aMousePath.GetAt(i) == pWnd)
          return TRUE;

    return FALSE;
  }

  FX_BOOL IsMainCaptureKeyboard(const CPWL_Wnd* pWnd) const {
    return pWnd == m_pMainKeyboardWnd;
  }

  FX_BOOL IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const {
    if (pWnd)
      for (int32_t i = 0, sz = m_aKeyboardPath.GetSize(); i < sz; i++)
        if (m_aKeyboardPath.GetAt(i) == pWnd)
          return TRUE;

    return FALSE;
  }

  void SetFocus(CPWL_Wnd* pWnd) {
    m_aKeyboardPath.RemoveAll();

    if (pWnd) {
      m_pMainKeyboardWnd = pWnd;

      CPWL_Wnd* pParent = pWnd;
      while (pParent) {
        m_aKeyboardPath.Add(pParent);
        pParent = pParent->GetParentWindow();
      }

      pWnd->OnSetFocus();
    }
  }

  void KillFocus() {
    if (m_aKeyboardPath.GetSize() > 0)
      if (CPWL_Wnd* pWnd = m_aKeyboardPath.GetAt(0))
        pWnd->OnKillFocus();

    m_pMainKeyboardWnd = NULL;
    m_aKeyboardPath.RemoveAll();
  }

  void SetCapture(CPWL_Wnd* pWnd) {
    m_aMousePath.RemoveAll();

    if (pWnd) {
      m_pMainMouseWnd = pWnd;

      CPWL_Wnd* pParent = pWnd;
      while (pParent) {
        m_aMousePath.Add(pParent);
        pParent = pParent->GetParentWindow();
      }
    }
  }

  void ReleaseCapture() {
    m_pMainMouseWnd = NULL;
    m_aMousePath.RemoveAll();
  }

 private:
  CFX_ArrayTemplate<CPWL_Wnd*> m_aMousePath;
  CFX_ArrayTemplate<CPWL_Wnd*> m_aKeyboardPath;
  CPWL_Wnd* m_pCreatedWnd;
  CPWL_Wnd* m_pMainMouseWnd;
  CPWL_Wnd* m_pMainKeyboardWnd;
};

/* --------------------------- CPWL_Wnd ---------------------------- */

CPWL_Wnd::CPWL_Wnd()
    : m_pVScrollBar(NULL),
      m_rcWindow(),
      m_rcClip(),
      m_bCreated(FALSE),
      m_bVisible(FALSE),
      m_bNotifying(FALSE),
      m_bEnabled(TRUE) {}

CPWL_Wnd::~CPWL_Wnd() {
  ASSERT(m_bCreated == FALSE);
}

CFX_ByteString CPWL_Wnd::GetClassName() const {
  return "CPWL_Wnd";
}

void CPWL_Wnd::Create(const PWL_CREATEPARAM& cp) {
  if (!IsValid()) {
    m_sPrivateParam = cp;

    OnCreate(m_sPrivateParam);

    m_sPrivateParam.rcRectWnd.Normalize();
    m_rcWindow = m_sPrivateParam.rcRectWnd;
    m_rcClip = CPWL_Utils::InflateRect(m_rcWindow, 1.0f);

    CreateMsgControl();

    if (m_sPrivateParam.pParentWnd)
      m_sPrivateParam.pParentWnd->OnNotify(this, PNM_ADDCHILD);

    PWL_CREATEPARAM ccp = m_sPrivateParam;

    ccp.dwFlags &= 0xFFFF0000L;  // remove sub styles
    ccp.mtChild = CPDF_Matrix(1, 0, 0, 1, 0, 0);

    CreateScrollBar(ccp);
    CreateChildWnd(ccp);

    m_bVisible = HasFlag(PWS_VISIBLE);

    OnCreated();

    RePosChildWnd();
    m_bCreated = TRUE;
  }
}

void CPWL_Wnd::OnCreate(PWL_CREATEPARAM& cp) {}

void CPWL_Wnd::OnCreated() {}

void CPWL_Wnd::OnDestroy() {}

void CPWL_Wnd::Destroy() {
  KillFocus();

  OnDestroy();

  if (m_bCreated) {
    for (int32_t i = m_aChildren.GetSize() - 1; i >= 0; i--) {
      if (CPWL_Wnd* pChild = m_aChildren[i]) {
        pChild->Destroy();
        delete pChild;
        pChild = NULL;
      }
    }

    if (m_sPrivateParam.pParentWnd)
      m_sPrivateParam.pParentWnd->OnNotify(this, PNM_REMOVECHILD);
    m_bCreated = FALSE;
  }

  DestroyMsgControl();

  FXSYS_memset(&m_sPrivateParam, 0, sizeof(PWL_CREATEPARAM));
  m_aChildren.RemoveAll();
  m_pVScrollBar = NULL;
}

void CPWL_Wnd::Move(const CPDF_Rect& rcNew, FX_BOOL bReset, FX_BOOL bRefresh) {
  if (IsValid()) {
    CPDF_Rect rcOld = GetWindowRect();

    m_rcWindow = rcNew;
    m_rcWindow.Normalize();

    if (rcOld.left != rcNew.left || rcOld.right != rcNew.right ||
        rcOld.top != rcNew.top || rcOld.bottom != rcNew.bottom) {
      if (bReset) {
        RePosChildWnd();
      }
    }
    if (bRefresh) {
      InvalidateRectMove(rcOld, rcNew);
    }

    m_sPrivateParam.rcRectWnd = m_rcWindow;
  }
}

void CPWL_Wnd::InvalidateRectMove(const CPDF_Rect& rcOld,
                                  const CPDF_Rect& rcNew) {
  CPDF_Rect rcUnion = rcOld;
  rcUnion.Union(rcNew);

  InvalidateRect(&rcUnion);
}

void CPWL_Wnd::GetAppearanceStream(CFX_ByteString& sAppStream) {
  if (IsValid()) {
    CFX_ByteTextBuf sTextBuf;
    GetAppearanceStream(sTextBuf);
    sAppStream += sTextBuf.GetByteString();
  }
}

void CPWL_Wnd::GetAppearanceStream(CFX_ByteTextBuf& sAppStream) {
  if (IsValid() && IsVisible()) {
    GetThisAppearanceStream(sAppStream);
    GetChildAppearanceStream(sAppStream);
  }
}

// if don't set,Get default apperance stream
void CPWL_Wnd::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) {
  CPDF_Rect rectWnd = GetWindowRect();
  if (!rectWnd.IsEmpty()) {
    CFX_ByteTextBuf sThis;

    if (HasFlag(PWS_BACKGROUND))
      sThis << CPWL_Utils::GetRectFillAppStream(rectWnd, GetBackgroundColor());

    if (HasFlag(PWS_BORDER)) {
      sThis << CPWL_Utils::GetBorderAppStream(
          rectWnd, (FX_FLOAT)GetBorderWidth(), GetBorderColor(),
          GetBorderLeftTopColor(GetBorderStyle()),
          GetBorderRightBottomColor(GetBorderStyle()), GetBorderStyle(),
          GetBorderDash());
    }

    sAppStream << sThis;
  }
}

void CPWL_Wnd::GetChildAppearanceStream(CFX_ByteTextBuf& sAppStream) {
  for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
    if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
      pChild->GetAppearanceStream(sAppStream);
    }
  }
}

void CPWL_Wnd::DrawAppearance(CFX_RenderDevice* pDevice,
                              CPDF_Matrix* pUser2Device) {
  if (IsValid() && IsVisible()) {
    DrawThisAppearance(pDevice, pUser2Device);
    DrawChildAppearance(pDevice, pUser2Device);
  }
}

void CPWL_Wnd::DrawThisAppearance(CFX_RenderDevice* pDevice,
                                  CPDF_Matrix* pUser2Device) {
  CPDF_Rect rectWnd = GetWindowRect();
  if (!rectWnd.IsEmpty()) {
    if (HasFlag(PWS_BACKGROUND)) {
      CPDF_Rect rcClient = CPWL_Utils::DeflateRect(
          rectWnd, (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth()));
      CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcClient,
                               GetBackgroundColor(), GetTransparency());
    }

    if (HasFlag(PWS_BORDER))
      CPWL_Utils::DrawBorder(
          pDevice, pUser2Device, rectWnd, (FX_FLOAT)GetBorderWidth(),
          GetBorderColor(), GetBorderLeftTopColor(GetBorderStyle()),
          GetBorderRightBottomColor(GetBorderStyle()), GetBorderStyle(),
          GetBorderDash(), GetTransparency());
  }
}

void CPWL_Wnd::DrawChildAppearance(CFX_RenderDevice* pDevice,
                                   CPDF_Matrix* pUser2Device) {
  for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
    if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
      CPDF_Matrix mt = pChild->GetChildMatrix();
      if (mt.IsIdentity()) {
        pChild->DrawAppearance(pDevice, pUser2Device);
      } else {
        mt.Concat(*pUser2Device);
        pChild->DrawAppearance(pDevice, &mt);
      }
    }
  }
}

void CPWL_Wnd::InvalidateRect(CPDF_Rect* pRect) {
  if (IsValid()) {
    CPDF_Rect rcRefresh = pRect ? *pRect : GetWindowRect();

    if (!HasFlag(PWS_NOREFRESHCLIP)) {
      CPDF_Rect rcClip = GetClipRect();
      if (!rcClip.IsEmpty()) {
        rcRefresh.Intersect(rcClip);
      }
    }

    FX_RECT rcWin = PWLtoWnd(rcRefresh);
    rcWin.left -= PWL_INVALIDATE_INFLATE;
    rcWin.top -= PWL_INVALIDATE_INFLATE;
    rcWin.right += PWL_INVALIDATE_INFLATE;
    rcWin.bottom += PWL_INVALIDATE_INFLATE;

    if (IFX_SystemHandler* pSH = GetSystemHandler()) {
      if (FX_HWND hWnd = GetAttachedHWnd()) {
        pSH->InvalidateRect(hWnd, rcWin);
      }
    }
  }
}

#define PWL_IMPLEMENT_KEY_METHOD(key_method_name)                      \
  FX_BOOL CPWL_Wnd::key_method_name(FX_WORD nChar, FX_DWORD nFlag) {   \
    if (IsValid() && IsVisible() && IsEnabled()) {                     \
      if (IsWndCaptureKeyboard(this)) {                                \
        for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) { \
          if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {               \
            if (IsWndCaptureKeyboard(pChild)) {                        \
              return pChild->key_method_name(nChar, nFlag);            \
            }                                                          \
          }                                                            \
        }                                                              \
      }                                                                \
    }                                                                  \
    return FALSE;                                                      \
  }

#define PWL_IMPLEMENT_MOUSE_METHOD(mouse_method_name)                        \
  FX_BOOL CPWL_Wnd::mouse_method_name(const CPDF_Point& point,               \
                                      FX_DWORD nFlag) {                      \
    if (IsValid() && IsVisible() && IsEnabled()) {                           \
      if (IsWndCaptureMouse(this)) {                                         \
        for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {       \
          if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {                     \
            if (IsWndCaptureMouse(pChild)) {                                 \
              return pChild->mouse_method_name(pChild->ParentToChild(point), \
                                               nFlag);                       \
            }                                                                \
          }                                                                  \
        }                                                                    \
        SetCursor();                                                         \
      } else {                                                               \
        for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {       \
          if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {                     \
            if (pChild->WndHitTest(pChild->ParentToChild(point))) {          \
              return pChild->mouse_method_name(pChild->ParentToChild(point), \
                                               nFlag);                       \
            }                                                                \
          }                                                                  \
        }                                                                    \
        if (WndHitTest(point))                                               \
          SetCursor();                                                       \
      }                                                                      \
    }                                                                        \
    return FALSE;                                                            \
  }

PWL_IMPLEMENT_KEY_METHOD(OnKeyDown)
PWL_IMPLEMENT_KEY_METHOD(OnKeyUp)
PWL_IMPLEMENT_KEY_METHOD(OnChar)

PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDblClk)
PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDown)
PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonUp)
PWL_IMPLEMENT_MOUSE_METHOD(OnMButtonDblClk)
PWL_IMPLEMENT_MOUSE_METHOD(OnMButtonDown)
PWL_IMPLEMENT_MOUSE_METHOD(OnMButtonUp)
PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonDown)
PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonUp)
PWL_IMPLEMENT_MOUSE_METHOD(OnMouseMove)

FX_BOOL CPWL_Wnd::OnMouseWheel(short zDelta,
                               const CPDF_Point& point,
                               FX_DWORD nFlag) {
  if (IsValid() && IsVisible() && IsEnabled()) {
    SetCursor();
    if (IsWndCaptureKeyboard(this)) {
      for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
        if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
          if (IsWndCaptureKeyboard(pChild)) {
            return pChild->OnMouseWheel(zDelta, pChild->ParentToChild(point),
                                        nFlag);
          }
        }
      }
    }
  }
  return FALSE;
}

void CPWL_Wnd::AddChild(CPWL_Wnd* pWnd) {
  m_aChildren.Add(pWnd);
}

void CPWL_Wnd::RemoveChild(CPWL_Wnd* pWnd) {
  for (int32_t i = m_aChildren.GetSize() - 1; i >= 0; i--) {
    if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
      if (pChild == pWnd) {
        m_aChildren.RemoveAt(i);
        break;
      }
    }
  }
}

void CPWL_Wnd::OnNotify(CPWL_Wnd* pWnd,
                        FX_DWORD msg,
                        intptr_t wParam,
                        intptr_t lParam) {
  switch (msg) {
    case PNM_ADDCHILD:
      AddChild(pWnd);
      break;
    case PNM_REMOVECHILD:
      RemoveChild(pWnd);
      break;
    default:
      break;
  }
}

FX_BOOL CPWL_Wnd::IsValid() const {
  return m_bCreated;
}

PWL_CREATEPARAM CPWL_Wnd::GetCreationParam() const {
  return m_sPrivateParam;
}

CPWL_Wnd* CPWL_Wnd::GetParentWindow() const {
  return m_sPrivateParam.pParentWnd;
}

CPDF_Rect CPWL_Wnd::GetOriginWindowRect() const {
  return m_sPrivateParam.rcRectWnd;
}

CPDF_Rect CPWL_Wnd::GetWindowRect() const {
  return m_rcWindow;
}

CPDF_Rect CPWL_Wnd::GetClientRect() const {
  CPDF_Rect rcWindow = GetWindowRect();
  CPDF_Rect rcClient = CPWL_Utils::DeflateRect(
      rcWindow, (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth()));
  if (CPWL_ScrollBar* pVSB = GetVScrollBar())
    rcClient.right -= pVSB->GetScrollBarWidth();

  rcClient.Normalize();
  return rcWindow.Contains(rcClient) ? rcClient : CPDF_Rect();
}

CPDF_Point CPWL_Wnd::GetCenterPoint() const {
  CPDF_Rect rcClient = GetClientRect();
  return CPDF_Point((rcClient.left + rcClient.right) * 0.5f,
                    (rcClient.top + rcClient.bottom) * 0.5f);
}

CPDF_Rect CPWL_Wnd::GetClientCenterSquare() const {
  return CPWL_Utils::GetCenterSquare(GetClientRect());
}

CPDF_Rect CPWL_Wnd::GetWindowCenterSquare() const {
  return CPWL_Utils::GetCenterSquare(
      CPWL_Utils::DeflateRect(GetWindowRect(), 0.1f));
}

FX_BOOL CPWL_Wnd::HasFlag(FX_DWORD dwFlags) const {
  return (m_sPrivateParam.dwFlags & dwFlags) != 0;
}

void CPWL_Wnd::RemoveFlag(FX_DWORD dwFlags) {
  m_sPrivateParam.dwFlags &= ~dwFlags;
}

void CPWL_Wnd::AddFlag(FX_DWORD dwFlags) {
  m_sPrivateParam.dwFlags |= dwFlags;
}

CPWL_Color CPWL_Wnd::GetBackgroundColor() const {
  return m_sPrivateParam.sBackgroundColor;
}

void CPWL_Wnd::SetBackgroundColor(const CPWL_Color& color) {
  m_sPrivateParam.sBackgroundColor = color;
}

void CPWL_Wnd::SetTextColor(const CPWL_Color& color) {
  m_sPrivateParam.sTextColor = color;
}

void CPWL_Wnd::SetTextStrokeColor(const CPWL_Color& color) {
  m_sPrivateParam.sTextStrokeColor = color;
}

CPWL_Color CPWL_Wnd::GetTextColor() const {
  return m_sPrivateParam.sTextColor;
}

CPWL_Color CPWL_Wnd::GetTextStrokeColor() const {
  return m_sPrivateParam.sTextStrokeColor;
}

int32_t CPWL_Wnd::GetBorderStyle() const {
  return m_sPrivateParam.nBorderStyle;
}

void CPWL_Wnd::SetBorderStyle(int32_t nBorderStyle) {
  if (HasFlag(PWS_BORDER))
    m_sPrivateParam.nBorderStyle = nBorderStyle;
}

int32_t CPWL_Wnd::GetBorderWidth() const {
  if (HasFlag(PWS_BORDER))
    return m_sPrivateParam.dwBorderWidth;

  return 0;
}

int32_t CPWL_Wnd::GetInnerBorderWidth() const {
  /*
  switch (GetBorderStyle())
  {
  case PBS_BEVELED:
  case PBS_INSET:
      return GetBorderWidth() / 2;
  }
  */
  return 0;
}

void CPWL_Wnd::SetBorderWidth(int32_t nBorderWidth) {
  if (HasFlag(PWS_BORDER))
    m_sPrivateParam.dwBorderWidth = nBorderWidth;
}

CPWL_Color CPWL_Wnd::GetBorderColor() const {
  if (HasFlag(PWS_BORDER))
    return m_sPrivateParam.sBorderColor;

  return CPWL_Color();
}

void CPWL_Wnd::SetBorderColor(const CPWL_Color& color) {
  if (HasFlag(PWS_BORDER))
    m_sPrivateParam.sBorderColor = color;
}

CPWL_Dash CPWL_Wnd::GetBorderDash() const {
  return m_sPrivateParam.sDash;
}

void* CPWL_Wnd::GetAttachedData() const {
  return m_sPrivateParam.pAttachedData;
}

void CPWL_Wnd::SetBorderDash(const CPWL_Dash& sDash) {
  if (HasFlag(PWS_BORDER))
    m_sPrivateParam.sDash = sDash;
}

CPWL_ScrollBar* CPWL_Wnd::GetVScrollBar() const {
  if (HasFlag(PWS_VSCROLL))
    return m_pVScrollBar;

  return NULL;
}

void CPWL_Wnd::CreateScrollBar(const PWL_CREATEPARAM& cp) {
  CreateVScrollBar(cp);
}

void CPWL_Wnd::CreateVScrollBar(const PWL_CREATEPARAM& cp) {
  if (!m_pVScrollBar && HasFlag(PWS_VSCROLL)) {
    PWL_CREATEPARAM scp = cp;

    // flags
    scp.dwFlags =
        PWS_CHILD | PWS_BACKGROUND | PWS_AUTOTRANSPARENT | PWS_NOREFRESHCLIP;

    scp.pParentWnd = this;
    scp.sBackgroundColor = PWL_DEFAULT_WHITECOLOR;
    scp.eCursorType = FXCT_ARROW;
    scp.nTransparency = PWL_SCROLLBAR_TRANSPARANCY;

    if ((m_pVScrollBar = new CPWL_ScrollBar(SBT_VSCROLL)))
      m_pVScrollBar->Create(scp);
  }
}

void CPWL_Wnd::SetCapture() {
  if (CPWL_MsgControl* pMsgCtrl = GetMsgControl())
    pMsgCtrl->SetCapture(this);
}

void CPWL_Wnd::ReleaseCapture() {
  for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++)
    if (CPWL_Wnd* pChild = m_aChildren.GetAt(i))
      pChild->ReleaseCapture();

  if (CPWL_MsgControl* pMsgCtrl = GetMsgControl())
    pMsgCtrl->ReleaseCapture();
}

void CPWL_Wnd::SetFocus() {
  if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) {
    if (!pMsgCtrl->IsMainCaptureKeyboard(this))
      pMsgCtrl->KillFocus();
    pMsgCtrl->SetFocus(this);
  }
}

void CPWL_Wnd::KillFocus() {
  if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) {
    if (pMsgCtrl->IsWndCaptureKeyboard(this))
      pMsgCtrl->KillFocus();
  }
}

void CPWL_Wnd::OnSetFocus() {}

void CPWL_Wnd::OnKillFocus() {}

FX_BOOL CPWL_Wnd::WndHitTest(const CPDF_Point& point) const {
  return IsValid() && IsVisible() && GetWindowRect().Contains(point.x, point.y);
}

FX_BOOL CPWL_Wnd::ClientHitTest(const CPDF_Point& point) const {
  return IsValid() && IsVisible() && GetClientRect().Contains(point.x, point.y);
}

const CPWL_Wnd* CPWL_Wnd::GetRootWnd() const {
  if (m_sPrivateParam.pParentWnd)
    return m_sPrivateParam.pParentWnd->GetRootWnd();

  return this;
}

void CPWL_Wnd::SetVisible(FX_BOOL bVisible) {
  if (IsValid()) {
    for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
      if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
        pChild->SetVisible(bVisible);
      }
    }

    if (bVisible != m_bVisible) {
      m_bVisible = bVisible;
      RePosChildWnd();
      InvalidateRect();
    }
  }
}

void CPWL_Wnd::SetClipRect(const CPDF_Rect& rect) {
  m_rcClip = rect;
  m_rcClip.Normalize();
}

CPDF_Rect CPWL_Wnd::GetClipRect() const {
  return m_rcClip;
}

FX_BOOL CPWL_Wnd::IsReadOnly() const {
  return HasFlag(PWS_READONLY);
}

void CPWL_Wnd::RePosChildWnd() {
  CPDF_Rect rcContent = CPWL_Utils::DeflateRect(
      GetWindowRect(), (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth()));

  CPWL_ScrollBar* pVSB = GetVScrollBar();

  CPDF_Rect rcVScroll =
      CPDF_Rect(rcContent.right - PWL_SCROLLBAR_WIDTH, rcContent.bottom,
                rcContent.right - 1.0f, rcContent.top);

  if (pVSB)
    pVSB->Move(rcVScroll, TRUE, FALSE);
}

void CPWL_Wnd::CreateChildWnd(const PWL_CREATEPARAM& cp) {}

void CPWL_Wnd::SetCursor() {
  if (IsValid()) {
    if (IFX_SystemHandler* pSH = GetSystemHandler()) {
      int32_t nCursorType = GetCreationParam().eCursorType;
      pSH->SetCursor(nCursorType);
    }
  }
}

void CPWL_Wnd::CreateMsgControl() {
  if (!m_sPrivateParam.pMsgControl)
    m_sPrivateParam.pMsgControl = new CPWL_MsgControl(this);
}

void CPWL_Wnd::DestroyMsgControl() {
  if (CPWL_MsgControl* pMsgControl = GetMsgControl())
    if (pMsgControl->IsWndCreated(this))
      delete pMsgControl;
}

CPWL_MsgControl* CPWL_Wnd::GetMsgControl() const {
  return m_sPrivateParam.pMsgControl;
}

FX_BOOL CPWL_Wnd::IsCaptureMouse() const {
  return IsWndCaptureMouse(this);
}

FX_BOOL CPWL_Wnd::IsWndCaptureMouse(const CPWL_Wnd* pWnd) const {
  if (CPWL_MsgControl* pCtrl = GetMsgControl())
    return pCtrl->IsWndCaptureMouse(pWnd);

  return FALSE;
}

FX_BOOL CPWL_Wnd::IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const {
  if (CPWL_MsgControl* pCtrl = GetMsgControl())
    return pCtrl->IsWndCaptureKeyboard(pWnd);

  return FALSE;
}

FX_BOOL CPWL_Wnd::IsFocused() const {
  if (CPWL_MsgControl* pCtrl = GetMsgControl())
    return pCtrl->IsMainCaptureKeyboard(this);

  return FALSE;
}

CPDF_Rect CPWL_Wnd::GetFocusRect() const {
  return CPWL_Utils::InflateRect(GetWindowRect(), 1);
}

FX_FLOAT CPWL_Wnd::GetFontSize() const {
  return m_sPrivateParam.fFontSize;
}

void CPWL_Wnd::SetFontSize(FX_FLOAT fFontSize) {
  m_sPrivateParam.fFontSize = fFontSize;
}

IFX_SystemHandler* CPWL_Wnd::GetSystemHandler() const {
  return m_sPrivateParam.pSystemHandler;
}

IPWL_FocusHandler* CPWL_Wnd::GetFocusHandler() const {
  return m_sPrivateParam.pFocusHandler;
}

IPWL_Provider* CPWL_Wnd::GetProvider() const {
  return m_sPrivateParam.pProvider;
}

IFX_Edit_FontMap* CPWL_Wnd::GetFontMap() const {
  return m_sPrivateParam.pFontMap;
}

CPWL_Color CPWL_Wnd::GetBorderLeftTopColor(int32_t nBorderStyle) const {
  CPWL_Color color;

  switch (nBorderStyle) {
    case PBS_SOLID:
      break;
    case PBS_DASH:
      break;
    case PBS_BEVELED:
      color = CPWL_Color(COLORTYPE_GRAY, 1);
      break;
    case PBS_INSET:
      color = CPWL_Color(COLORTYPE_GRAY, 0.5f);
      break;
    case PBS_UNDERLINED:
      break;
  }

  return color;
}

CPWL_Color CPWL_Wnd::GetBorderRightBottomColor(int32_t nBorderStyle) const {
  CPWL_Color color;

  switch (nBorderStyle) {
    case PBS_SOLID:
      break;
    case PBS_DASH:
      break;
    case PBS_BEVELED:
      color = CPWL_Utils::DevideColor(GetBackgroundColor(), 2);
      break;
    case PBS_INSET:
      color = CPWL_Color(COLORTYPE_GRAY, 0.75f);
      break;
    case PBS_UNDERLINED:
      break;
  }

  return color;
}

/* ----------------------------------------------------------------- */

int32_t CPWL_Wnd::GetTransparency() {
  return m_sPrivateParam.nTransparency;
}

void CPWL_Wnd::SetTransparency(int32_t nTransparency) {
  for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
    if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
      pChild->SetTransparency(nTransparency);
    }
  }

  m_sPrivateParam.nTransparency = nTransparency;
}

CPDF_Matrix CPWL_Wnd::GetWindowMatrix() const {
  CPDF_Matrix mt = GetChildToRoot();

  if (IPWL_Provider* pProvider = GetProvider()) {
    mt.Concat(pProvider->GetWindowMatrix(GetAttachedData()));
    return mt;
  }

  return mt;
}

void CPWL_Wnd::PWLtoWnd(const CPDF_Point& point, int32_t& x, int32_t& y) const {
  CPDF_Matrix mt = GetWindowMatrix();
  CPDF_Point pt = point;
  mt.Transform(pt.x, pt.y);
  x = (int32_t)(pt.x + 0.5);
  y = (int32_t)(pt.y + 0.5);
}

FX_RECT CPWL_Wnd::PWLtoWnd(const CPDF_Rect& rect) const {
  CPDF_Rect rcTemp = rect;
  CPDF_Matrix mt = GetWindowMatrix();
  mt.TransformRect(rcTemp);
  return FX_RECT((int32_t)(rcTemp.left + 0.5), (int32_t)(rcTemp.bottom + 0.5),
                 (int32_t)(rcTemp.right + 0.5), (int32_t)(rcTemp.top + 0.5));
}

FX_HWND CPWL_Wnd::GetAttachedHWnd() const {
  return m_sPrivateParam.hAttachedWnd;
}

CPDF_Point CPWL_Wnd::ChildToParent(const CPDF_Point& point) const {
  CPDF_Matrix mt = GetChildMatrix();
  if (mt.IsIdentity())
    return point;

  CPDF_Point pt = point;
  mt.Transform(pt.x, pt.y);
  return pt;
}

CPDF_Rect CPWL_Wnd::ChildToParent(const CPDF_Rect& rect) const {
  CPDF_Matrix mt = GetChildMatrix();
  if (mt.IsIdentity())
    return rect;

  CPDF_Rect rc = rect;
  mt.TransformRect(rc);
  return rc;
}

CPDF_Point CPWL_Wnd::ParentToChild(const CPDF_Point& point) const {
  CPDF_Matrix mt = GetChildMatrix();
  if (mt.IsIdentity())
    return point;

  mt.SetReverse(mt);
  CPDF_Point pt = point;
  mt.Transform(pt.x, pt.y);
  return pt;
}

CPDF_Rect CPWL_Wnd::ParentToChild(const CPDF_Rect& rect) const {
  CPDF_Matrix mt = GetChildMatrix();
  if (mt.IsIdentity())
    return rect;

  mt.SetReverse(mt);
  CPDF_Rect rc = rect;
  mt.TransformRect(rc);
  return rc;
}

CPDF_Matrix CPWL_Wnd::GetChildToRoot() const {
  CPDF_Matrix mt(1, 0, 0, 1, 0, 0);
  if (HasFlag(PWS_CHILD)) {
    const CPWL_Wnd* pParent = this;
    while (pParent) {
      mt.Concat(pParent->GetChildMatrix());
      pParent = pParent->GetParentWindow();
    }
  }
  return mt;
}

CPDF_Matrix CPWL_Wnd::GetChildMatrix() const {
  if (HasFlag(PWS_CHILD))
    return m_sPrivateParam.mtChild;

  return CPDF_Matrix(1, 0, 0, 1, 0, 0);
}

void CPWL_Wnd::SetChildMatrix(const CPDF_Matrix& mt) {
  m_sPrivateParam.mtChild = mt;
}

const CPWL_Wnd* CPWL_Wnd::GetFocused() const {
  if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) {
    return pMsgCtrl->m_pMainKeyboardWnd;
  }

  return NULL;
}

void CPWL_Wnd::EnableWindow(FX_BOOL bEnable) {
  if (m_bEnabled != bEnable) {
    for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
      if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
        pChild->EnableWindow(bEnable);
      }
    }

    m_bEnabled = bEnable;

    if (bEnable)
      OnEnabled();
    else
      OnDisabled();
  }
}

FX_BOOL CPWL_Wnd::IsEnabled() {
  return m_bEnabled;
}

void CPWL_Wnd::OnEnabled() {}

void CPWL_Wnd::OnDisabled() {}

FX_BOOL CPWL_Wnd::IsCTRLpressed(FX_DWORD nFlag) const {
  if (IFX_SystemHandler* pSystemHandler = GetSystemHandler()) {
    return pSystemHandler->IsCTRLKeyDown(nFlag);
  }

  return FALSE;
}

FX_BOOL CPWL_Wnd::IsSHIFTpressed(FX_DWORD nFlag) const {
  if (IFX_SystemHandler* pSystemHandler = GetSystemHandler()) {
    return pSystemHandler->IsSHIFTKeyDown(nFlag);
  }

  return FALSE;
}

FX_BOOL CPWL_Wnd::IsALTpressed(FX_DWORD nFlag) const {
  if (IFX_SystemHandler* pSystemHandler = GetSystemHandler()) {
    return pSystemHandler->IsALTKeyDown(nFlag);
  }

  return FALSE;
}

FX_BOOL CPWL_Wnd::IsINSERTpressed(FX_DWORD nFlag) const {
  if (IFX_SystemHandler* pSystemHandler = GetSystemHandler()) {
    return pSystemHandler->IsINSERTKeyDown(nFlag);
  }

  return FALSE;
}
