package de.geis.printserver;

import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Properties;

import javax.print.Doc;
import javax.print.DocFlavor;
import javax.print.DocPrintJob;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.SimpleDoc;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintJobAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.JobName;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.printing.PDFPageable;
import org.apache.commons.io.FileUtils;


public class Printer {	
	
	private String m_jobNummer = null;
	public String getJobNummer() { return m_jobNummer; }
	public void setJobNummer(String jobNummer) { m_jobNummer = jobNummer; }
	
	private boolean m_loaded = false;
	public boolean getLoaded() { return m_loaded; }
	public void setLoaded(boolean loaded) { m_loaded = loaded; }

	private File m_configFolder = null;
	public File getConfigFolder() { return m_configFolder; }
	public void setConfigFolder(File configFolder) { m_configFolder = configFolder; }
	
	private File m_errorFolder = null;
	public File getErrorFolder() { return m_errorFolder; }
	public void setErrorFolder(File errorFolder) { m_errorFolder = errorFolder; }
	
	private File m_fileFolder = null;
	public File getFileFolder() { return m_fileFolder; }
	public void setFileFolder(File fileFolder) { m_fileFolder = fileFolder; }
	
	PDDocument m_pdDocument = null;
	
//	private boolean m_withPrintDialog = false;
//    public boolean getWithPrintDialog() { return m_withPrintDialog; }
//    public void setWithPrintDialog(boolean withPrintDialog) { m_withPrintDialog = withPrintDialog; }
    
    private String m_printerName = null;
	public String getPrinterName() { return m_printerName; }
	public void setPrinterName(String printerName) { m_printerName = printerName; }
	
	private String m_pdfName = null;
	public String getPdfName() { return m_pdfName; }
	public void setPdfName(String pdfName) { this.m_pdfName = pdfName; }
	
	private String m_spoolName = null;
	public String getSpoolName() { return m_spoolName; }
	public void setSpoolName(String spoolName) { this.m_spoolName = spoolName; }
	
	
	public void loadInputStream(InputStream inputStream) throws IOException {
		m_pdDocument = PDDocument.load(inputStream);
	}

	public void loadUrl(String url) throws IOException {
		File file = null;
		FileUtils.copyURLToFile(new URL(url), file);
		
		m_pdDocument = PDDocument.load(file);
		file = null;
	}
	
	public void loadPdf(String pdfFileName) {
		try {
			File file = new File(pdfFileName);
			m_pdDocument = PDDocument.load(file);
			setLoaded(true);
		} catch (IOException e) {
			setLoaded(false);
		}
		
	}
	
	public void loadByteArray(byte[] byteArray) throws IOException {
		ByteArrayInputStream bis = new ByteArrayInputStream(byteArray);
		m_pdDocument = PDDocument.load(bis);
	}
	
    public boolean print() throws PrinterException, IOException {
    	boolean status = true;
    	System.out.println(getPdfName());
    	loadPdf(getPdfName());
    	
    	if (m_pdDocument == null)
    		return false;
    	
    	if (getLoaded() == false) {
    		return false;
    	}
    	
    	try {
    		PrinterJob printerJob = PrinterJob.getPrinterJob();
        	printerJob.setPageable(new PDFPageable(m_pdDocument));
        	printerJob.setPrintService(findPrintService(getPrinterName()));
        	setSpoolName(fillString(getSpoolName(), 10, " ", false));
        	printerJob.setJobName(getSpoolName() + getJobNummer());
//        	if (getWithPrintDialog()) {
//        		if (printerJob.printDialog()) {
//        			printerJob.print();
//        		}
//        	} else {
        		printerJob.print();
//        	}
        	
    	} catch (PrinterException pe) {
    		status = false;
    	} finally {
    		if (m_pdDocument != null) {
    			try {
    				m_pdDocument.close();
    			} catch (IOException io) {
    				status = false;
    			}
    		}
    	}
    	return status;
    }

    public Printer() {
    	setConfigFolder(Parameters.getConfigFolder());
    	setErrorFolder(Parameters.getErrorFolder());
    	setFileFolder(Parameters.getFileFolder());
    }
    
//    public Printer(boolean printDialog) {
//    	this.m_withPrintDialog = printDialog;
//    }
    
    public Printer(String configFolder) {
    	File file = null;
		try {
			FileUtils.copyURLToFile(new URL(configFolder), file);
		} catch (Exception e) {
			
		}
    	this.m_configFolder = file;
    }
    
    
    private static PrintService findPrintService(String printerName) {
    	PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null);
    	for (PrintService printService : printServices) {
    		if (printService.getName().trim().equals(printerName)) {
    			return printService;
    		}
    	}
    	return null;
    }
    
    @SuppressWarnings("resource")
	public boolean holeConfigDatei(File path) {
    	Properties props = new Properties();
    	FileInputStream fileInputStream = null;
    	FileOutputStream fileOutputStream = null;
    	
    	try {
			fileInputStream = new FileInputStream(path);

			props.load(fileInputStream);
			System.out.println("LOAD INPUTSTREAM");
			
			String status = props.getProperty("STATUS");
			System.out.println("STATUS:"+status);
			
			if (status.equals("open")) {
				setPdfName(getFileFolder()+ "\\" + props.getProperty("PDFNAME"));
				System.out.println(getPdfName());
				setJobNummer(props.getProperty("JOBNUMMER"));
				setSpoolName(props.getProperty("SPOOLNAME"));
				setPrinterName(props.getProperty("PRINTERNAME"));
				//setWithPrintDialog(getWithPrintDialog());
				try {
					/*
					if (print()) {
						System.out.println("printed!!");
						return true;
					}
					*/
					if (printAlternativ()){
						System.out.println("printed");
						return true;
					}
					
					else {
						System.out.println("not printed!!");
						if (getLoaded()) {
							props.setProperty("STATUS", "fehler:drucker nicht gefunden");
							fileOutputStream = new FileOutputStream(getErrorFolder() + "\\" + path.getName());
							props.store(fileOutputStream, null);
						}
						else {
							props.setProperty("STATUS", "fehler:pdf nicht gefunden");
							fileOutputStream = new FileOutputStream(getErrorFolder() + "\\" + path.getName());
							props.store(fileOutputStream, null);
						}
						return false;
					}
				} catch (Exception e) {
					path.delete();
					e.printStackTrace();
				} finally {
					path.delete();
					fileInputStream.close();
					if (fileOutputStream != null) {
						fileOutputStream.close();
					}
				}
			} 
			else {
				System.out.println("Hier kommt keiner hin");
			}
			
			
    	} catch (FileNotFoundException e) {
    		e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
		}
    	System.out.println("ICH BIN UNTEN BEIM FALSE");
		return false;
    }
    
    public void start() {

		File[] listoffiles = getConfigFolder().listFiles();
		File pdffile = null;
		
		for (File file : listoffiles) {
			if (file.isFile()) {
				System.out.println(file);
				boolean printStatus = holeConfigDatei(file);			
				System.out.println("PRINTSTATUS: "+ printStatus);
				
				if (printStatus) {
					pdffile = new File(getPdfName());
					file.delete();
					pdffile.delete();
				}
				else {
					file.delete();
					
				}
			}
			pdffile = null;
		}
    }
    
    static public String fillString(Object data, int totaleLenght, String fillWith, boolean isRight) {
		StringBuffer stringFueller = new StringBuffer();
		if (data == null) {
			data = "";
		}
		for (int i = 0; i < totaleLenght - data.toString().length(); ++i) {
			stringFueller.append(fillWith);
		}
		return isRight ? stringFueller.toString() + data : data + stringFueller.toString();
	}
    
    @SuppressWarnings("null")
	public boolean printAlternativ() {

    	FileInputStream fis = null;
    	System.out.println("Print Alternativ");
		try {
			fis = new FileInputStream(getPdfName());
			System.out.println("HALLO "+getPdfName());
			DocFlavor psInFormat = DocFlavor.INPUT_STREAM.PDF;
			
	    	Doc pdfDoc = new SimpleDoc(fis, psInFormat, null);
	    	PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet(); 
	    	
	    	DocPrintJob printJob = findPrintService(getPrinterName()).createPrintJob();
	    	PrintJobAttributeSet printJobAttributeSet = printJob.getAttributes();
	    	
	    	System.out.println("printJobAttributeSet: " + printJobAttributeSet.size());
	    	
	    	setSpoolName(fillString(getSpoolName(), 10, " ", false));
	    	aset.add(new JobName(getSpoolName() + getJobNummer(), null));
	    	
	    	printJob.print(pdfDoc, aset);
	    	
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		} finally {
    		try {
    			fis.close();
    		} catch (IOException io) {
    			io.printStackTrace();
    			return false;
    		}
    	}
		return true;
    }
    
	public static void main(String[] args) {
/*		
		// Test mit Property-Datei
		Printer printer = new Printer();
		try {
			printer.holeConfigDatei();
			printer.setWithPrintDialog(printer.getWithPrintDialog());
			String path = "C:\\Users\\braunp\\Desktop\\Files\\"+printer.getPdfName();
			InputStream inputStream = new FileInputStream(path);
			
			printer.loadInputStream(inputStream);
			
			if (printer.print()) {
				System.out.println("printed!!");
			}
			else {
				System.out.println("not printed!!");
			}
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			printer = null;
		}
/*	
		// Test mit InputStream
	    	try {
	    		Printer printer = new Printer();
				InputStream inputStream = new FileInputStream("C:\\Users\\braunp\\Desktop\\pdftest.pdf");
				printer.setWithPrintDialog(false);
				printer.loadInputStream(inputStream);
				
				if (printer.print()) {
					System.out.println("printed!!");
				}
				else {
					System.out.println("not printed!!");
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
	    	    	
		// Test mit URL
	    	try {
	    		Printer printer = new Printer();
				String url = "";
				printer.setWithPrintDialog(false);
				printer.loadUrl(url);
				
				if (printer.print()) {
					System.out.println("printed!!");
				}
				else {
					System.out.println("not printed!!");
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
	    	
	    // Test mit PDF
	    	try {
	    		Printer printer = new Printer();
				String pdf = "C:\\Users\\braunp\\Desktop\\pdftest.pdf";
				printer.setWithPrintDialog(false);
				printer.loadPdf(pdf);
				
				if (printer.print()) {
					System.out.println("printed!!");
				}
				else {
					System.out.println("not printed!!");
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
	    	
	    // Test mit Byte
	    	try {
	    		Printer printer = new Printer();
				byte[] bytes = {3, 6, 9, 12};
				printer.setWithPrintDialog(false);
				printer.loadByteArray(bytes);
				
				if (printer.print()) {
					System.out.println("printed!!");
				}
				else {
					System.out.println("not printed!!");
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
	    	
	    	
*/	    	
	 }
}
