// 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/fsdk_define.h"
#include "../include/fpdf_ext.h"

#define  FPDFSDK_UNSUPPORT_CALL 100

class CFSDK_UnsupportInfo_Adapter
{
public:
	CFSDK_UnsupportInfo_Adapter(UNSUPPORT_INFO* unsp_info){ m_unsp_info = unsp_info;}
//	FX_BOOL NeedToPauseNow();
	void ReportError(int nErrorType);

private:
	UNSUPPORT_INFO* m_unsp_info;
};

void CFSDK_UnsupportInfo_Adapter::ReportError(int nErrorType)
{
	if(m_unsp_info && m_unsp_info->FSDK_UnSupport_Handler)
	{
		m_unsp_info->FSDK_UnSupport_Handler(m_unsp_info,nErrorType);
	}
}

void FreeUnsupportInfo(FX_LPVOID pData)
{
	CFSDK_UnsupportInfo_Adapter * pAdapter = (CFSDK_UnsupportInfo_Adapter *)pData;
	delete pAdapter;
}

FX_BOOL FPDF_UnSupportError(int nError)
{
	CFSDK_UnsupportInfo_Adapter * pAdapter = (CFSDK_UnsupportInfo_Adapter *)CPDF_ModuleMgr::Get()->GetPrivateData((void *)FPDFSDK_UNSUPPORT_CALL);

	if(!pAdapter)
		return FALSE;
	pAdapter->ReportError(nError);
	return TRUE;
}	

DLLEXPORT FPDF_BOOL STDCALL FSDK_SetUnSpObjProcessHandler(UNSUPPORT_INFO* unsp_info)
{
	if (!unsp_info || unsp_info->version!=1)
		return FALSE;
	CFSDK_UnsupportInfo_Adapter * pAdapter = new CFSDK_UnsupportInfo_Adapter(unsp_info);

	CPDF_ModuleMgr::Get()->SetPrivateData((void *)FPDFSDK_UNSUPPORT_CALL,pAdapter, &FreeUnsupportInfo);

	return TRUE;
}

void CheckUnSupportAnnot(CPDF_Document * pDoc, CPDF_Annot* pPDFAnnot)
{
	CFX_ByteString cbSubType = pPDFAnnot->GetSubType();
	if(cbSubType.Compare("3D") == 0)
	{
		FPDF_UnSupportError(FPDF_UNSP_ANNOT_3DANNOT);
	}
	else if(cbSubType.Compare("Screen") ==0)
	{
		CPDF_Dictionary* pAnnotDict = pPDFAnnot->m_pAnnotDict;
		CFX_ByteString cbString;
		if(pAnnotDict->KeyExist("IT"))
			cbString = pAnnotDict->GetString("IT");
		if(cbString.Compare("Img") != 0)
			FPDF_UnSupportError(FPDF_UNSP_ANNOT_SCREEN_MEDIA);
	}
	else if(cbSubType.Compare("Movie") ==0)
	{
		FPDF_UnSupportError(FPDF_UNSP_ANNOT_MOVIE);
	}
	else if(cbSubType.Compare("Sound") ==0)
	{
		FPDF_UnSupportError(FPDF_UNSP_ANNOT_SOUND);
	}
	else if(cbSubType.Compare("RichMedia") ==0)
	{
		FPDF_UnSupportError(FPDF_UNSP_ANNOT_SCREEN_RICHMEDIA);
	}
	else if(cbSubType.Compare("FileAttachment") ==0)
	{
		FPDF_UnSupportError(FPDF_UNSP_ANNOT_ATTACHMENT);
	}
	else if(cbSubType.Compare("Widget") ==0)
	{
		CPDF_Dictionary* pAnnotDict = pPDFAnnot->m_pAnnotDict;
		CFX_ByteString cbString;
		if(pAnnotDict->KeyExist("FT"))
		{
			cbString = pAnnotDict->GetString("FT");
		}	
		if(cbString.Compare("Sig") == 0)
		{
			FPDF_UnSupportError(FPDF_UNSP_ANNOT_SIG);
		}
	}
	
}

FX_BOOL CheckSharedForm(CXML_Element * pElement, CFX_ByteString cbName)
{
	int count = pElement->CountAttrs();
	int i=0;
	for (i = 0; i < count; i++) 
	{
		CFX_ByteString space, name; 
		CFX_WideString value;
		pElement->GetAttrByIndex(i, space, name, value);
		if (space == FX_BSTRC("xmlns") && name == FX_BSTRC("adhocwf") && value ==  L"http://ns.adobe.com/AcrobatAdhocWorkflow/1.0/")
		{
			CXML_Element *pVersion = pElement->GetElement("adhocwf",cbName);
			if (!pVersion)
				continue;
			CFX_WideString wsContent = pVersion->GetContent(0); // == 1.1
			int nType = wsContent.GetInteger();
			switch(nType)
			{
			case 1:
				FPDF_UnSupportError(FPDF_UNSP_DOC_SHAREDFORM_ACROBAT);
				break;
			case 2:
				FPDF_UnSupportError(FPDF_UNSP_DOC_SHAREDFORM_FILESYSTEM);
				break;
			case 0:
				FPDF_UnSupportError(FPDF_UNSP_DOC_SHAREDFORM_EMAIL);
				break;
			}
		}
	}

	FX_DWORD nCount = pElement->CountChildren();
	for(i=0; i<(int)nCount; i++)
	{
		CXML_Element::ChildType childType = pElement->GetChildType(i);
		if(childType == CXML_Element::Element)
		{
			CXML_Element * pChild = pElement->GetElement(i);
			if(CheckSharedForm(pChild, cbName))
				return TRUE;
		}
	}
	return FALSE;
}

void CheckUnSupportError(CPDF_Document * pDoc, FX_DWORD err_code)
{
	// Security
	if(err_code == FPDF_ERR_SECURITY)
	{
		FPDF_UnSupportError(FPDF_UNSP_DOC_SECURITY);
		return ;
	}
	if(!pDoc)
		return ;

	// Portfolios and Packages 
	CPDF_Dictionary * pRootDict = pDoc->GetRoot();
	if(pRootDict)
	{
		CFX_ByteString cbString;
		if(pRootDict->KeyExist("Collection"))
		{
			FPDF_UnSupportError(FPDF_UNSP_DOC_PORTABLECOLLECTION);
			return ;
		}
		if(pRootDict->KeyExist("Names"))
		{
			CPDF_Dictionary* pNameDict = pRootDict->GetDict("Names");
			if(pNameDict->KeyExist("EmbeddedFiles"))
			{
				FPDF_UnSupportError(FPDF_UNSP_DOC_ATTACHMENT);
				return;
			}
			else if(pNameDict->KeyExist("JavaScript"))
			{
				CPDF_Dictionary* pJSDict = pNameDict->GetDict("JavaScript");
				CPDF_Array * pArray = pJSDict->GetArray("Names");
				if (pArray) {
					int nCount = pArray->GetCount();
					for(int i=0; i<nCount; i++)
					{
						CFX_ByteString cbStr = pArray->GetString(i);
						if(cbStr.Compare("com.adobe.acrobat.SharedReview.Register") == 0)
						{
							FPDF_UnSupportError(FPDF_UNSP_DOC_SHAREDREVIEW);
							return;
						}
					}
				}
			}
		}
	}

	// SharedForm
	CPDF_Metadata metaData;
	metaData.LoadDoc(pDoc);
	CXML_Element * pElement = metaData.GetRoot();
	if(pElement)
		CheckSharedForm(pElement, "workflowType");

	
	// XFA Forms
	CPDF_InterForm * pInterForm = FX_NEW CPDF_InterForm(pDoc,FALSE);
	if (pInterForm)
	{
		if(pInterForm->HasXFAForm())
		{
			FPDF_UnSupportError(FPDF_UNSP_DOC_XFAFORM);
		}
		delete pInterForm;
	}
}

DLLEXPORT int FPDFDoc_GetPageMode(FPDF_DOCUMENT document)
{
	if (!document) return PAGEMODE_UNKNOWN;
	CPDF_Dictionary *pRoot = ((CPDF_Document*)document)->GetRoot();
	if (!pRoot)
		return PAGEMODE_UNKNOWN;
	CPDF_Object* pName = pRoot->GetElement("PageMode");
	if (!pName)
		return PAGEMODE_USENONE;
	CFX_ByteString strPageMode = pName->GetString();
	
	if (strPageMode.IsEmpty()||strPageMode.EqualNoCase(FX_BSTR("UseNone")))
		return PAGEMODE_USENONE;
	else if (strPageMode.EqualNoCase(FX_BSTR("UseOutlines")))
		return PAGEMODE_USEOUTLINES;
	else if (strPageMode.EqualNoCase(FX_BSTR("UseThumbs")))
		return PAGEMODE_USETHUMBS;
	else if (strPageMode.EqualNoCase(FX_BSTR("FullScreen")))
		return PAGEMODE_FULLSCREEN;
	else if (strPageMode.EqualNoCase(FX_BSTR("UseOC")))
		return PAGEMODE_USEOC;
	else if (strPageMode.EqualNoCase(FX_BSTR("UseAttachments")))
		return PAGEMODE_USEATTACHMENTS;

	return PAGEMODE_UNKNOWN;
}
