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

#include "xfa/fwl/fwl_widgetdef.h"
#include "xfa/fwl/fwl_widgethit.h"
#include "xfa/fxfa/cxfa_ffapp.h"
#include "xfa/fxfa/cxfa_ffdoc.h"
#include "xfa/fxfa/cxfa_ffdraw.h"
#include "xfa/fxfa/cxfa_ffpageview.h"
#include "xfa/fxfa/cxfa_ffwidget.h"
#include "xfa/fxfa/cxfa_linkuserdata.h"
#include "xfa/fxfa/cxfa_pieceline.h"
#include "xfa/fxfa/cxfa_textlayout.h"
#include "xfa/fxfa/cxfa_textpiece.h"
#include "xfa/fxfa/parser/cxfa_margin.h"
#include "xfa/fxgraphics/cxfa_graphics.h"

CXFA_FFText::CXFA_FFText(CXFA_Node* pNode) : CXFA_FFDraw(pNode) {}

CXFA_FFText::~CXFA_FFText() {}

void CXFA_FFText::RenderWidget(CXFA_Graphics* pGS,
                               const CFX_Matrix& matrix,
                               uint32_t dwStatus) {
  if (!IsMatchVisibleStatus(dwStatus))
    return;

  CFX_Matrix mtRotate = GetRotateMatrix();
  mtRotate.Concat(matrix);

  CXFA_FFWidget::RenderWidget(pGS, mtRotate, dwStatus);

  CXFA_TextLayout* pTextLayout = m_pNode->GetTextLayout();
  if (!pTextLayout)
    return;

  CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice();
  CFX_RectF rtText = GetRectWithoutRotate();
  CXFA_Margin* margin = m_pNode->GetMarginIfExists();
  if (margin) {
    CXFA_LayoutItem* pItem = this;
    if (!pItem->GetPrev() && !pItem->GetNext()) {
      XFA_RectWithoutMargin(rtText, margin);
    } else {
      float fTopInset = 0;
      float fBottomInset = 0;
      if (!pItem->GetPrev())
        fTopInset = margin->GetTopInset();
      else if (!pItem->GetNext())
        fBottomInset = margin->GetBottomInset();

      rtText.Deflate(margin->GetLeftInset(), fTopInset, margin->GetRightInset(),
                     fBottomInset);
    }
  }

  CFX_Matrix mt(1, 0, 0, 1, rtText.left, rtText.top);
  CFX_RectF rtClip = mtRotate.TransformRect(rtText);
  mt.Concat(mtRotate);
  pTextLayout->DrawString(pRenderDevice, mt, rtClip, GetIndex());
}

bool CXFA_FFText::IsLoaded() {
  CXFA_TextLayout* pTextLayout = m_pNode->GetTextLayout();
  return pTextLayout && !pTextLayout->m_bHasBlock;
}

bool CXFA_FFText::PerformLayout() {
  CXFA_FFDraw::PerformLayout();
  CXFA_TextLayout* pTextLayout = m_pNode->GetTextLayout();
  if (!pTextLayout)
    return false;
  if (!pTextLayout->m_bHasBlock)
    return true;

  pTextLayout->m_Blocks.clear();
  CXFA_LayoutItem* pItem = this;
  if (!pItem->GetPrev() && !pItem->GetNext())
    return true;

  pItem = pItem->GetFirst();
  while (pItem) {
    CFX_RectF rtText = pItem->GetRect(false);
    CXFA_Margin* margin = m_pNode->GetMarginIfExists();
    if (margin) {
      if (!pItem->GetPrev())
        rtText.height -= margin->GetTopInset();
      else if (!pItem->GetNext())
        rtText.height -= margin->GetBottomInset();
    }
    pTextLayout->ItemBlocks(rtText, pItem->GetIndex());
    pItem = pItem->GetNext();
  }
  pTextLayout->m_bHasBlock = false;
  return true;
}

bool CXFA_FFText::OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) {
  if (!GetRectWithoutRotate().Contains(point))
    return false;

  const wchar_t* wsURLContent = GetLinkURLAtPoint(point);
  if (!wsURLContent)
    return false;

  SetButtonDown(true);
  return true;
}

bool CXFA_FFText::OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) {
  return GetRectWithoutRotate().Contains(point) && !!GetLinkURLAtPoint(point);
}

bool CXFA_FFText::OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) {
  if (!IsButtonDown())
    return false;

  SetButtonDown(false);
  const wchar_t* wsURLContent = GetLinkURLAtPoint(point);
  if (!wsURLContent)
    return false;

  CXFA_FFDoc* pDoc = GetDoc();
  pDoc->GetDocEnvironment()->GotoURL(pDoc, wsURLContent);
  return true;
}

FWL_WidgetHit CXFA_FFText::OnHitTest(const CFX_PointF& point) {
  if (!GetRectWithoutRotate().Contains(point))
    return FWL_WidgetHit::Unknown;
  if (!GetLinkURLAtPoint(point))
    return FWL_WidgetHit::Unknown;
  return FWL_WidgetHit::HyperLink;
}

const wchar_t* CXFA_FFText::GetLinkURLAtPoint(const CFX_PointF& point) {
  CXFA_TextLayout* pTextLayout = m_pNode->GetTextLayout();
  if (!pTextLayout)
    return nullptr;

  CFX_RectF rect = GetRectWithoutRotate();
  for (const auto& pPieceLine : *pTextLayout->GetPieceLines()) {
    for (const auto& pPiece : pPieceLine->m_textPieces) {
      if (pPiece->pLinkData &&
          pPiece->rtPiece.Contains(point - rect.TopLeft())) {
        return pPiece->pLinkData->GetLinkURL();
      }
    }
  }
  return nullptr;
}
