// 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 "fpdfsdk/include/pdfwindow/PDFWindow.h"
#include "fpdfsdk/include/pdfwindow/PWL_Icon.h"
#include "fpdfsdk/include/pdfwindow/PWL_Label.h"
#include "fpdfsdk/include/pdfwindow/PWL_Signature.h"
#include "fpdfsdk/include/pdfwindow/PWL_Utils.h"
#include "fpdfsdk/include/pdfwindow/PWL_Wnd.h"

/* --------------------------------- CPWL_Signature_Image
 * --------------------------------- */

CPWL_Signature_Image::CPWL_Signature_Image() : m_pImage(NULL) {}

CPWL_Signature_Image::~CPWL_Signature_Image() {}

void CPWL_Signature_Image::SetImage(CFX_DIBSource* pImage) {
  m_pImage = pImage;
}

CFX_DIBSource* CPWL_Signature_Image::GetImage() {
  return m_pImage;
}

void CPWL_Signature_Image::DrawThisAppearance(CFX_RenderDevice* pDevice,
                                              CPDF_Matrix* pUser2Device) {
  CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device);

  if (m_pImage) {
    CPDF_Rect rcClient = GetClientRect();

    FX_FLOAT x, y;
    pUser2Device->Transform(rcClient.left, rcClient.top, x, y);

    pDevice->StretchDIBits(m_pImage, (int32_t)x, (int32_t)y,
                           (int32_t)rcClient.Width(),
                           (int32_t)rcClient.Height());
  }
}

void CPWL_Signature_Image::GetThisAppearanceStream(
    CFX_ByteTextBuf& sAppStream) {
  sAppStream << CPWL_Image::GetImageAppStream();
}

void CPWL_Signature_Image::GetScale(FX_FLOAT& fHScale, FX_FLOAT& fVScale) {
  FX_FLOAT fImageW, fImageH;

  GetImageSize(fImageW, fImageH);

  CPDF_Rect rcClient = GetClientRect();

  fHScale = rcClient.Width() / fImageW;
  fVScale = rcClient.Height() / fImageH;
}

/* --------------------------------- CPWL_Signature
 * --------------------------------- */

CPWL_Signature::CPWL_Signature()
    : m_pText(NULL),
      m_pDescription(NULL),
      m_pImage(NULL),
      m_bTextExist(TRUE),
      m_bImageExist(FALSE),
      m_bFlagExist(TRUE) {}

CPWL_Signature::~CPWL_Signature() {}

void CPWL_Signature::SetTextFlag(FX_BOOL bTextExist) {
  m_bTextExist = bTextExist;

  RePosChildWnd();
}

void CPWL_Signature::SetImageFlag(FX_BOOL bImageExist) {
  m_bImageExist = bImageExist;

  RePosChildWnd();
}

void CPWL_Signature::SetFoxitFlag(FX_BOOL bFlagExist) {
  m_bFlagExist = bFlagExist;
}

void CPWL_Signature::SetText(const FX_WCHAR* sText) {
  m_pText->SetText(sText);

  RePosChildWnd();
}

void CPWL_Signature::SetDescription(const FX_WCHAR* string) {
  m_pDescription->SetText(string);

  RePosChildWnd();
}

void CPWL_Signature::SetImage(CFX_DIBSource* pImage) {
  m_pImage->SetImage(pImage);

  RePosChildWnd();
}

void CPWL_Signature::SetImageStream(CPDF_Stream* pStream,
                                    const FX_CHAR* sImageAlias) {
  m_pImage->SetPDFStream(pStream);
  m_pImage->SetImageAlias(sImageAlias);

  RePosChildWnd();
}

void CPWL_Signature::RePosChildWnd() {
  CPDF_Rect rcClient = GetClientRect();

  CPDF_Rect rcText = rcClient;
  CPDF_Rect rcDescription = rcClient;

  FX_BOOL bTextVisible = m_bTextExist && m_pText->GetText().GetLength() > 0;

  if ((bTextVisible || m_bImageExist) &&
      m_pDescription->GetText().GetLength() > 0) {
    if (rcClient.Width() >= rcClient.Height()) {
      rcText.right = rcText.left + rcClient.Width() / 2.0f;
      rcDescription.left = rcDescription.right - rcClient.Width() / 2.0f;
    } else {
      rcText.bottom = rcText.top - rcClient.Height() / 2.0f;
      rcDescription.top = rcDescription.bottom + rcClient.Height() / 2.0f;
    }
  }

  m_pText->SetVisible(bTextVisible);
  m_pImage->SetVisible(m_bImageExist);

  m_pText->Move(rcText, TRUE, FALSE);
  m_pImage->Move(rcText, TRUE, FALSE);
  m_pDescription->Move(rcDescription, TRUE, FALSE);
}

void CPWL_Signature::CreateChildWnd(const PWL_CREATEPARAM& cp) {
  m_pImage = new CPWL_Signature_Image;
  PWL_CREATEPARAM icp = cp;
  icp.pParentWnd = this;
  icp.dwFlags = PWS_CHILD | PWS_VISIBLE;
  icp.sTextColor = CPWL_Color(COLORTYPE_GRAY, 0);
  m_pImage->Create(icp);

  m_pText = new CPWL_Label;
  PWL_CREATEPARAM acp = cp;
  acp.pParentWnd = this;
  acp.dwFlags = PWS_CHILD | PWS_VISIBLE | PWS_AUTOFONTSIZE | PES_MULTILINE |
                PES_AUTORETURN | PES_MIDDLE | PES_CENTER;
  acp.sTextColor = CPWL_Color(COLORTYPE_GRAY, 0);
  m_pText->Create(acp);

  m_pDescription = new CPWL_Label;
  PWL_CREATEPARAM dcp = cp;
  dcp.pParentWnd = this;
  dcp.dwFlags = PWS_CHILD | PWS_VISIBLE | PWS_AUTOFONTSIZE | PES_MULTILINE |
                PES_AUTORETURN | PES_LEFT | PES_CENTER;
  dcp.sTextColor = CPWL_Color(COLORTYPE_GRAY, 0);
  m_pDescription->Create(dcp);
}

void CPWL_Signature::DrawThisAppearance(CFX_RenderDevice* pDevice,
                                        CPDF_Matrix* pUser2Device) {
  CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device);

  if (m_bFlagExist)
    CPWL_Utils::DrawIconAppStream(
        pDevice, pUser2Device, PWL_ICONTYPE_FOXIT,
        CPWL_Utils::GetCenterSquare(GetClientRect()),
        CPWL_Color(COLORTYPE_RGB, 0.91f, 0.855f, 0.92f),
        CPWL_Color(COLORTYPE_TRANSPARENT), 255);

  /*
  CPDF_Rect rcClient = GetClientRect();

  CFX_PathData path;

  path.SetPointCount(2);
  path.SetPoint(0, rcClient.left, (rcClient.top + rcClient.bottom) * 0.5f,
  FXPT_MOVETO);
  path.SetPoint(1, rcClient.right, (rcClient.top + rcClient.bottom) * 0.5f,
  FXPT_LINETO);

  CFX_GraphStateData gsd;
  gsd.SetDashCount(2);
  gsd.m_DashArray[0] = 6.0f;
  gsd.m_DashArray[1] = 6.0f;
  gsd.m_DashPhase = 0;

  gsd.m_LineWidth = 10.0f;
  pDevice->DrawPath(&path, pUser2Device, &gsd, 0, ArgbEncode(255,255,0,0),
  FXFILL_ALTERNATE);
  */
}

void CPWL_Signature::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) {
  CPWL_Wnd::GetThisAppearanceStream(sAppStream);
}
