package aiko;

import com.googlecode.pngtastic.core.PngImage;
import com.googlecode.pngtastic.core.PngOptimizer;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;

public class Aiko {

    protected PDDocument document;
    protected String pdfName;
    protected boolean disableImageOptimization;
    protected boolean singlePage;
    protected float dpi = 72.0F;

    /** Syntax: <file>.pdf <page> <dpi>*/
    public static void main(String[] args) {
        Aiko aiko = new Aiko();
        aiko.run(args);

        try {
            if (aiko.document != null) {
                aiko.document.close();
            }
        } catch (IOException ignored) {}
    }

    public void run(String[] args) {
        /* Argument-parsing. */
        if (args.length == 0) {
            System.out.println(
                            "Arguments: <file>.pdf <page>\n" +
                            "OR: <file>.pdf all");
            return;
        } else if (args.length == 1) {
            System.out.println("Please specify a page number."); return;
        } else if (args.length == 3) {
            if (args[2].equalsIgnoreCase("-d")) {
                disableImageOptimization = true;
            } else {
            	try { 
            		this.dpi = Float.parseFloat(args[2]);
            	} catch (NumberFormatException nfe) {
            		nfe.printStackTrace();
            	}
            }
        }

        /* Open and load PDF */
        pdfName = args[0].substring(0, args[0].lastIndexOf('.'));
        File file = new File(args[0]);
        if (!file.exists()) {
            System.out.println("PDF file doesn't exist."); return;
        }

        try {
            document = Loader.loadPDF(file);
        } catch (IOException ioe) {
            System.out.println("Unable to load PDF."); return;
        }

        /* Parse page number */               
        int pageTotal = document.getNumberOfPages();
        int page, pageTo;
        try {
            /* Extract all images from the PDF. */
            if (args[1].equalsIgnoreCase("all")) {
                for (int i = 0; i < pageTotal; i++) {
                    extractImage(i);
                }
            } else if (args[1].contains("-")) {
                String[] split = args[1].split("-");
                page = Integer.parseInt(split[0]);
                pageTo = Integer.parseInt(split[1]);
                
                if (pageTo > pageTotal-1) {
                	System.out.println("Ignoring specified page numbers exceeding document length.");
                	pageTo = pageTotal-1;
                }
                
                /* Loop through interval. */
                for (int i = page; i <= pageTo; i++) {
                    extractImage(i);
                }
            } else {
                page = Integer.parseInt(args[1]);

                /* Extract single page. */
                singlePage = true;
                extractImage(page);
            }
        } catch (NumberFormatException nfe) {
            System.out.println("Unable to read page number(s).");
        } catch (ArrayIndexOutOfBoundsException obe) {
            System.out.println("Please specify a page number.");
        } catch (IOException ioe) {
            System.out.println("Error occurred extracting the image.");
        }
    }

    public void extractImage(int pageNum) throws IOException, NullPointerException {
        /* Render the image. */
        PDFRenderer renderer = new PDFRenderer(document);
        //BufferedImage image = renderer.renderImage(pageNum);
        BufferedImage image = renderer.renderImageWithDPI(pageNum, dpi);

        File folder = new File(pdfName);
        
        if (!singlePage && (folder.mkdirs() || folder.isDirectory())) {
            writeImage(image, pdfName + "/" + pageNum + ".png");
        } else {
            writeImage(image, pdfName + "—" + pageNum + ".png");
        }
    }
    
    public void writeImage(BufferedImage image, String path) throws IOException, NullPointerException {
    	    /* Write it into a byte[] */
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(image, "PNG", baos);

            PngOptimizer optimizer = new PngOptimizer();
            PngImage optimizedImage = optimizer.optimize(new PngImage(baos.toByteArray()));

	    if (disableImageOptimization) {
    	    	ImageIO.write(image, "PNG", new FileOutputStream(path));
    	    } else {
    	        optimizedImage.writeDataOutputStream(new FileOutputStream(path));
    	    }
    }
}

