// 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/fpdfppo.h"
#include "../include/fsdk_define.h"

class CPDF_PageOrganizer
{
public:
	CPDF_PageOrganizer();
	~CPDF_PageOrganizer();
	
public:
	FX_BOOL				PDFDocInit(CPDF_Document *pDestPDFDoc, CPDF_Document *pSrcPDFDoc);
	FX_BOOL				ExportPage(CPDF_Document *pSrcPDFDoc, CFX_WordArray* nPageNum, CPDF_Document *pDestPDFDoc, int nIndex);
	CPDF_Object*		PageDictGetInheritableTag(CPDF_Dictionary *pDict, CFX_ByteString nSrctag);
	FX_BOOL				UpdateReference(CPDF_Object *pObj, CPDF_Document *pDoc, CFX_MapPtrToPtr* pMapPtrToPtr);
	int					GetNewObjId(CPDF_Document *pDoc, CFX_MapPtrToPtr* pMapPtrToPtr, CPDF_Reference *pRef);
	
};


CPDF_PageOrganizer::CPDF_PageOrganizer()
{

}

CPDF_PageOrganizer::~CPDF_PageOrganizer()
{

}

FX_BOOL CPDF_PageOrganizer::PDFDocInit(CPDF_Document *pDestPDFDoc, CPDF_Document *pSrcPDFDoc)
{
	if(!pDestPDFDoc || !pSrcPDFDoc)
		return false;
	
	CPDF_Dictionary* pNewRoot = pDestPDFDoc->GetRoot();
	if(!pNewRoot)	return FALSE;
	
	//Set the document information////////////////////////////////////////////
	
	CPDF_Dictionary* DInfoDict = pDestPDFDoc->GetInfo();
	
	if(!DInfoDict)
		return FALSE;
	
	CFX_ByteString producerstr;
	
#ifdef FOXIT_CHROME_BUILD
	producerstr.Format("Google");
#else
	 producerstr.Format("Foxit PDF SDK %s - Foxit Corporation", "2.0");
#endif
	DInfoDict->SetAt("Producer", new CPDF_String(producerstr));

	//Set type////////////////////////////////////////////////////////////////
	CFX_ByteString cbRootType = pNewRoot->GetString("Type","");
	if( cbRootType.Equal("") )
	{
		pNewRoot->SetAt("Type", new CPDF_Name("Catalog"));
	}
	
	CPDF_Dictionary* pNewPages = (CPDF_Dictionary*)pNewRoot->GetElement("Pages")->GetDirect();
	if(!pNewPages)
	{
		pNewPages = new CPDF_Dictionary;
		FX_DWORD NewPagesON = pDestPDFDoc->AddIndirectObject(pNewPages);
		pNewRoot->SetAt("Pages", new CPDF_Reference(pDestPDFDoc, NewPagesON));
	}
	
	CFX_ByteString cbPageType = pNewPages->GetString("Type","");
	if(cbPageType.Equal(""))
	{
		pNewPages->SetAt("Type", new CPDF_Name("Pages"));
	}

	CPDF_Array* pKeysArray = pNewPages->GetArray("Kids");
	if(pKeysArray == NULL)
	{
		CPDF_Array* pNewKids = new CPDF_Array;
		FX_DWORD Kidsobjnum = -1;
		Kidsobjnum = pDestPDFDoc->AddIndirectObject(pNewKids);//, Kidsobjnum, Kidsgennum);
		
		pNewPages->SetAt("Kids", new CPDF_Reference(pDestPDFDoc, Kidsobjnum));//, Kidsgennum));
		pNewPages->SetAt("Count", new CPDF_Number(0));		
	}

	return true;
}

FX_BOOL CPDF_PageOrganizer::ExportPage(CPDF_Document *pSrcPDFDoc, CFX_WordArray* nPageNum, 
												CPDF_Document *pDestPDFDoc,int nIndex)
{
	int curpage =nIndex;

	CFX_MapPtrToPtr* pMapPtrToPtr = new CFX_MapPtrToPtr;
	pMapPtrToPtr->InitHashTable(1001);

	for(int i=0; i<nPageNum->GetSize(); i++)
	{
		
		CPDF_Dictionary* pCurPageDict = pDestPDFDoc->CreateNewPage(curpage);
		CPDF_Dictionary* pSrcPageDict = pSrcPDFDoc->GetPage(nPageNum->GetAt(i)-1);
		if(!pSrcPageDict || !pCurPageDict)
		{
			delete pMapPtrToPtr;
			return FALSE;
		}
		
		// Clone the page dictionary///////////
		FX_POSITION	SrcPos = pSrcPageDict->GetStartPos();
		while (SrcPos)
		{
			CFX_ByteString cbSrcKeyStr;
			CPDF_Object* pObj = pSrcPageDict->GetNextElement(SrcPos, cbSrcKeyStr);
			if(cbSrcKeyStr.Compare(("Type")) && cbSrcKeyStr.Compare(("Parent")))
			{
				if(pCurPageDict->KeyExist(cbSrcKeyStr))
					pCurPageDict->RemoveAt(cbSrcKeyStr);
				pCurPageDict->SetAt(cbSrcKeyStr, pObj->Clone());
			}
		}
		
		//inheritable item///////////////////////
		CPDF_Object* pInheritable = NULL;
		//1	MediaBox  //required
		if(!pCurPageDict->KeyExist("MediaBox"))
		{
			
			pInheritable = PageDictGetInheritableTag(pSrcPageDict, "MediaBox");
			if(!pInheritable) 
			{
				//Search the "CropBox" from source page dictionary, if not exists,we take the letter size.
				pInheritable = PageDictGetInheritableTag(pSrcPageDict, "CropBox");
				if(pInheritable)
					pCurPageDict->SetAt("MediaBox", pInheritable->Clone());
				else
				{
					//Make the default size to be letter size (8.5'x11')
					CPDF_Array* pArray = new CPDF_Array;
					pArray->AddNumber(0);
					pArray->AddNumber(0);
					pArray->AddNumber(612);
					pArray->AddNumber(792);
					pCurPageDict->SetAt("MediaBox", pArray);
				}
			}
			else
				pCurPageDict->SetAt("MediaBox", pInheritable->Clone());
		}
		//2 Resources //required
		if(!pCurPageDict->KeyExist("Resources"))
		{
			pInheritable = PageDictGetInheritableTag(pSrcPageDict, "Resources");
			if(!pInheritable) 
			{
				delete pMapPtrToPtr;
				return FALSE;
			}
			pCurPageDict->SetAt("Resources", pInheritable->Clone());
		}
		//3 CropBox  //Optional
		if(!pCurPageDict->KeyExist("CropBox"))
		{
			pInheritable = PageDictGetInheritableTag(pSrcPageDict, "CropBox");
			if(pInheritable) 
				pCurPageDict->SetAt("CropBox", pInheritable->Clone());
		}
		//4 Rotate  //Optional
		if(!pCurPageDict->KeyExist("Rotate"))
		{
			pInheritable = PageDictGetInheritableTag(pSrcPageDict, "Rotate");
			if(pInheritable) 
				pCurPageDict->SetAt("Rotate", pInheritable->Clone());
		}

		/////////////////////////////////////////////
		//Update the reference
		FX_DWORD dwOldPageObj = pSrcPageDict->GetObjNum();
		FX_DWORD dwNewPageObj = pCurPageDict->GetObjNum();
		
		pMapPtrToPtr->SetAt((FX_LPVOID)(FX_UINTPTR)dwOldPageObj, (FX_LPVOID)(FX_UINTPTR)dwNewPageObj);

		this->UpdateReference(pCurPageDict, pDestPDFDoc, pMapPtrToPtr);
		curpage++;
	}

	delete pMapPtrToPtr;
	return TRUE;
}

CPDF_Object* CPDF_PageOrganizer::PageDictGetInheritableTag(CPDF_Dictionary *pDict, CFX_ByteString nSrctag)
{
	if(!pDict || !pDict->KeyExist("Type") || nSrctag.IsEmpty())	
		return NULL;

	CPDF_Object* pType = pDict->GetElement("Type")->GetDirect();
	if(!pType || pType->GetType() != PDFOBJ_NAME)	return NULL;

	if(pType->GetString().Compare("Page"))	return NULL;

	if(!pDict->KeyExist("Parent"))	return NULL;
	CPDF_Object* pParent = pDict->GetElement("Parent")->GetDirect();
	if(!pParent || pParent->GetType() != PDFOBJ_DICTIONARY)	return NULL;
	
	CPDF_Dictionary* pp = (CPDF_Dictionary*)pParent;
	
	if(pDict->KeyExist((const char*)nSrctag))	
		return pDict->GetElement((const char*)nSrctag);
	while (pp)
	{
		if(pp->KeyExist((const char*)nSrctag))	
			return pp->GetElement((const char*)nSrctag);
		else if(pp->KeyExist("Parent"))
			pp = (CPDF_Dictionary*)pp->GetElement("Parent")->GetDirect();
		else break;
	}
	
	return NULL;
}

FX_BOOL CPDF_PageOrganizer::UpdateReference(CPDF_Object *pObj, CPDF_Document *pDoc, 
										 CFX_MapPtrToPtr* pMapPtrToPtr)
{
	switch (pObj->GetType())
	{
	case PDFOBJ_REFERENCE:
		{
			CPDF_Reference* pReference = (CPDF_Reference*)pObj;
			int newobjnum = GetNewObjId(pDoc, pMapPtrToPtr, pReference);
			if (newobjnum == 0) return FALSE;
			pReference->SetRef(pDoc, newobjnum);//, 0);
			break;
		}
	case PDFOBJ_DICTIONARY:
		{
			CPDF_Dictionary* pDict = (CPDF_Dictionary*)pObj;
			
			FX_POSITION pos = pDict->GetStartPos();
			while(pos)
			{
				CFX_ByteString key("");
				CPDF_Object* pNextObj = pDict->GetNextElement(pos, key);
				if (!FXSYS_strcmp(key, "Parent") || !FXSYS_strcmp(key, "Prev") || !FXSYS_strcmp(key, "First"))
					continue;
				if(pNextObj)
				{
					if(!UpdateReference(pNextObj, pDoc, pMapPtrToPtr))
						pDict->RemoveAt(key);
				}
				else
					return FALSE;
			}
			break;
		}
	case	PDFOBJ_ARRAY:
		{
			CPDF_Array* pArray = (CPDF_Array*)pObj;
			FX_DWORD count = pArray->GetCount();
			for(FX_DWORD i = 0; i < count; i ++)
			{
				CPDF_Object* pNextObj = pArray->GetElement(i);
				if(pNextObj)
				{
					if(!UpdateReference(pNextObj, pDoc, pMapPtrToPtr))
						return FALSE;
				}
				else
					return FALSE;
			}
			break;
		}
	case	PDFOBJ_STREAM:
		{
			CPDF_Stream* pStream = (CPDF_Stream*)pObj;
			CPDF_Dictionary* pDict = pStream->GetDict();
			if(pDict)
			{
				if(!UpdateReference(pDict, pDoc, pMapPtrToPtr))
					return FALSE;
			}
			else
				return FALSE;
			break;
		}
	default:	break;
	}

	return TRUE;
}

int	CPDF_PageOrganizer::GetNewObjId(CPDF_Document *pDoc, CFX_MapPtrToPtr* pMapPtrToPtr,
									CPDF_Reference *pRef)
{
	size_t dwObjnum = 0;
	if(!pRef)
		return 0;
	dwObjnum = pRef->GetRefObjNum();
	
	size_t dwNewObjNum = 0;
	
	pMapPtrToPtr->Lookup((FX_LPVOID)dwObjnum, (FX_LPVOID&)dwNewObjNum);
	if(dwNewObjNum)
	{
		return (int)dwNewObjNum;
	}
	else
	{
		CPDF_Object* pClone  = pRef->GetDirect()->Clone();
		if(!pClone)			return 0;
		
		if(pClone->GetType() == PDFOBJ_DICTIONARY)
		{
			CPDF_Dictionary* pDictClone = (CPDF_Dictionary*)pClone;
			if(pDictClone->KeyExist("Type"))
			{
				CFX_ByteString strType = pDictClone->GetString("Type");
				if(!FXSYS_stricmp(strType, "Pages"))
				{
					pDictClone->Release();
					return 4;
				}
				else if(!FXSYS_stricmp(strType, "Page"))
				{
					pDictClone->Release();
					return  0;
				}
			}
		}
		dwNewObjNum = pDoc->AddIndirectObject(pClone);//, onum, gnum);
		pMapPtrToPtr->SetAt((FX_LPVOID)dwObjnum, (FX_LPVOID)dwNewObjNum);
		
		if(!UpdateReference(pClone, pDoc, pMapPtrToPtr))
		{
			pClone->Release();
			return 0;
		}
		return (int)dwNewObjNum;
	}
	return 0;
}

FPDF_BOOL ParserPageRangeString(CFX_ByteString rangstring, CFX_WordArray* pageArray,int nCount)
{

	if(rangstring.GetLength() != 0)
	{
		rangstring.Remove(' ');
		int nLength = rangstring.GetLength();
		CFX_ByteString cbCompareString("0123456789-,");
		for(int i=0; i<nLength; i++)
		{
			if(cbCompareString.Find(rangstring[i]) == -1)
				return FALSE;
		}
		CFX_ByteString cbMidRange;
		int nStringFrom = 0;
		int nStringTo=0;
		while(nStringTo < nLength)
		{
			nStringTo = rangstring.Find(',',nStringFrom);
			if(nStringTo == -1)
			{
				nStringTo = nLength;
			}
			cbMidRange = rangstring.Mid(nStringFrom,nStringTo-nStringFrom);
			
			int nMid = cbMidRange.Find('-');
			if(nMid == -1)
			{
				long lPageNum = atol(cbMidRange);
				if(lPageNum <= 0 || lPageNum > nCount)
					return FALSE;
				pageArray->Add((FX_WORD)lPageNum);
			}
			else
			{
				int nStartPageNum = atol(cbMidRange.Mid(0,nMid));
				if (nStartPageNum ==0)
				{
					return FALSE;
				}


				nMid = nMid+1;
				int nEnd = cbMidRange.GetLength()-nMid;

				if(nEnd ==0)return FALSE;
				
				//				int nEndPageNum = (nEnd == 0)?nCount:atol(cbMidRange.Mid(nMid,nEnd));
				int nEndPageNum = atol(cbMidRange.Mid(nMid,nEnd));
				
				if(nStartPageNum < 0 ||nStartPageNum >nEndPageNum|| nEndPageNum > nCount)
				{
					return FALSE;
				}
				else
				{
					for(int nIndex=nStartPageNum; nIndex <= nEndPageNum; nIndex ++)
						pageArray->Add(nIndex);
				}
			}
			nStringFrom = nStringTo +1;
		}
	}
	return TRUE;
}

DLLEXPORT FPDF_BOOL STDCALL FPDF_ImportPages(FPDF_DOCUMENT dest_doc,FPDF_DOCUMENT src_doc, 
											 FPDF_BYTESTRING pagerange, int index)
{
	if(dest_doc == NULL || src_doc == NULL )
		return FALSE;
	CFX_WordArray pageArray;
	CPDF_Document* pSrcDoc = (CPDF_Document*)src_doc;
	int nCount = pSrcDoc->GetPageCount();
	if(pagerange)
	{
		if(ParserPageRangeString(pagerange,&pageArray,nCount) == FALSE)
			return FALSE;
	}
	else
	{
		for(int i=1; i<=nCount; i++)
		{
			pageArray.Add(i);
		}
	}
	
	CPDF_Document* pDestDoc = (CPDF_Document*)dest_doc;
	CPDF_PageOrganizer pageOrg;

	pageOrg.PDFDocInit(pDestDoc,pSrcDoc);

	if(pageOrg.ExportPage(pSrcDoc,&pageArray,pDestDoc,index))
		return TRUE;
	return FALSE;
}

DLLEXPORT FPDF_BOOL STDCALL FPDF_CopyViewerPreferences(FPDF_DOCUMENT dest_doc, FPDF_DOCUMENT src_doc)
{
	if(src_doc == NULL || dest_doc == NULL)
		return false;
	CPDF_Document* pSrcDoc = (CPDF_Document*)src_doc;
	CPDF_Dictionary* pSrcDict = pSrcDoc->GetRoot();
	pSrcDict = pSrcDict->GetDict(FX_BSTRC("ViewerPreferences"));;
	if(!pSrcDict)
		return FALSE;
	CPDF_Document* pDstDoc = (CPDF_Document*)dest_doc;
	CPDF_Dictionary* pDstDict = pDstDoc->GetRoot();
	if(!pDstDict)
		return FALSE;
	pDstDict->SetAt(FX_BSTRC("ViewerPreferences"), pSrcDict->Clone(TRUE));
	return TRUE;
}

