/* ====================================================================
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
==================================================================== */

package org.apache.poi.hslf.dev;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.List;
import java.util.Locale;

import org.apache.poi.ddf.DefaultEscherRecordFactory;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.ddf.EscherTextboxRecord;
import org.apache.poi.hslf.record.EscherTextboxWrapper;
import org.apache.poi.hslf.record.HSLFEscherRecordFactory;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.hslf.record.StyleTextPropAtom;
import org.apache.poi.hslf.record.TextBytesAtom;
import org.apache.poi.hslf.record.TextCharsAtom;
import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
import org.apache.poi.util.HexDump;

/**
 * This class provides a way to view the contents of a powerpoint file.
 * It will use the recored layer to grok the contents of the file, and
 *  will print out what it finds.
 *
 * @author Nick Burch
 */
public final class SlideShowRecordDumper {
    static final String tabs = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
    
    private boolean optVerbose;
    private boolean optEscher;
    private HSLFSlideShowImpl doc;
    private final PrintStream ps;

    /**
     * right now this function takes one parameter: a ppt file, and outputs a
     * dump of what it contains
     */
    public static void main(String[] args) throws IOException {
        boolean verbose = false;
        boolean escher = false;

        int ndx = 0;
        for (; ndx < args.length; ndx++) {
            if (!args[ndx].substring(0, 1).equals("-"))
                break;

            if (args[ndx].equals("-escher")) {
                escher = true;
            } else if (args[ndx].equals("-verbose")) {
                verbose = true;
            } else {
                printUsage();
                return;
            }
        }

        // parsed any options, expect exactly one remaining arg (filename)
        if (ndx != args.length - 1) {
            printUsage();
            return;
        }

        String filename = args[ndx];

        SlideShowRecordDumper foo = new SlideShowRecordDumper(System.out,
                filename, verbose, escher);

        foo.printDump();

        foo.doc.close();
    }

    public static void printUsage() {
        System.err.println("Usage: SlideShowRecordDumper [-escher] [-verbose] <filename>");
        System.err.println("Valid Options:");
        System.err.println("-escher\t\t: dump contents of escher records");
        System.err.println("-verbose\t: dump binary contents of each record");
    }

    /**
     * Constructs a Powerpoint dump from fileName. Parses the document
     * and dumps out the contents
     *
     * @param fileName The name of the file to read.
     * @throws IOException if there is a problem while parsing the document.
     */
    public SlideShowRecordDumper(PrintStream ps, String fileName, boolean verbose, boolean escher)
    throws IOException {
        this.ps = ps;
        optVerbose = verbose;
        optEscher = escher;
        doc = new HSLFSlideShowImpl(fileName);
    }


    public void printDump() throws IOException {
        // Prints out the records in the tree
        walkTree(0, 0, doc.getRecords(), 0);
    }

    public String makeHex(int number, int padding) {
        StringBuilder hex = new StringBuilder(Integer.toHexString(number).toUpperCase(Locale.ROOT));
        while (hex.length() < padding) {
            hex.insert(0, "0");
        }
        return hex.toString();
    }

    public String reverseHex(String s) {
        StringBuilder ret = new StringBuilder();

        // Get to a multiple of two
        int pos = 0;
        if ((s.length() & 1) == 1) {
            ret.append(0);
            pos++;
        }
        for (char c : s.toCharArray()) {
            if (pos > 0 && (pos & 1) == 0) {
                ret.append(' ');
            }
            ret.append(c);
            pos++;
        }

        return ret.toString();
    }

    public int getDiskLen(org.apache.poi.hslf.record.Record r) throws IOException {
        int diskLen = 0;
        if (r != null) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            r.writeOut(baos);
            diskLen = baos.size();
        }
        return diskLen;
    }

    public String getPrintableRecordContents(org.apache.poi.hslf.record.Record r) throws IOException {
        if (r == null) {
            return "<<null>>";
        }

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        r.writeOut(baos);
        byte[] b = baos.toByteArray();
        return HexDump.dump(b, 0, 0);
    }

    public void printEscherRecord(EscherRecord er, int indent) {
		if (er instanceof EscherContainerRecord) {
			printEscherContainerRecord( (EscherContainerRecord)er, indent );
		} else if (er instanceof EscherTextboxRecord) {
		    printEscherTextBox( (EscherTextboxRecord)er, indent );
		} else {
		    ps.print( tabs.substring(0, indent) );
		    ps.println(er);
		}
    }

    private void printEscherTextBox( EscherTextboxRecord tbRecord, int indent ) {
        String ind = tabs.substring(0, indent);
        ps.println(ind+"EscherTextboxRecord:");

        EscherTextboxWrapper etw = new EscherTextboxWrapper(tbRecord);
        Record prevChild = null;
        for (Record child : etw.getChildRecords()) {
            if (child instanceof StyleTextPropAtom) {
                // need preceding Text[Chars|Bytes]Atom to initialize the data structure
                String text;
                if (prevChild instanceof TextCharsAtom) {
                    text = ((TextCharsAtom)prevChild).getText();
                } else if (prevChild instanceof TextBytesAtom) {
                    text = ((TextBytesAtom)prevChild).getText();
                } else {
                    ps.println(ind+"Error! Couldn't find preceding TextAtom for style");
                    continue;
                }

                StyleTextPropAtom tsp = (StyleTextPropAtom)child;
                tsp.setParentTextSize(text.length());
            }
            ps.println(ind+ child);
            prevChild = child;
        }
 
    }
    
    private void printEscherContainerRecord( EscherContainerRecord ecr, int indent ) {
        String ind = tabs.substring(0, indent);
        ps.println(ind + ecr.getClass().getName() + " (" + ecr.getRecordName() + "):");
        ps.println(ind + "  isContainer: " + ecr.isContainerRecord());
        ps.println(ind + "  options: 0x" + HexDump.toHex( ecr.getOptions() ));
        ps.println(ind + "  recordId: 0x" + HexDump.toHex( ecr.getRecordId() ));
        
        ps.println(ind + "  numchildren: " + ecr.getChildCount());
        ps.println(ind + "  children: ");
        int count = 0;
        for ( EscherRecord record : ecr ) {
            ps.println(ind + "   Child " + count + ":");
            printEscherRecord(record, indent+1);
            count++;
        }
    }


    public void walkTree(int depth, int pos, Record[] records, int indent) throws IOException {
        String ind = tabs.substring(0, indent);

        for (org.apache.poi.hslf.record.Record r : records) {
            if (r == null) {
                ps.println(ind + "At position " + pos + " (" + makeHex(pos, 6) + "):");
                ps.println(ind + "Warning! Null record found.");
                continue;
            }

            // Figure out how big it is
            int len = getDiskLen(r);

            // Grab the type as hex
            String hexType = makeHex((int) r.getRecordType(), 4);
            String rHexType = reverseHex(hexType);

            // Grab the hslf.record type
            Class<? extends Record> c = r.getClass();
            String cname = c.toString();
            if (cname.startsWith("class ")) {
                cname = cname.substring(6);
            }
            if (cname.startsWith("org.apache.poi.hslf.record.")) {
                cname = cname.substring(27);
            }

            // Display the record
            ps.println(ind + "At position " + pos + " (" + makeHex(pos, 6) + "):");
            ps.println(ind + " Record is of type " + cname);
            ps.println(ind + " Type is " + r.getRecordType() + " (" + hexType + " -> " + rHexType + " )");
            ps.println(ind + " Len is " + (len - 8) + " (" + makeHex((len - 8), 8) + "), on disk len is " + len);

            // print additional information for drawings and atoms
            if (optEscher && cname.equals("PPDrawing")) {
                DefaultEscherRecordFactory factory = new HSLFEscherRecordFactory();

                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                r.writeOut(baos);
                byte[] b = baos.toByteArray();

                EscherRecord er = factory.createRecord(b, 0);
                er.fillFields(b, 0, factory);

                printEscherRecord(er, indent + 1);

            } else if (optVerbose && r.getChildRecords() == null) {
                String recData = getPrintableRecordContents(r);
                ps.println(ind + recData);
            }

            ps.println();

            // If it has children, show them
            if (r.getChildRecords() != null) {
                walkTree((depth + 3), pos + 8, r.getChildRecords(), indent + 1);
            }

            // Wind on the position marker
            pos += len;
        }
  }
}
