// 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, (FX_INT32)x, (FX_INT32)y, 
			(FX_INT32)rcClient.Width(), (FX_INT32)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(FX_LPCWSTR sText)
{
	m_pText->SetText(sText);

	RePosChildWnd();
}

void CPWL_Signature::SetDescription(FX_LPCWSTR 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, FX_LPCSTR 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);
}


