/*
 * This file (PdfPrinter.java) is part of DebGen-ReportPrintLib  developed by ASTRID Research.
 * All rights reserved. Reproduction, modification, use or disclosure
 * to third parties without express authority is forbidden.
 *
 *  Copyright ASTRID Research, Hungary, 2010.
 *
 *  ASTRID Research
 *  Headquaters: Csapó utca 42. Debrecen H-4029 HUNGARY
 *  Phone: +36-52-533-173        Fax: +36-52-533-174
 *  Web: http://www.astrid.hu    E-mail: info@astrid.hu
 *
 * Project name: DEBGEN-Biobank-Project.
 * File last modified at 2010.01.06 20:12
 */

package hu.astrid.printxml.printer;

import com.sun.pdfview.PDFFile;
import com.sun.pdfview.PDFPrintPage;
import hu.astrid.printxml.exception.PatientPrintException;

import javax.print.PrintService;
import java.awt.print.Book;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.PrinterJob;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URI;
import java.nio.ByteBuffer;

/**
 * Class of PDF Printer objects
 * @author inagy
 */
public class PdfPrinter {
    private static final double PAPER_A4_WIDTH = 594.992125984252;
    private static final double PAPER_A4_HEIGHT = 841.8897637795276;

    private static final double PAPER_A4_MARGIN = 18.0;

    private static final double PAPER_A4_IMAGEABLE_WIDTH = PAPER_A4_WIDTH - 2 * PAPER_A4_MARGIN;
    private static final double PAPER_A4_IMAGEABLE_HEIGHT = PAPER_A4_HEIGHT - 2 * PAPER_A4_MARGIN;

    private PrintService printService;
    private boolean showPrintDialog;


    /**
     * Default Constructor
     */
    public PdfPrinter() {
    }

    /**
     * Creates a PdfPrinter instance and sets the printService too
     * @param printService The PrintService
     */
    public PdfPrinter(PrintService printService) {
        this.printService = printService;
    }

    /**
     * Returns the printservice of this instance
     * @return The PrintService
     */
    public PrintService getPrintService() {
        return printService;
    }

    /**
     * Sets the PrintService of the current instance
     * @param printService The PrintService
     */
    public void setPrintService(PrintService printService) {
        this.printService = printService;
    }

    /**
     * Returns the value of the showPrintDialog property
     * @return the value of the showPrintDialog property
     */
    public boolean isShowPrintDialog() {
        return showPrintDialog;
    }

    /**
     * Sets the value of the showPrintDialog property
     * @param showPrintDialog The new value of the showPrintDialog property
     */
    public void setShowPrintDialog(boolean showPrintDialog) {
        this.showPrintDialog = showPrintDialog;
    }

    /**
     * Prints the pdf document from the given InputStream
     * @param pdf The InputStream of the PDF document
     * @throws PatientPrintException When the print operation is not possible
     */
    public void print(InputStream pdf) throws PatientPrintException {
        try {
            BufferedInputStream bis = new BufferedInputStream(pdf);
            ByteArrayOutputStream bao = new ByteArrayOutputStream();
            //DONE:  add buffer
            BufferedOutputStream bos = new BufferedOutputStream(bao);
            int i;
            byte[] b = new byte[1024];
            while ((i = bis.read(b)) != -1) {
                bos.write(b, 0, i);
            }
            bos.close();

            ByteBuffer bb = ByteBuffer.wrap(bao.toByteArray());
            PDFFile pdfFile = new PDFFile(bb); // Create PDF Print Page
            print(pdfFile);

        }
        catch (Exception e) {
            throw new PatientPrintException(e);
        }
    }

    /**
     * Prints the pdf document from the given URI
     * @param pdf The URI of the PDF document
     * @throws PatientPrintException When the print operation is not possible
     */
    public void print(URI pdf) throws PatientPrintException {
        try {
            print(pdf.toURL().openStream());
        } catch (MalformedURLException e) {
            throw new PatientPrintException(e, "Cannot create URL from URI");
        } catch (IOException e) {
            throw new PatientPrintException(e, "Cannot open stream");
        }
    }

    /**
     * Prints the pdf document from the given File
     * @param file The File of the PDF document
     * @throws PatientPrintException When the print operation is not possible
     */
    public void print(File file) throws PatientPrintException {
        try {
            FileInputStream fis = new FileInputStream(file);
            print(fis);
        } catch (PatientPrintException pe) {
            throw pe;
        } catch (Exception e) {
            throw new PatientPrintException(e);
        }
    }

    private void print(PDFFile pdfFile) throws PatientPrintException {
        try {
            PDFPrintPage pages = new PDFPrintPage(pdfFile);
            PrinterJob pjob = PrinterJob.getPrinterJob();
            if (printService != null) {
                pjob.setPrintService(printService);
            } else if (printService == null && showPrintDialog) {
                pjob.printDialog();
            }
            PageFormat pf = PrinterJob.getPrinterJob().defaultPage();
            Paper paper = new Paper();
            paper.setSize(PAPER_A4_WIDTH, PAPER_A4_HEIGHT);
            paper.setImageableArea(PAPER_A4_MARGIN, PAPER_A4_MARGIN, PAPER_A4_IMAGEABLE_WIDTH, PAPER_A4_IMAGEABLE_HEIGHT);
            pf.setPaper(paper);
            pjob.setJobName("Java Pdf Printing");
            Book book = new Book();
            book.append(pages, pf, pdfFile.getNumPages());
            pjob.setPageable(book);
            pjob.print();
        } catch (Exception e) {
            throw new PatientPrintException(e);
        }
    }
}
