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

typedef CFX_ArrayTemplate<CPDF_Dictionary*> CPDF_ObjectArray;
typedef CFX_ArrayTemplate<CPDF_Rect> CPDF_RectArray;

enum FPDF_TYPE { MAX, MIN };
enum FPDF_VALUE { TOP, LEFT, RIGHT, BOTTOM };

FX_BOOL IsValiableRect(CPDF_Rect rect, CPDF_Rect rcPage)
{
	if ( rect.left - rect.right > 0.000001f || 
		 rect.bottom - rect.top > 0.000001f)
		return FALSE;
	
	if (rect.left == 0.0f &&
		rect.top == 0.0f &&
		rect.right == 0.0f &&
		rect.bottom == 0.0f)
		return FALSE;
	
	if (!rcPage.IsEmpty())
	{
		if (rect.left - rcPage.left < -10.000001f ||
			rect.right - rcPage.right > 10.000001f ||
			rect.top - rcPage.top > 10.000001f ||
			rect.bottom - rcPage.bottom < -10.000001f)
			return FALSE;
	}
	
	return TRUE;
}


FX_BOOL GetContentsRect( CPDF_Document * pDoc, CPDF_Dictionary* pDict, CPDF_RectArray * pRectArray )
{
	CPDF_Page* pPDFPage = new CPDF_Page;
	pPDFPage->Load( pDoc, pDict, FALSE );
	pPDFPage->ParseContent();

	FX_POSITION pos = pPDFPage->GetFirstObjectPosition();
	
	while (pos)
	{
		CPDF_PageObject* pPageObject = pPDFPage->GetNextObject(pos);
		if (!pPageObject)continue;
		
		CPDF_Rect rc;
		rc.left = pPageObject->m_Left;
		rc.right = pPageObject->m_Right;
		rc.bottom = pPageObject->m_Bottom;
		rc.top = pPageObject->m_Top;
		
		if (IsValiableRect(rc, pDict->GetRect("MediaBox")))
		{
			pRectArray->Add(rc);
		}
	}
	
	delete pPDFPage;
	return TRUE;
}


void ParserStream( CPDF_Dictionary * pPageDic, CPDF_Dictionary* pStream, CPDF_RectArray * pRectArray, CPDF_ObjectArray * pObjectArray )
{
	if (!pStream)return;
	CPDF_Rect rect;
	if (pStream->KeyExist("Rect"))
		rect = pStream->GetRect("Rect");
	else if (pStream->KeyExist("BBox"))
		rect = pStream->GetRect("BBox");
	
	if (IsValiableRect(rect, pPageDic->GetRect("MediaBox")))
		pRectArray->Add(rect);
	
	pObjectArray->Add(pStream);
}


int ParserAnnots( CPDF_Document* pSourceDoc, CPDF_Dictionary * pPageDic, CPDF_RectArray * pRectArray, CPDF_ObjectArray * pObjectArray, int nUsage)
{
    if (!pSourceDoc || !pPageDic)
        return FLATTEN_FAIL;

    GetContentsRect( pSourceDoc, pPageDic, pRectArray );
    CPDF_Array* pAnnots = pPageDic->GetArray("Annots");
    if (!pAnnots)
        return FLATTEN_NOTHINGTODO;

    FX_DWORD dwSize = pAnnots->GetCount();
    for (int i = 0; i < (int)dwSize; i++)
    {
        CPDF_Object* pObj = pAnnots->GetElementValue(i);
        if (!pObj || pObj->GetType() != PDFOBJ_DICTIONARY)
            continue;

        CPDF_Dictionary* pAnnotDic = (CPDF_Dictionary*)pObj;
        CFX_ByteString sSubtype = pAnnotDic->GetString("Subtype");
        if (sSubtype == "Popup")
            continue;

        int nAnnotFlag = pAnnotDic->GetInteger("F");
        if (nAnnotFlag & ANNOTFLAG_HIDDEN)
            continue;

        if(nUsage == FLAT_NORMALDISPLAY)
        {
            if (nAnnotFlag & ANNOTFLAG_INVISIBLE)
                continue;

            ParserStream( pPageDic, pAnnotDic, pRectArray, pObjectArray );
        }
        else
        {
            if (nAnnotFlag & ANNOTFLAG_PRINT)
                ParserStream( pPageDic, pAnnotDic, pRectArray, pObjectArray );
        }
    }
    return FLATTEN_SUCCESS;
}


FX_FLOAT GetMinMaxValue( CPDF_RectArray& array, FPDF_TYPE type, FPDF_VALUE value)
{
	int nRects = array.GetSize();
	FX_FLOAT fRet = 0.0f;
	
	if (nRects <= 0)return 0.0f;
	
	FX_FLOAT* pArray = new FX_FLOAT[nRects];
	switch(value)
	{
	case LEFT:
		{
			for (int i = 0; i < nRects; i++)
				pArray[i] = CPDF_Rect(array.GetAt(i)).left;
			
			break;
		}
	case TOP:
		{
			for (int i = 0; i < nRects; i++)
				pArray[i] = CPDF_Rect(array.GetAt(i)).top;
			
			break;
		}
	case RIGHT:
		{
			for (int i = 0; i < nRects; i++)
				pArray[i] = CPDF_Rect(array.GetAt(i)).right;
			
			break;
		}
	case BOTTOM:
		{
			for (int i = 0; i < nRects; i++)
				pArray[i] = CPDF_Rect(array.GetAt(i)).bottom;
			
			break;
		}
	default:
		break;
	}
	fRet = pArray[0];
	if (type == MAX)
	{
		for (int i = 1; i < nRects; i++)
			if (fRet <= pArray[i])
				fRet = pArray[i];
	}
	else
	{
		for (int i = 1; i < nRects; i++)
			if (fRet >= pArray[i])
				fRet = pArray[i];
	}
	delete[] pArray;
	return fRet;
}

CPDF_Rect CalculateRect( CPDF_RectArray * pRectArray )
{

	CPDF_Rect rcRet;
	
	rcRet.left = GetMinMaxValue(*pRectArray, MIN, LEFT);
	rcRet.top = GetMinMaxValue(*pRectArray, MAX, TOP);
	rcRet.right = GetMinMaxValue(*pRectArray, MAX, RIGHT);
	rcRet.bottom = GetMinMaxValue(*pRectArray, MIN, BOTTOM);
	
	return rcRet;
}


void SetPageContents(CFX_ByteString key, CPDF_Dictionary* pPage, CPDF_Document* pDocument)
{
	CPDF_Object* pContentsObj = pPage->GetStream("Contents");
	if (!pContentsObj)
	{
		pContentsObj = pPage->GetArray("Contents");
	}
	
	if (!pContentsObj)
	{
		//Create a new contents dictionary
		if (!key.IsEmpty())
		{
			CPDF_Stream* pNewContents = new CPDF_Stream(NULL, 0, new CPDF_Dictionary);
			pPage->SetAtReference("Contents", pDocument, pDocument->AddIndirectObject(pNewContents));

			CFX_ByteString sStream;
			sStream.Format("q 1 0 0 1 0 0 cm /%s Do Q", key.c_str());
			pNewContents->SetData((const uint8_t*)sStream, sStream.GetLength(), FALSE, FALSE);
		}
		return;
	}

	int iType = pContentsObj->GetType();
	CPDF_Array* pContentsArray = NULL;
	
	switch(iType)
	{
	case PDFOBJ_STREAM:
		{
			pContentsArray = new CPDF_Array;
			CPDF_Stream* pContents = (CPDF_Stream*)pContentsObj;
			FX_DWORD dwObjNum = pDocument->AddIndirectObject(pContents);
			CPDF_StreamAcc acc;
			acc.LoadAllData(pContents);
			CFX_ByteString sStream = "q\n";
			CFX_ByteString sBody = CFX_ByteString((const FX_CHAR*)acc.GetData(), acc.GetSize());
			sStream = sStream + sBody + "\nQ";
			pContents->SetData((const uint8_t*)sStream, sStream.GetLength(), FALSE, FALSE);
			pContentsArray->AddReference(pDocument, dwObjNum);
			break;
		}
		
	case PDFOBJ_ARRAY:
		{
			pContentsArray = (CPDF_Array*)pContentsObj;
			break;
		}
	default:
		break;
	}	
	
	if (!pContentsArray)return;
	
	FX_DWORD dwObjNum = pDocument->AddIndirectObject(pContentsArray);
	pPage->SetAtReference("Contents", pDocument, dwObjNum);
	
	if (!key.IsEmpty())
	{
		CPDF_Stream* pNewContents = new CPDF_Stream(NULL, 0, new CPDF_Dictionary);
		dwObjNum = pDocument->AddIndirectObject(pNewContents);
		pContentsArray->AddReference(pDocument, dwObjNum);

		CFX_ByteString sStream;
		sStream.Format("q 1 0 0 1 0 0 cm /%s Do Q", key.c_str());
		pNewContents->SetData((const uint8_t*)sStream, sStream.GetLength(), FALSE, FALSE);
	}
}
 
CFX_AffineMatrix GetMatrix(CPDF_Rect rcAnnot, CPDF_Rect rcStream, CFX_AffineMatrix matrix)
{
	if(rcStream.IsEmpty())
		return CFX_AffineMatrix();
	
	matrix.TransformRect(rcStream);
	rcStream.Normalize();
	
	FX_FLOAT a = rcAnnot.Width()/rcStream.Width();
	FX_FLOAT d = rcAnnot.Height()/rcStream.Height();
	
	FX_FLOAT e = rcAnnot.left - rcStream.left * a;
	FX_FLOAT f = rcAnnot.bottom - rcStream.bottom * d;
	return CFX_AffineMatrix(a, 0, 0, d, e, f);
}

void GetOffset(FX_FLOAT& fa, FX_FLOAT& fd, FX_FLOAT& fe, FX_FLOAT& ff, CPDF_Rect rcAnnot, CPDF_Rect rcStream, CFX_AffineMatrix matrix)
{
	FX_FLOAT fStreamWidth = 0.0f;
	FX_FLOAT fStreamHeight = 0.0f;


	
	if (matrix.a != 0 && matrix.d != 0)
	{
		fStreamWidth = rcStream.right - rcStream.left;
		fStreamHeight = rcStream.top - rcStream.bottom;
	}
	else
	{
		fStreamWidth = rcStream.top - rcStream.bottom;
		fStreamHeight = rcStream.right - rcStream.left;
	}
	
	FX_FLOAT x1 = matrix.a * rcStream.left + matrix.c * rcStream.bottom + matrix.e;
	FX_FLOAT y1 = matrix.b * rcStream.left + matrix.d * rcStream.bottom + matrix.f;
	FX_FLOAT x2 = matrix.a * rcStream.left + matrix.c * rcStream.top + matrix.e;
	FX_FLOAT y2 = matrix.b * rcStream.left + matrix.d * rcStream.top + matrix.f;
	FX_FLOAT x3 = matrix.a * rcStream.right + matrix.c * rcStream.bottom + matrix.e;
	FX_FLOAT y3 = matrix.b * rcStream.right + matrix.d * rcStream.bottom + matrix.f;
	FX_FLOAT x4 = matrix.a * rcStream.right + matrix.c * rcStream.top + matrix.e;
	FX_FLOAT y4 = matrix.b * rcStream.right + matrix.d * rcStream.top + matrix.f;
	
	FX_FLOAT left = FX_MIN(FX_MIN(x1, x2), FX_MIN(x3, x4));
	FX_FLOAT bottom = FX_MIN(FX_MIN(y1, y2), FX_MIN(y3, y4));
	
	fa = (rcAnnot.right - rcAnnot.left)/fStreamWidth;
	fd = (rcAnnot.top - rcAnnot.bottom)/fStreamHeight;
	fe = rcAnnot.left - left * fa;
	ff = rcAnnot.bottom - bottom * fd;
}


DLLEXPORT int STDCALL FPDFPage_Flatten( FPDF_PAGE page, int nFlag)
{
	if (!page)
	{
		return FLATTEN_FAIL;
	}

	CPDF_Page * pPage = (CPDF_Page*)( page );
	CPDF_Document * pDocument = pPage->m_pDocument;
	CPDF_Dictionary * pPageDict = pPage->m_pFormDict;
	
	if ( !pDocument || !pPageDict )
	{
		return FLATTEN_FAIL;
	}

	CPDF_ObjectArray ObjectArray;
	CPDF_RectArray  RectArray;

	int iRet = FLATTEN_FAIL;
	iRet = ParserAnnots( pDocument, pPageDict, &RectArray, &ObjectArray, nFlag);
	if (iRet == FLATTEN_NOTHINGTODO || iRet == FLATTEN_FAIL)
		return iRet;

	CPDF_Rect rcOriginalCB;
	CPDF_Rect rcMerger = CalculateRect( &RectArray );
	CPDF_Rect rcOriginalMB = pPageDict->GetRect("MediaBox");

	if (pPageDict->KeyExist("CropBox"))
		rcOriginalMB = pPageDict->GetRect("CropBox");
	
	if (rcOriginalMB.IsEmpty()) 	
	{
		rcOriginalMB = CPDF_Rect(0.0f, 0.0f, 612.0f, 792.0f);
	}
	
	rcMerger.left = rcMerger.left < rcOriginalMB.left? rcOriginalMB.left : rcMerger.left;
	rcMerger.right = rcMerger.right > rcOriginalMB.right? rcOriginalMB.right : rcMerger.right;
	rcMerger.top = rcMerger.top > rcOriginalMB.top? rcOriginalMB.top : rcMerger.top;
	rcMerger.bottom = rcMerger.bottom < rcOriginalMB.bottom? rcOriginalMB.bottom : rcMerger.bottom;
	
	if (pPageDict->KeyExist("ArtBox"))
		rcOriginalCB = pPageDict->GetRect("ArtBox");
	else
		rcOriginalCB = rcOriginalMB;

	if (!rcOriginalMB.IsEmpty())
	{
		CPDF_Array* pMediaBox = new CPDF_Array();
		pMediaBox->Add(new CPDF_Number(rcOriginalMB.left));
		pMediaBox->Add(new CPDF_Number(rcOriginalMB.bottom));
		pMediaBox->Add(new CPDF_Number(rcOriginalMB.right));
		pMediaBox->Add(new CPDF_Number(rcOriginalMB.top));
		pPageDict->SetAt("MediaBox",pMediaBox);
	}

	if (!rcOriginalCB.IsEmpty())
	{
		CPDF_Array* pCropBox = new CPDF_Array();
		pCropBox->Add(new CPDF_Number(rcOriginalCB.left));
		pCropBox->Add(new CPDF_Number(rcOriginalCB.bottom));
		pCropBox->Add(new CPDF_Number(rcOriginalCB.right));
		pCropBox->Add(new CPDF_Number(rcOriginalCB.top));
		pPageDict->SetAt("ArtBox", pCropBox);
	}

	CPDF_Dictionary* pRes = pPageDict->GetDict("Resources");
	if (!pRes)
	{
		pRes = new CPDF_Dictionary;
		pPageDict->SetAt("Resources", pRes );
	}

	CPDF_Stream* pNewXObject = new CPDF_Stream(NULL, 0, new CPDF_Dictionary);
	FX_DWORD dwObjNum = pDocument->AddIndirectObject(pNewXObject);
	CPDF_Dictionary* pPageXObject = pRes->GetDict("XObject");
	if (!pPageXObject)
	{
		pPageXObject = new CPDF_Dictionary;
		pRes->SetAt("XObject", pPageXObject);
	}

	CFX_ByteString key = "";
	int nStreams = ObjectArray.GetSize();

	if (nStreams > 0)
	{
		for (int iKey = 0; /*iKey < 100*/; iKey++)
		{
			char sExtend[5] = {0};
			FXSYS_itoa(iKey, sExtend, 10);
			key = CFX_ByteString("FFT") + CFX_ByteString(sExtend);

			if (!pPageXObject->KeyExist(key))
				break;
		}
	}

	SetPageContents(key, pPageDict, pDocument);

	CPDF_Dictionary* pNewXORes = NULL;

	if (!key.IsEmpty())
	{
		pPageXObject->SetAtReference(key, pDocument, dwObjNum);
		CPDF_Dictionary* pNewOXbjectDic = pNewXObject->GetDict();
		pNewXORes = new CPDF_Dictionary;
		pNewOXbjectDic->SetAt("Resources", pNewXORes);
		pNewOXbjectDic->SetAtName("Type", "XObject");
		pNewOXbjectDic->SetAtName("Subtype", "Form");
		pNewOXbjectDic->SetAtInteger("FormType", 1);
		pNewOXbjectDic->SetAtName("Name", "FRM");
		CPDF_Rect rcBBox = pPageDict->GetRect("ArtBox");
		pNewOXbjectDic->SetAtRect("BBox", rcBBox);
	}

	for (int i = 0; i < nStreams; i++)
	{
		CPDF_Dictionary* pAnnotDic = ObjectArray.GetAt(i);
		if (!pAnnotDic)continue;

		CPDF_Rect rcAnnot = pAnnotDic->GetRect("Rect");
		rcAnnot.Normalize();

		CFX_ByteString sAnnotState = pAnnotDic->GetString("AS");
		CPDF_Dictionary* pAnnotAP = pAnnotDic->GetDict("AP");
		if (!pAnnotAP)continue;

		CPDF_Stream* pAPStream = pAnnotAP->GetStream("N");
		if (!pAPStream)
		{
			CPDF_Dictionary* pAPDic = pAnnotAP->GetDict("N");
			if (!pAPDic)continue;

			if (!sAnnotState.IsEmpty())
			{
				pAPStream = pAPDic->GetStream(sAnnotState);
			}
			else
			{
				FX_POSITION pos = pAPDic->GetStartPos();
				if (pos)
				{
					CFX_ByteString sKey;
					CPDF_Object* pFirstObj = pAPDic->GetNextElement(pos, sKey);
					if (pFirstObj)
					{
						if (pFirstObj->GetType() == PDFOBJ_REFERENCE)
							pFirstObj = pFirstObj->GetDirect();
						
						if (pFirstObj->GetType() != PDFOBJ_STREAM)
							continue;

						pAPStream = (CPDF_Stream*)pFirstObj;
					}
				}
			}
		}

		if (!pAPStream)continue;

		CPDF_Dictionary* pAPDic = pAPStream->GetDict();
		CFX_AffineMatrix matrix = pAPDic->GetMatrix("Matrix");

		CPDF_Rect rcStream;
		if (pAPDic->KeyExist("Rect"))
			rcStream = pAPDic->GetRect("Rect");
		else if (pAPDic->KeyExist("BBox"))
			rcStream = pAPDic->GetRect("BBox");

		if (rcStream.IsEmpty())continue;

		CPDF_Object* pObj = pAPStream;

		if (pObj)
		{		
			CPDF_Dictionary* pObjDic = pObj->GetDict();
			if (pObjDic)
			{
				pObjDic->SetAtName("Type", "XObject");
				pObjDic->SetAtName("Subtype", "Form");
			}
		}

		CPDF_Dictionary* pXObject = pNewXORes->GetDict("XObject");
		if (!pXObject)
		{
			pXObject = new CPDF_Dictionary;
			pNewXORes->SetAt("XObject", pXObject);
		}

		CFX_ByteString sFormName;
		sFormName.Format("F%d", i);
		FX_DWORD dwObjNum = pDocument->AddIndirectObject(pObj);
		pXObject->SetAtReference(sFormName, pDocument, dwObjNum);

		CPDF_StreamAcc acc;
		acc.LoadAllData(pNewXObject);

		const uint8_t* pData = acc.GetData();
		CFX_ByteString sStream(pData, acc.GetSize());
		CFX_ByteString sTemp;

		if (matrix.IsIdentity())
		{
			matrix.a = 1.0f;
			matrix.b = 0.0f;
			matrix.c = 0.0f;
			matrix.d = 1.0f;
			matrix.e = 0.0f;
			matrix.f = 0.0f;
		}

		CFX_AffineMatrix m = GetMatrix(rcAnnot, rcStream, matrix);
		sTemp.Format("q %f 0 0 %f %f %f cm /%s Do Q\n", m.a, m.d, m.e, m.f, sFormName.c_str());
		sStream += sTemp;

		pNewXObject->SetData((const uint8_t*)sStream, sStream.GetLength(), FALSE, FALSE);
	}
	pPageDict->RemoveAt( "Annots" );

	ObjectArray.RemoveAll();
	RectArray.RemoveAll();

	return FLATTEN_SUCCESS;
}
