package com.pdflib.cookbook.pcos.interactive;

import com.pdflib.pCOS;
import com.pdflib.pCOSException;
import com.pdflib.cookbook.pcos.pcos_cookbook_example;

/**
 * Retrieve form fields and emit field properties and values.
 * <p>
 * Required software: pCOS interface 3 (pCOS 3.x, PDFlib+PDI/PPS 7.x, TET 2.2,
 * PLOP 3.x) <br>
 * Required data: PDF document
 * <p>
 * In products that predate pCOS 3 there is a problem with the "Opt" entry in
 * field dictionaries. With thos products the options for choice fields will
 * not be displayed.
 * 
 * @version $Id: fields.java,v 1.10 2010/10/28 14:42:56 stm Exp $
 */
public class fields extends pcos_cookbook_example {

    /* This is where the data files are. Adjust as necessary. */
    private final static String SEARCH_PATH = "../input";

    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.pcos_get_string(doc, "filename"));

        int fieldcount = (int) p.pcos_get_number(doc, "length:fields");
        if (fieldcount == 0) {
            System.out.println("No form fields found\n");
        }
        else {
            System.out.println(fieldcount + " form fields found");

            for (int f = 0; f < fieldcount; f++) {
                print_field(p, doc, f);
            }
        }

        p.close_document(doc);
    }

    /**
     * Print information about a single field.
     * 
     * @param p
     *            pCOS object
     * @param doc
     *            document handle
     * @param f
     *            number of field in "fields" pseudo object array
     * @throws pCOSException
     */
    private void print_field(pCOS p, int doc, int f) throws pCOSException {
        System.out.print("field " + f + ": level="
            + (int) p.pcos_get_number(doc, "fields[" + f + "]/level") + " ");

        String res = p.pcos_get_string(doc, "fields[" + f + "]/fullname");
        System.out.print("fullname='" + res + "'; ");

        /* Check the field type /FT */
        String objtype = p.pcos_get_string(doc, "type:fields[" + f + "]/FT");
        if (objtype.equals("name")) {
            String fieldtype = p.pcos_get_string(doc, "fields[" + f + "]/FT");
            System.out.print("type='" + fieldtype + "' ");

            /*
             * Check the formatting (quadding) /Q: 0=left-justified, 1=centered,
             * 2=right-justified
             */
            if (fieldtype.equals("Btn")) {
                print_button_field(p, doc, f);
            }
            else if (fieldtype.equals("Ch")) {
                print_choice_field(p, doc, f);
            }
            else if (fieldtype.equals("Tx")) {
                print_text_field(p, doc, f);
            }
            else if (fieldtype.equals("Sig")) {
                print_signature_field(p, doc, f);
            }
        }
        else {
            System.out.println("non-terminal field without any type");
        }
    }

    /**
     * Print information about a button field.
     * 
     * @param p
     *            pCOS object
     * @param doc
     *            document handle
     * @param f
     *            number of field in "fields" pseudo object array
     * 
     * @throws pCOSException
     */
    private void print_button_field(pCOS p, int doc, int f)
        throws pCOSException {
        /* Flags in /Ff entry indicate the type of button field */
        final int pushbutton_flag = 1 << 16;
        final int radiobutton_flag = 1 << 15;

        int ff_value = 0; /* /Ff is optional and 0 is the default */
        String objtype = p.pcos_get_string(doc, "type:fields[" + f + "]/Ff");
        if (objtype.equals("number")) {
            ff_value = (int) p.pcos_get_number(doc, "fields[" + f + "]/Ff");
        }
        String type = (ff_value & pushbutton_flag) != 0 ? "pushbutton"
            : ((ff_value & radiobutton_flag) != 0 ? "radio button"
                : "check box");
        System.out.println("(" + type + " field)");

        print_value(p, doc, f, "  ");
    }

    /**
     * Print information about a signature field.
     * 
     * @param p
     *            pCOS object
     * @param doc
     *            document handle
     * @param f
     *            number of field in "fields" pseudo object array
     * 
     * @throws pCOSException
     */
    private void print_signature_field(pCOS p, int doc, int f)
        throws pCOSException {
        String prefix = "  ";
        System.out.println("(signature field)");
        String objtype = p.pcos_get_string(doc, "type:fields[" + f + "]/V");

        if (objtype.equals("dict")) {
            String res = p.pcos_get_string(doc, "fields[" + f + "]/V/Filter");
            System.out.println(prefix + "Filter: '" + res + "'");

            objtype = p.pcos_get_string(doc, "type:fields[" + f + "]/V/Name");
            if (objtype.equals("string")) {
                res = p.pcos_get_string(doc, "fields[" + f + "]/V/Name");
                System.out.println(prefix + "Name: '" + res + "'");
            }
            objtype = p.pcos_get_string(doc, "type:fields[" + f + "]/V/Reason");
            if (objtype.equals("string")) {
                res = p.pcos_get_string(doc, "fields[" + f + "]/V/Reason");
                System.out.println(prefix + "Reason: '" + res + "'");
            }
            objtype = p.pcos_get_string(doc, "type:fields[" + f + "]/V/M");
            if (objtype.equals("string")) {
                res = p.pcos_get_string(doc, "fields[" + f + "]/V/M");
                System.out.println(prefix + "Time of signing: '" + res + "'");
            }
        }
    }

    /**
     * Print information about a choice field (type /Ch).
     * 
     * @param p
     *            pCOS object
     * @param doc
     *            document handle
     * @param f
     *            number of field in "fields" pseudo object array
     * 
     * @throws pCOSException
     */
    private void print_choice_field(pCOS p, int doc, int f)
        throws pCOSException {
        String prefix = "  ";
        /* Flag in /Ff entry indicates the type of choice field */
        final int combo_flag = 1 << 17;

        int ff_value = 0; /* /Ff is optional and 0 is the default */
        String objtype = p.pcos_get_string(doc, "type:fields[" + f + "]/Ff");
        if (objtype.equals("number")) {
            ff_value = (int) p.pcos_get_number(doc, "fields[" + f + "]/Ff");
        }
        String type = (ff_value & combo_flag) != 0 ? "combo" : "list";
        System.out.println("(" + type + " box)");

        print_value(p, doc, f, prefix);

        /* List options */
        objtype = p.pcos_get_string(doc, "type:fields[" + f + "]/Opt");
        if (objtype.equals("array")) {
            int num_opt = (int) p.pcos_get_number(doc, "length:fields[" + f
                + "]/Opt");

            for (int i = 0; i < num_opt; i += 1) {
                String option = null;
                objtype = p.pcos_get_string(doc, "type:fields[" + f + "]/Opt["
                    + i + "]");
                if (objtype.equals("array")) {
                    option = p.pcos_get_string(doc, "fields[" + f + "]/Opt["
                        + i + "][1]");
                }
                else if (objtype.equals("string")) {
                    option = p.pcos_get_string(doc, "fields[" + f + "]/Opt["
                        + i + "]");
                }
                if (option != null) {
                    System.out.println(prefix + "option " + (i + 1) + "='"
                        + option + "'");
                }
            }
        }
    }

    /**
     * Print information about a text field (type /FT).
     * 
     * @param p
     *            pCOS object
     * @param doc
     *            document handle
     * @param f
     *            number of field in "fields" pseudo object array
     * 
     * @throws pCOSException
     */
    private void print_text_field(pCOS p, int doc, int f) throws pCOSException {
        String prefix = "  ";
        System.out.println("(text field)");

        /* Print value if available */
        String objtype;
        print_value(p, doc, f, prefix);

        /* Print the "quadding" (justification) */
        String[] formatnames = { "left-justified", "centered",
            "right-justified", "unknown" };

        objtype = p.pcos_get_string(doc, "type:fields[" + f + "]/Q");
        int format = 0; /* 0 is default */
        if (objtype.equals("number")) {
            format = (int) p.pcos_get_number(doc, "fields[" + f + "]/Q");
        }
        if (format < 0 || format > 2)
            format = 3;
        System.out.println(prefix + "format=" + formatnames[format]);
    }

    /**
     * Print a single /V value.
     * 
     * @param p
     *            pCOS object
     * @param doc
     *            document handle
     * @param f
     *            number of field in "fields" pseudo object array
     * @param prefix
     *            prefix for indentation
     * @throws pCOSException
     */
    private void print_value(pCOS p, int doc, int f, String prefix)
        throws pCOSException {
        String objtype = p.pcos_get_string(doc, "type:fields[" + f + "]/V");
        if (objtype.equals("name") || objtype.equals("string")) {
            String res = p.pcos_get_string(doc, "fields[" + f + "]/V");
            System.out.println(prefix + "value='" + res + "'");
        }
        else if (objtype.equals("stream")) {
            byte[] res_stream = p.pcos_get_stream(doc, "fields[" + f + "]/FT",
                "");
            System.out.println(prefix + "value='" + res_stream + "'");
        }
    }

    public fields(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[]) {
        fields example = new fields(argv, "Form fields", SEARCH_PATH,
            "$RCSfile: fields.java,v $", "$Revision: 1.10 $");
        example.execute();
    }
}

