// 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 "../../include/pdfwindow/PDFWindow.h"
#include "../../include/pdfwindow/PWL_Wnd.h"
#include "../../include/pdfwindow/PWL_Icon.h"
#include "../../include/pdfwindow/PWL_Signature.h"
#include "../../include/pdfwindow/PWL_Label.h"
#include "../../include/pdfwindow/PWL_Utils.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(bool bTextExist)
{
	m_bTextExist = bTextExist;

	RePosChildWnd();
}

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

	RePosChildWnd();
}

void CPWL_Signature::SetFoxitFlag(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;

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


