package com.pdflib.cookbook.pcos.special;

import java.util.HashMap;
import java.util.Map;

import com.pdflib.pCOS;
import com.pdflib.pCOSException;
import com.pdflib.cookbook.pcos.pcos_cookbook_example;

/**
 * Emit the indented list of layer names which is presented in Acrobat by
 * default.
 * <p>
 * This Cookbook topic prints the layer information in the same manner as
 * Acrobat displays the layers in a hierarchical way. Note that this
 * presentation may miss layers which are actually contained in the document
 * e.g. layers which are not controlled interactively, but via JavaScript. For
 * getting a full list of all the layers in a document in a non-hierarchical
 * presentation use the "layers" Cookbook topic.
 * <p>
 * Required software: pCOS interface 3 (pCOS 2.x, PDFlib 7.x, TET 2.2,
 * PLOP 3.x)<br>
 * Required data: PDF document
 *
 * @version $Id: defaultlayers.java,v 1.2 2007/10/02 16:06:57 tm Exp $
 */
public class defaultlayers extends pcos_cookbook_example {

    /* This is where the data files are. Adjust as necessary. */
    private final static String SEARCH_PATH = "../input";

    private final static String KEY = "/Root/OCProperties";

    public void example_code(pCOS p, String filename)
            throws pCOSException, Exception {

        /* Open the PDF document */
        int doc = p.open_document(filename, "");
        if (doc == -1)
            throw new Exception("Error: " + p.get_errmsg());

        System.out.println("File name: " + p.get_string(doc, "filename"));

        String objtype = p.get_string(doc, "type:" + KEY);
        if (!objtype.equals("dict")) {
            System.out.println("No layers found\n");
            return;
        }

        /* Use the /Order array */
        objtype = p.get_string(doc, "type:" + KEY + "/D/Order");
        if (objtype.equals("array")) {
            /*
             * Prepare a Map of all locked layers because this information
             * is global for the "D" dictionary
             */
            Map locked_layers = new HashMap();

            int locked_layers_count = (int) p.get_number(doc,
                    "length:" + KEY + "/D/Locked");
            for (int i = 0; i < locked_layers_count; i += 1) {
                String locked_layer_name = p.get_string(doc,
                        KEY + "/D/Locked[" + i + "]/Name");
                locked_layers.put(locked_layer_name, new Boolean(true));
            }

            /* Recursively check all entries */
            check_ocg_entry(p, doc, 0, KEY + "/D/Order", locked_layers);
        }
        else {
            System.out.println("No recommended order for presentation of layers available.");
        }

        p.close_document(doc);
    }

    private void check_ocg_entry(pCOS p, int doc, int level, String base,
            Map locked_layers)
            throws pCOSException {
        String objtype = p.get_string(doc, "type:" + base);

        /*
         * If it's an array it indicates a nested set of layers. Indent and
         * process all subordinate OCGs.
         */
        if (objtype.equals("array")) {
            int numentries = (int) p.get_number(doc, "length:" + base);
            int i = 0;

            level++;

            /* The first element can be a string which holds a label name. */
            objtype = p.get_string(doc, "type:" + base + "[0]");

            if (objtype.equals("string")) {
                String indentation = getIndentationString(level);

                System.out.println(indentation + "["
                    + p.get_string(doc, base + "[0]") + "]");

                i = 1;
            }

            for (/* */; i < numentries; i++) {
                String path = base + "[" + i + "]";
                check_ocg_entry(p, doc, level, path, locked_layers);
            }
        }
        /* If it's a dict: print the layer Name */
        else if (objtype.equals("dict")) {
            String indentation = getIndentationString(level);
            String layer_name = p.get_string(doc, base + "/Name");
            System.out.print(indentation + layer_name);

            if (locked_layers.containsKey(layer_name)) {
                System.out.print(" (locked)");
            }

            System.out.println();
        }
        else
            System.out.println("PDF error in OCG Order array\n");
    }

    private String getIndentationString(int level) {
        int indentation = level * 4;
        StringBuffer s = new StringBuffer(indentation);
        for (int i = 0; i < indentation; i += 1) {
            s.append(' ');
        }
        return s.toString();
    }

    public defaultlayers(String[] argv, String readable_name,
        String search_path, String full_rcs_file_name, String revision) {
        super(argv, readable_name, search_path, full_rcs_file_name, revision);
    }

    public static void main(String argv[]) {
        defaultlayers example = new defaultlayers(argv, "Default layer names",
            SEARCH_PATH, "$RCSfile: defaultlayers.java,v $", "$Revision: 1.2 $");
        example.execute();
    }
}
