// ************************************************************************************************************
// Author: Marcin Załęczny
// Release Date: 2010-11-08
// Licence: The GNU Lesser General Public License, version 3.0 (LGPLv3)
// ************************************************************************************************************
#include "mzXpsMetadata.h"
#include "mzFileUtils.h"
#include "mzXpsResources.h"

CXpsMetadata::CXpsMetadata()
    : _jobPT(NULL), _mxdcEmptyPT(NULL), _pagePTArray(NULL), _inMemoryThumbnails(NULL)
{
    this->setRealClassName(L"CXpsMetadata");
}

CXpsMetadata::~CXpsMetadata() {
    this->_releaseJobPT();
    this->_releaseMxdcEmptyPT();
    this->_releasePagePTArray();
    this->_releasePageInMemoryThumbnails();
}

VOID CXpsMetadata::_releaseJobPT() {
    if (this->_jobPT) {
        delete this->_jobPT;
        this->_jobPT = NULL;
    }
}

VOID CXpsMetadata::_releaseMxdcEmptyPT() {
    if (this->_mxdcEmptyPT) {
        delete this->_mxdcEmptyPT;
        this->_mxdcEmptyPT = NULL;
    }
}

VOID CXpsMetadata::_releasePagePTArray() {
    if (this->_pagePTArray) {
        INT size = this->_pagePTArray->size();
        LONG* items = this->_pagePTArray->getItemsBuf();
        CXpsPrintTicket* item;

        for (INT i = 0; i < size; i++) {
            item = (CXpsPrintTicket*)items[i];
            delete item;
        }

        delete this->_pagePTArray;
        this->_pagePTArray = NULL;
    }
}

VOID CXpsMetadata::_releasePageInMemoryThumbnails() {
    if (this->_inMemoryThumbnails) {
        INT size = this->_inMemoryThumbnails->size();
        LONG* items = this->_inMemoryThumbnails->getItemsBuf();
        CXpsMetadataThumbnail* item;

        for (INT i = 0; i < size; i++) {
            item = (CXpsMetadataThumbnail*)items[i];
            delete item;
        }

        delete this->_inMemoryThumbnails;
        this->_inMemoryThumbnails = NULL;
    }
}

VOID CXpsMetadata::addJobPT(CString PageMediaSize, CString PageOrientation, CString PageResolutionX, CString PageResolutionY) {
    if (this->_jobPT) {
        this->_releaseJobPT();
    }

    this->_jobPT = new CXpsPrintTicket();
    this->_jobPT->addPsfXmlns();
    this->_jobPT->addXsiXmlns();
    this->_jobPT->addXsdXmlns();
    this->_jobPT->addAttribute(L"version", L"1");
    this->_jobPT->addNs0000Xmlns();
    this->_jobPT->addPskXmlns();

    CXmlNode* node;
    node = this->_jobPT->createParameterInit(NULL, L"PageDevmodeSnapshot",
        L"TQBpAGMAcgBvAHMAbwBmAHQAIABYAFAAUwAgAEQAbwBjAHUAbQBlAG4AdAAgAFcAcgBpAHQAZQByAAAAAAAAAAEEAAbcAFgDA/8AAAEACQCaCzQIZAABAA8AWAICAAEAWAICAAAAQQA0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAgAAAAEAAAD/////AAAAAAAAAAAAAAAAAAAAAERJTlUiABABTAMMAMrS9nIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAEAEAAFNNVEoAAAAAEAAAAU0AaQBjAHIAbwBzAG8AZgB0ACAAWABQAFMAIABEAG8AYwB1AG0AZQBuAHQAIABXAHIAaQB0AGUAcgAAAElucHV0QmluAEZPUk1TT1VSQ0UAUkVTRExMAFVuaXJlc0RMTABJbnRlcmxlYXZpbmcAT0ZGAEltYWdlVHlwZQBKUEVHTWVkAE9yaWVudGF0aW9uAFBPUlRSQUlUAENvbGxhdGUAT0ZGAFJlc29sdXRpb24AT3B0aW9uMQBQYXBlclNpemUATEVUVEVSAENvbG9yTW9kZQAyNGJwcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAATVhEVwEBAAA=",
        COMMON_EMPTY_STRING, L"ns0000"
    );
    this->_jobPT->addItem(node);
    node = this->_jobPT->createParameterInit(NULL, L"JobCopiesAllDocuments", L"1", L"integer", L"psk");
    this->_jobPT->addItem(node);

    CXmlNode* feature;

    // default to A4 settings
    CString optPageMediaSize(L"ISOA4"), spMediaSizeWidth(L"210000"), spMediaSizeHeight(L"297000");
    feature = this->_jobPT->createPageMediaSizeFeature(NULL, optPageMediaSize, spMediaSizeWidth, spMediaSizeHeight);
    this->_jobPT->addItem(feature);

    feature = this->_jobPT->createFeatureWithOption(NULL, L"JobInputBin", L"psk", L"AutoSelect", L"psk");
    this->_jobPT->addItem(feature);
    feature = this->_jobPT->createFeatureWithOption(NULL, L"JobInterleaving", L"ns0000", L"OFF", L"ns0000");
    this->_jobPT->addItem(feature);
    feature = this->_jobPT->createFeatureWithOption(NULL, L"JobImageType", L"ns0000", L"JPEGMed", L"ns0000");
    this->_jobPT->addItem(feature);
    feature = this->_jobPT->createFeatureWithOption(NULL, L"PageOrientation", L"psk", PageOrientation, L"psk");
    this->_jobPT->addItem(feature);
    feature = this->_jobPT->createFeatureWithOption(NULL, L"DocumentCollate", L"psk", L"Uncollated", L"psk");
    this->_jobPT->addItem(feature);

    feature = this->_jobPT->createResolutionFeature(NULL, PageResolutionX, PageResolutionY);
    this->_jobPT->addItem(feature);

    feature = this->_jobPT->createPageOutputColorFeature(NULL, 24, 24);
    this->_jobPT->addItem(feature);
}

VOID CXpsMetadata::addMxdcEmptyPT() {
    if (this->_mxdcEmptyPT) {
        this->_releaseMxdcEmptyPT();
    }

    this->_mxdcEmptyPT = new CXpsPrintTicket();
    this->_mxdcEmptyPT->addPsfXmlns();
    this->_mxdcEmptyPT->addXsiXmlns();
    this->_mxdcEmptyPT->addXsdXmlns();
    this->_mxdcEmptyPT->addAttribute(L"version", L"1");
    this->_mxdcEmptyPT->addNs0000Xmlns();
    this->_mxdcEmptyPT->addPskXmlns();
}

CXpsPagePrintTicket* CXpsMetadata::getPagePT(INT pagenum) {
    if (!this->_pagePTArray || this->_pagePTArray->size() < 1) {
        return NULL;
    }

    INT size = this->_pagePTArray->size();
    LONG* items = this->_pagePTArray->getItemsBuf();
    CXpsPagePrintTicket* item;

    for (INT i = 0; i < size; i++) {
        item = (CXpsPagePrintTicket*)items[i];
        if (item->getPagenum() == pagenum) {
            return item;
        }
    }

    return NULL;
}

VOID CXpsMetadata::addPagePT(INT pagenum, CString PageMediaSize, CString PageOrientation, CString PageResolutionX, CString PageResolutionY) {
    if (pagenum < 1) {
        return;
    }

    if (!this->_pagePTArray) {
        this->_pagePTArray = new CArrayList(5);
    } else {
        if (this->getPagePT(pagenum) != NULL) {
            return;
        }
    }

    CXpsPagePrintTicket* pagePT = new CXpsPagePrintTicket(pagenum);
    pagePT->addPsfXmlns();
    pagePT->addXsiXmlns();
    pagePT->addXsdXmlns();
    pagePT->addAttribute(L"version", L"1");
    pagePT->addNs0000Xmlns();
    pagePT->addPskXmlns();

    CXmlNode* node;
    node = pagePT->createParameterInit(NULL, L"PageDevmodeSnapshot",
        L"TQBpAGMAcgBvAHMAbwBmAHQAIABYAFAAUwAgAEQAbwBjAHUAbQBlAG4AdAAgAFcAcgBpAHQAZQByAAAAAAAAAAEEAAbcAFgDA/8AAAEACQCaCzQIZAABAA8AWAICAAEAWAICAAAAQQA0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAgAAAAEAAAD/////AAAAAAAAAAAAAAAAAAAAAERJTlUiABABTAMMAMrS9nIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAEAEAAFNNVEoAAAAAEAAAAU0AaQBjAHIAbwBzAG8AZgB0ACAAWABQAFMAIABEAG8AYwB1AG0AZQBuAHQAIABXAHIAaQB0AGUAcgAAAElucHV0QmluAEZPUk1TT1VSQ0UAUkVTRExMAFVuaXJlc0RMTABJbnRlcmxlYXZpbmcAT0ZGAEltYWdlVHlwZQBKUEVHTWVkAE9yaWVudGF0aW9uAFBPUlRSQUlUAENvbGxhdGUAT0ZGAFJlc29sdXRpb24AT3B0aW9uMQBQYXBlclNpemUATEVUVEVSAENvbG9yTW9kZQAyNGJwcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAATVhEVwEBAAA=",
        COMMON_EMPTY_STRING, L"ns0000"
    );
    pagePT->addItem(node);

    CXmlNode* feature;
    // default to A4 settings
    CString optPageMediaSize(L"ISOA4"), spMediaSizeWidth(L"210000"), spMediaSizeHeight(L"297000");
    feature = pagePT->createPageMediaSizeFeature(NULL, optPageMediaSize, spMediaSizeWidth, spMediaSizeHeight);
    pagePT->addItem(feature);

    feature = pagePT->createFeatureWithOption(NULL, L"PageOrientation", L"psk", PageOrientation, L"psk");
    pagePT->addItem(feature);

    feature = pagePT->createResolutionFeature(NULL, PageResolutionX, PageResolutionY);
    pagePT->addItem(feature);

    feature = pagePT->createPageOutputColorFeature(NULL, 24, 24);
    pagePT->addItem(feature);
    
    this->_pagePTArray->append((LONG)pagePT);
}

BOOL CXpsMetadata::saveToFiles(CString dirname) {
    if (this->_jobPT) {
        this->_jobPT->saveXmlFile(dirname + L"\\Job_PT.xml");
    }
    
    if (this->_mxdcEmptyPT) {
        this->_mxdcEmptyPT->saveXmlFile(dirname + L"\\MXDC_Empty_PT.xml");
    }

    if (this->_pagePTArray) {
        INT size = this->_pagePTArray->size();
        LONG* items = this->_pagePTArray->getItemsBuf();
        CXpsPagePrintTicket* pagePT;
        for (INT i = 0; i < size; i++) {
            pagePT = (CXpsPagePrintTicket*)items[i];
            pagePT->saveXmlFile(dirname);
        }
    }

    if (this->_inMemoryThumbnails) {
        INT size = this->_inMemoryThumbnails->size();
        LONG* items = this->_inMemoryThumbnails->getItemsBuf();
        CXpsMetadataThumbnail* thumb;
        for (INT i = 0; i < size; i++) {
            thumb = (CXpsMetadataThumbnail*)items[i];
            thumb->save(dirname);
        }
    }
    
    return TRUE;
}

VOID CXpsMetadata::addInMemoryThumbnailForPage(INT pagenum, BYTE* imageBuffer, DWORD bufferSize) {
    if (pagenum > 0) {
        this->addInMemoryThumbnail(CString(L"Page") + pagenum + L"_Thumbnail.jpg", imageBuffer, bufferSize);
    }
}

VOID CXpsMetadata::addInMemoryThumbnail(CString filename, BYTE* imageBuffer, DWORD bufferSize) {
    CXpsMetadataThumbnail* thumb = new CXpsMetadataThumbnail(filename, imageBuffer, bufferSize);
    if (!this->_inMemoryThumbnails) {
        this->_inMemoryThumbnails = new CArrayList(10);
    }
    
    this->_inMemoryThumbnails->append((LONG)thumb);
}
