// 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_Label.h"
#include "../../include/pdfwindow/PWL_Utils.h"

/* ---------------------------- CPWL_Label ------------------------------ */

CPWL_Label::CPWL_Label() : m_pEdit(NULL)
{
	m_pEdit = IFX_Edit::NewEdit();

	ASSERT(m_pEdit != NULL);
}

CPWL_Label::~CPWL_Label()
{
	IFX_Edit::DelEdit(m_pEdit);
}

CFX_ByteString CPWL_Label::GetClassName() const
{
	return "CPWL_Label";
}

void CPWL_Label::OnCreated()
{
	SetParamByFlag();
	SetFontSize(GetCreationParam().fFontSize);

	m_pEdit->SetFontMap(GetFontMap());
	m_pEdit->Initialize();

	if (HasFlag(PES_TEXTOVERFLOW))
	{
		SetClipRect(CPDF_Rect(0.0f,0.0f,0.0f,0.0f));
		m_pEdit->SetTextOverflow(true);
	}
}

void CPWL_Label::SetText(const FX_WCHAR* csText)
{
	m_pEdit->SetText(csText);
}

void CPWL_Label::RePosChildWnd()
{
	m_pEdit->SetPlateRect(GetClientRect());
}

void CPWL_Label::SetFontSize(FX_FLOAT fFontSize)
{
	m_pEdit->SetFontSize(fFontSize);
}

FX_FLOAT CPWL_Label::GetFontSize() const
{
	return m_pEdit->GetFontSize();
}

void CPWL_Label::SetParamByFlag()
{
	if (HasFlag(PES_LEFT))
	{
		m_pEdit->SetAlignmentH(0);
	}
	else if (HasFlag(PES_MIDDLE))
	{
		m_pEdit->SetAlignmentH(1);
	}
	else if (HasFlag(PES_RIGHT))
	{
		m_pEdit->SetAlignmentH(2);
	}
	else
	{
		m_pEdit->SetAlignmentH(0);
	}

	if (HasFlag(PES_TOP))
	{
		m_pEdit->SetAlignmentV(0);
	}
	else if (HasFlag(PES_CENTER))
	{
		m_pEdit->SetAlignmentV(1);
	}
	else if (HasFlag(PES_BOTTOM))
	{
		m_pEdit->SetAlignmentV(2);
	}
	else
	{
		m_pEdit->SetAlignmentV(0);
	}

	if (HasFlag(PES_PASSWORD))
	{
		m_pEdit->SetPasswordChar('*');
	}

	m_pEdit->SetMultiLine(HasFlag(PES_MULTILINE));
	m_pEdit->SetAutoReturn(HasFlag(PES_AUTORETURN));
	m_pEdit->SetAutoFontSize(HasFlag(PWS_AUTOFONTSIZE));
	m_pEdit->SetAutoScroll(HasFlag(PES_AUTOSCROLL));
}

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

	GetClientRect();

	CPDF_Rect rcClip;
	CPVT_WordRange wrRange = m_pEdit->GetVisibleWordRange();
	CPVT_WordRange* pRange = NULL;

	if (!HasFlag(PES_TEXTOVERFLOW))
	{
		rcClip = GetClientRect();
		pRange = &wrRange;
	}
IFX_SystemHandler* pSysHandler = GetSystemHandler();
	IFX_Edit::DrawEdit(pDevice, pUser2Device, m_pEdit,
		CPWL_Utils::PWLColorToFXColor(GetTextColor(), GetTransparency()),
		CPWL_Utils::PWLColorToFXColor(GetTextStrokeColor(), GetTransparency()),
		rcClip, CPDF_Point(0.0f,0.0f), pRange,pSysHandler, NULL);
}

void CPWL_Label::SetHorzScale(int32_t nHorzScale)
{
	m_pEdit->SetHorzScale(nHorzScale);
}

void CPWL_Label::SetCharSpace(FX_FLOAT fCharSpace)
{
	m_pEdit->SetCharSpace(fCharSpace);
}

CPDF_Rect CPWL_Label::GetContentRect() const
{
	return m_pEdit->GetContentRect();
}

void CPWL_Label::GetThisAppearanceStream(CFX_ByteTextBuf & sAppStream)
{
	CPWL_Wnd::GetThisAppearanceStream(sAppStream);

	sAppStream << GetTextAppearanceStream(CPDF_Point(0.0f, 0.0f));
}

CFX_ByteString CPWL_Label::GetTextAppearanceStream(const CPDF_Point & ptOffset) const
{
	CFX_ByteTextBuf sRet;
	CFX_ByteString sEdit = CPWL_Utils::GetEditAppStream(m_pEdit,ptOffset);

	if (sEdit.GetLength() > 0)
	{
		sRet << "BT\n" << CPWL_Utils::GetColorAppStream(GetTextColor()) << sEdit << "ET\n";
	}

	return sRet.GetByteString();
}

CFX_WideString CPWL_Label::GetText() const
{
	return m_pEdit->GetText();
}

void CPWL_Label::SetLimitChar(int32_t nLimitChar)
{
	m_pEdit->SetLimitChar(nLimitChar);
}

int32_t CPWL_Label::GetTotalWords()
{
	if (m_pEdit)
		return m_pEdit->GetTotalWords();

	return 0;
}

