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

    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;
}
