// 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;
}

