// 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/src/foxitlib.h"
#include "xfa/src/fxfa/src/common/xfa_common.h"
#include "xfa_ffwidget.h"
#include "xfa_ffdraw.h"
#include "xfa_fftext.h"
#include "xfa_textlayout.h"
#include "xfa_ffpageview.h"
#include "xfa_ffdoc.h"
#include "xfa_ffapp.h"
CXFA_FFText::CXFA_FFText(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc)
    : CXFA_FFDraw(pPageView, pDataAcc) {}
CXFA_FFText::~CXFA_FFText() {}
void CXFA_FFText::RenderWidget(CFX_Graphics* pGS,
                               CFX_Matrix* pMatrix,
                               FX_DWORD dwStatus,
                               int32_t iRotate) {
  if (!IsMatchVisibleStatus(dwStatus)) {
    return;
  }
  {
    CFX_Matrix mtRotate;
    GetRotateMatrix(mtRotate);
    if (pMatrix) {
      mtRotate.Concat(*pMatrix);
    }
    CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus);
    CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout();
    if (pTextLayout) {
      CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice();
      CFX_RectF rtText;
      GetRectWithoutRotate(rtText);
      if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) {
        CXFA_LayoutItem* pItem = this;
        if (pItem->GetPrev() == NULL && pItem->GetNext() == NULL) {
          XFA_RectWidthoutMargin(rtText, mgWidget);
        } else {
          FX_FLOAT fLeftInset, fRightInset, fTopInset = 0, fBottomInset = 0;
          mgWidget.GetLeftInset(fLeftInset);
          mgWidget.GetRightInset(fRightInset);
          if (pItem->GetPrev() == NULL) {
            mgWidget.GetTopInset(fTopInset);
          } else if (pItem->GetNext() == NULL) {
            mgWidget.GetBottomInset(fBottomInset);
          }
          rtText.Deflate(fLeftInset, fTopInset, fRightInset, fBottomInset);
        }
      }
      CFX_Matrix mt;
      mt.Set(1, 0, 0, 1, rtText.left, rtText.top);
      CFX_RectF rtClip = rtText;
      mtRotate.TransformRect(rtClip);
      mt.Concat(mtRotate);
      pTextLayout->DrawString(pRenderDevice, mt, rtClip, GetIndex());
    }
  }
}
FX_BOOL CXFA_FFText::IsLoaded() {
  CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout();
  return pTextLayout != NULL && !pTextLayout->m_bHasBlock;
}
FX_BOOL CXFA_FFText::PerformLayout() {
  CXFA_FFDraw::PerformLayout();
  CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout();
  if (!pTextLayout) {
    return FALSE;
  }
  if (!pTextLayout->m_bHasBlock) {
    return TRUE;
  }
  pTextLayout->m_Blocks.RemoveAll();
  CXFA_LayoutItem* pItem = this;
  if (pItem->GetPrev() == NULL && pItem->GetNext() == NULL) {
    return TRUE;
  }
  pItem = pItem->GetFirst();
  while (pItem) {
    CFX_RectF rtText;
    pItem->GetRect(rtText);
    if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) {
      if (pItem->GetPrev() == NULL) {
        FX_FLOAT fTopInset;
        mgWidget.GetTopInset(fTopInset);
        rtText.height -= fTopInset;
      } else if (pItem->GetNext() == NULL) {
        FX_FLOAT fBottomInset;
        mgWidget.GetBottomInset(fBottomInset);
        rtText.height -= fBottomInset;
      }
    }
    pTextLayout->ItemBlocks(rtText, pItem->GetIndex());
    pItem = pItem->GetNext();
  }
  pTextLayout->m_bHasBlock = FALSE;
  return TRUE;
}
FX_BOOL CXFA_FFText::OnLButtonDown(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
  CFX_RectF rtBox;
  GetRectWithoutRotate(rtBox);
  if (!rtBox.Contains(fx, fy)) {
    return FALSE;
  }
  const FX_WCHAR* wsURLContent = GetLinkURLAtPoint(fx, fy);
  if (NULL == wsURLContent) {
    return FALSE;
  }
  SetButtonDown(TRUE);
  return TRUE;
}
FX_BOOL CXFA_FFText::OnMouseMove(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
  CFX_RectF rtBox;
  GetRectWithoutRotate(rtBox);
  if (!rtBox.Contains(fx, fy)) {
    return FALSE;
  }
  const FX_WCHAR* wsURLContent = GetLinkURLAtPoint(fx, fy);
  if (NULL == wsURLContent) {
    return FALSE;
  }
  return TRUE;
}
FX_BOOL CXFA_FFText::OnLButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
  if (!IsButtonDown()) {
    return FALSE;
  }
  SetButtonDown(FALSE);
  const FX_WCHAR* wsURLContent = GetLinkURLAtPoint(fx, fy);
  if (NULL == wsURLContent) {
    return FALSE;
  }
  CXFA_FFDoc* pDoc = GetDoc();
  pDoc->GetDocProvider()->GotoURL(pDoc, CFX_WideStringC(wsURLContent), FALSE);
  return TRUE;
}
FX_DWORD CXFA_FFText::OnHitTest(FX_FLOAT fx, FX_FLOAT fy) {
  CFX_RectF rtBox;
  GetRectWithoutRotate(rtBox);
  if (!rtBox.Contains(fx, fy)) {
    return FWL_WGTHITTEST_Unknown;
  }
  if (!GetLinkURLAtPoint(fx, fy)) {
    return FWL_WGTHITTEST_Unknown;
  }
  return FWL_WGTHITTEST_HyperLink;
}
const FX_WCHAR* CXFA_FFText::GetLinkURLAtPoint(FX_FLOAT fx, FX_FLOAT fy) {
  CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout();
  if (NULL == pTextLayout) {
    return NULL;
  }
  FX_FLOAT x(fx), y(fy);
  FWLToClient(x, y);
  const CXFA_PieceLineArray* pPieceLines = pTextLayout->GetPieceLines();
  int32_t iCount = pPieceLines->GetSize();
  for (int32_t i = 0; i < iCount; i++) {
    CXFA_PieceLine* pPieceLine = pPieceLines->GetAt(i);
    int32_t iPieces = pPieceLine->m_textPieces.GetSize();
    for (int32_t j = 0; j < iPieces; j++) {
      XFA_LPTEXTPIECE pPiece = pPieceLine->m_textPieces.GetAt(j);
      if (pPiece->pLinkData && pPiece->rtPiece.Contains(x, y)) {
        return pPiece->pLinkData->GetLinkURL();
      }
    }
  }
  return NULL;
}
void CXFA_FFText::FWLToClient(FX_FLOAT& fx, FX_FLOAT& fy) {
  CFX_RectF rtWidget;
  GetRectWithoutRotate(rtWidget);
  fx -= rtWidget.left;
  fy -= rtWidget.top;
}
