/* pCOS sample application for dumping PDF information
 *
 * $Id: dumper.cpp,v 1.6 2007/06/06 13:38:31 stm Exp $
 */

#include <iostream>

#include "pcos.hpp"

const string	docoptlist = "requiredmode=minimum";
const string	globaloptlist = "";

int
main(int argc, char **argv)
{
    pCOS	p;

    if (argc != 2)
    {   
        cerr << "usage: dumper <filename>" << endl;
        return(2);
    }

    try
    {
	int		count, pcosmode, plainmetadata;
	int		objtype, i, doc;

	p.set_option(globaloptlist);

	if ((doc = p.open_document(argv[1], docoptlist)) == -1)
	{
	    cout << "ERROR: " << p.get_errmsg() << endl;
	    return 98;
	}

	/* --------- general information (always available) */

	pcosmode = (int) p.get_number(doc, "pcosmode");

	cout << "   File name: " << p.get_string(doc, "filename") << endl;

	cout << " PDF version: " <<
	    p.get_number(doc, "pdfversion")/10 << endl;

	cout << "  Encryption: " <<
	    p.get_string(doc, "encrypt/description") << endl;

	cout << "   Master pw: " <<
	    (p.get_number(doc, "encrypt/master") ? "yes" : "no") << endl;

	cout << "     User pw: " <<
	    (p.get_number(doc, "encrypt/user") ? "yes" : "no") << endl;

	cout << "Text copying: " <<
	    (p.get_number(doc, "encrypt/nocopy") ? "no" : "yes") << endl;

	cout << "  Linearized: " <<
	    (p.get_number(doc, "linearized") ? "yes" : "no") << endl;

	if (pcosmode == 0)
	{
	    cerr << "Minimum mode: no more information available\n\n" << endl;
	    p.close_document(doc);
	    return 0;
	}

	/* --------- more details (requires at least user password) */

	cout << "PDF/X status: " << p.get_string(doc, "pdfx") << endl;

	cout << "PDF/A status: " << p.get_string(doc, "pdfa") << endl;

	cout << "  Tagged PDF: " <<
	    (p.get_number(doc, "tagged") ? "yes" : "no") << endl << endl;

	cout << "No. of pages: " <<
	    (int) p.get_number(doc, "length:pages") << endl;

	cout << " Page 1 size: width="
	     << p.get_number(doc, "pages[0]/width")
	     << ", height="
	     << p.get_number(doc, "pages[0]/height") << endl;

	count = (int) p.get_number(doc, "length:fonts");
	cout << "No. of fonts: " <<  count << endl;

	for (i=0; i < count; i++)
	{
	    char fonts [128];

	    // fonts[%d], i
	    sprintf(fonts, "fonts[%d]/embedded", i);
	    if (p.get_number(doc, fonts))
		cout << "embedded ";
	    else
		cout << "unembedded ";

	    sprintf(fonts, "fonts[%d]/type", i);
	    cout << p.get_string(doc, fonts) << " font ",
	    sprintf(fonts, "fonts[%d]/name", i);
	    cout << p.get_string(doc, fonts) << endl;
	}

	cout << endl;

	plainmetadata = (int) p.get_number(doc, "encrypt/plainmetadata");

	if (pcosmode == 1 && !plainmetadata &&
	    ((int) p.get_number(doc, "encrypt/nocopy")))
	{
	    cout << "Restricted mode: no more information available"
		 << endl << endl;
	    p.close_document(doc);
	    return 0;
	}

	/* --------- document info keys and XMP metadata (requires master pw) */

	count = (int) p.get_number(doc, "length:/Info");

	for (i=0; i < count; i++)
	{
	    char info[128];
	    sprintf(info, "type:/Info[%d]", i);
	    objtype = (int) p.get_number(doc, info);
	    sprintf(info, "/Info[%d].key", i);
	    cout.width(12);
	    cout << p.get_string(doc, info) << ": ";

	    /* Info entries can be stored as string or name objects */
	    if (objtype == pcos_ot_string || objtype == pcos_ot_name)
	    {
		sprintf(info, "/Info[%d]", i);
		cout << "'" << p.get_string(doc, info)<< "'" << endl;
	    }
	    else
	    {
		sprintf(info, "type:/Info[%d]", i);
		cout << "(" << p.get_string(doc, info) << " object)" << endl;
	    }
	}

	cout << endl << "XMP meta data: ";

	objtype = (int) p.get_number(doc, "type:/Root/Metadata");
	if (objtype == pcos_ot_stream)
	{
	    const unsigned char *contents;
	    int len;
	    string utf16;

	    contents = p.get_stream(doc, &len, "", "/Root/Metadata");
	    cout << len << " bytes ";

	    /* This demonstrates Unicode conversion */
	    utf16 = p.utf8_to_utf16((const char *)contents, "utf16");
	    cout << "(" << utf16.size()/2 << " Unicode characters)";
	    cout << endl << endl;
	}
	else
	{
	    cout << "not present" << endl << endl;
	}

	p.close_document(doc);
    }

    catch (pCOS::Exception &ex) {
        cerr << "pCOS exception occurred in dumper:" << endl;
	cerr << "[" << ex.get_errnum() << "] " << ex.get_apiname()
	            << ": " << ex.get_errmsg() << endl;
    }

    return 0;
}
