// 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/formfiller/FormFiller.h"
#include "../../include/formfiller/FFL_CBA_Fontmap.h"

CBA_FontMap::CBA_FontMap(CPDFSDK_Annot* pAnnot, IFX_SystemHandler* pSystemHandler) :
	CPWL_FontMap(pSystemHandler),
	m_pDocument(NULL),
	m_pAnnotDict(NULL),
	m_pDefaultFont(NULL),
	m_sAPType("N")
{
	ASSERT(pAnnot != NULL);

	CPDF_Page* pPage = pAnnot->GetPDFPage();

	m_pDocument = pPage->m_pDocument;
	m_pAnnotDict = pAnnot->GetPDFAnnot()->m_pAnnotDict;
}

CBA_FontMap::CBA_FontMap(CPDF_Document* pDocument, CPDF_Dictionary* pAnnotDict, 
						 IFX_SystemHandler* pSystemHandler) :
	CPWL_FontMap(pSystemHandler),
	m_pDocument(pDocument),
	m_pAnnotDict(pAnnotDict),
	m_pDefaultFont(NULL),
	m_sAPType("N")
{
}

CBA_FontMap::~CBA_FontMap()
{
}

void CBA_FontMap::Reset()
{
	Empty();
	m_pDefaultFont = NULL;
	m_sDefaultFontName = "";
}

void CBA_FontMap::Initial(FX_LPCSTR fontname)
{
	FX_INT32 nCharset = DEFAULT_CHARSET;

	if (!m_pDefaultFont)
	{
		m_pDefaultFont = GetAnnotDefaultFont(m_sDefaultFontName);	
		if (m_pDefaultFont)
		{
			if (const CFX_SubstFont* pSubstFont = m_pDefaultFont->GetSubstFont())
				nCharset = pSubstFont->m_Charset;
			else
			{
				if (m_sDefaultFontName == "Wingdings" || m_sDefaultFontName == "Wingdings2" ||
					m_sDefaultFontName == "Wingdings3" || m_sDefaultFontName == "Webdings")
						nCharset = SYMBOL_CHARSET;
				else
					nCharset = ANSI_CHARSET;
			}
			AddFontData(m_pDefaultFont, m_sDefaultFontName, nCharset);
			AddFontToAnnotDict(m_pDefaultFont, m_sDefaultFontName);
		}
	}

	if (nCharset != ANSI_CHARSET)
		CPWL_FontMap::Initial(fontname);
}

void CBA_FontMap::SetDefaultFont(CPDF_Font * pFont, const CFX_ByteString & sFontName)
{
	ASSERT(pFont != NULL);

	if (m_pDefaultFont) return;

	m_pDefaultFont = pFont;
	m_sDefaultFontName = sFontName;

//	if (m_sDefaultFontName.IsEmpty())
//		m_sDefaultFontName = pFont->GetFontTypeName();

	FX_INT32 nCharset = DEFAULT_CHARSET;
	if (const CFX_SubstFont* pSubstFont = m_pDefaultFont->GetSubstFont())
		nCharset = pSubstFont->m_Charset;
	AddFontData(m_pDefaultFont, m_sDefaultFontName, nCharset);
}

CPDF_Font* CBA_FontMap::FindFontSameCharset(CFX_ByteString& sFontAlias, FX_INT32 nCharset)
{
	ASSERT(m_pAnnotDict != NULL);

	if (m_pAnnotDict->GetString("Subtype") == "Widget")
	{
		CPDF_Document* pDocument = GetDocument();
		ASSERT(pDocument != NULL);

		CPDF_Dictionary * pRootDict = pDocument->GetRoot();
		if (!pRootDict) return NULL;

		CPDF_Dictionary* pAcroFormDict = pRootDict->GetDict("AcroForm");
		if (!pAcroFormDict) return NULL;

		CPDF_Dictionary * pDRDict = pAcroFormDict->GetDict("DR");
		if (!pDRDict) return NULL;

		return FindResFontSameCharset(pDRDict, sFontAlias, nCharset);
	}

	return NULL;
}

CPDF_Document* CBA_FontMap::GetDocument()
{
	return m_pDocument;
}

CPDF_Font* CBA_FontMap::FindResFontSameCharset(CPDF_Dictionary* pResDict, CFX_ByteString& sFontAlias, 
													FX_INT32 nCharset)
{
	if (!pResDict) return NULL;

	CPDF_Document* pDocument = GetDocument();
	ASSERT(pDocument != NULL);

	CPDF_Dictionary* pFonts = pResDict->GetDict("Font");
	if (pFonts == NULL) return NULL;

	CPDF_Font* pFind = NULL;

	FX_POSITION pos = pFonts->GetStartPos();
	while (pos)
	{
		CPDF_Object* pObj = NULL;
		CFX_ByteString csKey;
		pObj = pFonts->GetNextElement(pos, csKey);
		if (pObj == NULL) continue;

		CPDF_Object* pDirect = pObj->GetDirect();
		if (pDirect == NULL || pDirect->GetType() != PDFOBJ_DICTIONARY) continue;

		CPDF_Dictionary* pElement = (CPDF_Dictionary*)pDirect;
		if (pElement->GetString("Type") != "Font") continue;

		CPDF_Font* pFont = pDocument->LoadFont(pElement);
		if (pFont == NULL) continue;
		const CFX_SubstFont* pSubst = pFont->GetSubstFont();
		if (pSubst == NULL) continue;
		if (pSubst->m_Charset == nCharset)
		{
			sFontAlias = csKey;
			pFind = pFont;
		}
	}
	return pFind;
}

void CBA_FontMap::AddedFont(CPDF_Font* pFont, const CFX_ByteString& sFontAlias)
{
	AddFontToAnnotDict(pFont, sFontAlias);
}

void CBA_FontMap::AddFontToAnnotDict(CPDF_Font* pFont, const CFX_ByteString& sAlias)
{
	if (!pFont)	return;

	ASSERT(m_pAnnotDict != NULL);
	ASSERT(m_pDocument != NULL);

	CPDF_Dictionary* pAPDict = m_pAnnotDict->GetDict("AP");

	if (pAPDict == NULL) 
	{
		pAPDict = FX_NEW CPDF_Dictionary;
		m_pAnnotDict->SetAt("AP", pAPDict);
	}

	//to avoid checkbox and radiobutton
	CPDF_Object* pObject = pAPDict->GetElement(m_sAPType);
	if (pObject && pObject->GetType() == PDFOBJ_DICTIONARY)
		return;

	CPDF_Stream* pStream = pAPDict->GetStream(m_sAPType);
	if (pStream == NULL) 
	{
		pStream = FX_NEW CPDF_Stream(NULL, 0, NULL);
		FX_INT32 objnum = m_pDocument->AddIndirectObject(pStream);
		pAPDict->SetAtReference(m_sAPType, m_pDocument, objnum);
	}

	CPDF_Dictionary * pStreamDict = pStream->GetDict();

	if (!pStreamDict)
	{
		pStreamDict = FX_NEW CPDF_Dictionary;
		pStream->InitStream(NULL, 0, pStreamDict);
	}

	if (pStreamDict)
	{
		CPDF_Dictionary* pStreamResList = pStreamDict->GetDict("Resources");
		if (!pStreamResList)
		{
			pStreamResList = FX_NEW CPDF_Dictionary();
			pStreamDict->SetAt("Resources", pStreamResList);
		}

		if (pStreamResList) 
		{
			CPDF_Dictionary* pStreamResFontList = pStreamResList->GetDict("Font");
			if (!pStreamResFontList) 
			{
				pStreamResFontList = FX_NEW CPDF_Dictionary;
				FX_INT32 objnum = m_pDocument->AddIndirectObject(pStreamResFontList);
				pStreamResList->SetAtReference("Font", m_pDocument, objnum);
			}
			if (!pStreamResFontList->KeyExist(sAlias))
				pStreamResFontList->SetAtReference(sAlias, m_pDocument, pFont->GetFontDict());
		}
	}
}

CPDF_Font* CBA_FontMap::GetAnnotDefaultFont(CFX_ByteString &sAlias)
{
	ASSERT(m_pAnnotDict != NULL);
	ASSERT(m_pDocument != NULL);

	CPDF_Dictionary* pAcroFormDict = NULL;

	FX_BOOL bWidget = (m_pAnnotDict->GetString("Subtype") == "Widget");

	if (bWidget)
	{
		if (CPDF_Dictionary * pRootDict = m_pDocument->GetRoot())
			pAcroFormDict = pRootDict->GetDict("AcroForm");
	}
	
	CFX_ByteString sDA;
	
	sDA = FPDF_GetFieldAttr(m_pAnnotDict, "DA")->GetString();

	if (bWidget)
	{
		if (sDA.IsEmpty())
		{
			sDA = FPDF_GetFieldAttr(pAcroFormDict, "DA")->GetString();	
		}
	}
	
	CPDF_Dictionary * pFontDict = NULL;	

	if (!sDA.IsEmpty())
	{
		CPDF_SimpleParser syntax(sDA);
		syntax.FindTagParam("Tf", 2);
		CFX_ByteString sFontName = syntax.GetWord();
		sAlias = PDF_NameDecode(sFontName).Mid(1);

		if (CPDF_Dictionary * pDRDict = m_pAnnotDict->GetDict("DR"))
			if (CPDF_Dictionary* pDRFontDict = pDRDict->GetDict("Font"))
				pFontDict = pDRFontDict->GetDict(sAlias);

		if (!pFontDict)
			if (CPDF_Dictionary* pAPDict = m_pAnnotDict->GetDict("AP"))
				if (CPDF_Dictionary* pNormalDict = pAPDict->GetDict("N"))
					if (CPDF_Dictionary* pNormalResDict = pNormalDict->GetDict("Resources"))
						if (CPDF_Dictionary* pResFontDict = pNormalResDict->GetDict("Font"))
							pFontDict = pResFontDict->GetDict(sAlias);

		if (bWidget)
		{			
			if (!pFontDict)
			{
				if (pAcroFormDict)
				{
					if (CPDF_Dictionary * pDRDict = pAcroFormDict->GetDict("DR"))
						if (CPDF_Dictionary* pDRFontDict = pDRDict->GetDict("Font"))
							pFontDict = pDRFontDict->GetDict(sAlias);
				}
			}
		}
	}

	if (pFontDict)
		return m_pDocument->LoadFont(pFontDict);
	else
		return NULL;
}

void CBA_FontMap::SetAPType(const CFX_ByteString& sAPType)
{
	m_sAPType = sAPType;

	Reset();
	Initial();
}

