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

#define  FPDFSDK_UNSUPPORT_CALL 100

class CFSDK_UnsupportInfo_Adapter
{
public:
    CFSDK_UnsupportInfo_Adapter(UNSUPPORT_INFO* unsp_info){ m_unsp_info = unsp_info;}
//  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(void* pData)
{
    CFSDK_UnsupportInfo_Adapter * pAdapter = (CFSDK_UnsupportInfo_Adapter *)pData;
    delete pAdapter;
}

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->GetAnnotDict();
        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->GetAnnotDict();
        CFX_ByteString cbString;
        if(pAnnotDict->KeyExist("FT"))
        {
            cbString = pAnnotDict->GetString("FT");
        }
        if(cbString.Compare("Sig") == 0)
        {
            FPDF_UnSupportError(FPDF_UNSP_ANNOT_SIG);
        }
    }

}

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 && pNameDict->KeyExist("EmbeddedFiles"))
            {
                FPDF_UnSupportError(FPDF_UNSP_DOC_ATTACHMENT);
                return;
            }
            if (pNameDict && pNameDict->KeyExist("JavaScript"))
            {
                CPDF_Dictionary* pJSDict = pNameDict->GetDict("JavaScript");
                CPDF_Array * pArray = pJSDict ? pJSDict->GetArray("Names") : NULL;
                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 = new CPDF_InterForm(pDoc,false);
    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("UseNone"))
        return PAGEMODE_USENONE;
    if (strPageMode.EqualNoCase("UseOutlines"))
        return PAGEMODE_USEOUTLINES;
    if (strPageMode.EqualNoCase("UseThumbs"))
        return PAGEMODE_USETHUMBS;
    if (strPageMode.EqualNoCase("FullScreen"))
        return PAGEMODE_FULLSCREEN;
    if (strPageMode.EqualNoCase("UseOC"))
        return PAGEMODE_USEOC;
    if (strPageMode.EqualNoCase("UseAttachments"))
        return PAGEMODE_USEATTACHMENTS;

    return PAGEMODE_UNKNOWN;
}
