/* 
* Copyright 2016 Agencia Estatal de Administración Tibutaria
*
* Licencia con arreglo a la EUPL, Versión 1.1 o –en cuanto
* sean aprobadas por la Comisión Europea– versiones
* posteriores de la EUPL (la «Licencia»);
* Solo podrá usarse esta obra si se respeta la Licencia.
* Puede obtenerse una copia de la Licencia en:
*  
* https://joinup.ec.europa.eu/software/page/eupl
*  
* Salvo cuando lo exija la legislación aplicable o se acuerde
* por escrito, el programa distribuido con arreglo a la
* Licencia se distribuye «TAL CUAL», SIN GARANTÍAS NI CONDICIONES
* DE NINGÚN TIPO, ni expresasni implícitas.
*
* Véase la Licencia en el idioma concreto que rige los permisos y 
* limitaciones que establece la Licencia.
*/ 

package gestor.utiles;

import gestor.Configuracion;
import java.util.*;
import java.text.*;
import java.awt.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.awt.print.*;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.print.*;
import javax.print.attribute.*;
import javax.print.attribute.standard.*;

public final class ImpresorTicket {

    PrintService prt;
    PrinterJob pj;
    Image logo;
    Font fntArial_Grande;
    Font fntTimes_14;
    Font fntTimes_12;
    Font fntTimes_11;
    Font fntTimes_10;
    Font fntTimes_8;
    SimpleDateFormat dateFormat;
    Configuracion conf;
    String nombreImpresora;
    String plataforma;
    String numTicket;
    String horaCalculada;
    String horaEmision;
    String nombreCola = "";
    String textoTicket = "";
    String idTicket = "";
    String nif = "";
    static final float puntosMm = 72.0f / 25.4f;
    float altoPapel;
    float anchoPapel;
    float margenIzquierdo;
    float margenDerecho;
    float margenSuperior;
    float margenInferior;
    boolean imprimirCorte = false;
    byte[] codigos;
    boolean imprimirHoraCita, imprimirHoraTicket;
    String textoHoraCita;
    String textoHoraTicket;
    boolean imprimirlogo = false;
    private static final int IMG_WIDTH = 32;
    private static final int IMG_HEIGHT = 32;
    private int type;

    public void setIdTicket(String id) {
        idTicket = id;
    }

    public void setNombrePlataforma(String v) {
        plataforma = v;
    }

    public void setNumeroTicket(String n) {
        numTicket = n;
    }

    public void setHoraCalculada(Date d) {
        horaCalculada = textoHoraCita + dateFormat.format(d);
    }

    public void setHoraEmision(Date d) {
        horaEmision = textoHoraTicket + Fecha.formatoHoraHMS(d);
    }

    public void setNombreCola(String nombre) {
        nombreCola = nombre;
    }

    public String getNombreImpresora() {
        return prt.getName();
    }

    public void setImprimirCorte(boolean value) {
        imprimirCorte = value;
    }

    public void setTextoTicket(String texto) {
        textoTicket = texto;
    }

    public void setNif(String nif) {
        this.nif = nif;
    }

    public Image resizeImageWithHint(BufferedImage originalImage) {
        type = originalImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : originalImage.getType();
        BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, type);
        Graphics2D g = resizedImage.createGraphics();
        g.drawImage(originalImage, 0, 0, IMG_WIDTH, IMG_HEIGHT, null);
        g.dispose();
        g.setComposite(AlphaComposite.Src);

        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.setRenderingHint(RenderingHints.KEY_RENDERING,
                RenderingHints.VALUE_RENDER_QUALITY);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);

        return Toolkit.getDefaultToolkit().createImage(resizedImage.getSource());
    }

    BufferedImage leerficheroexterno(String nombref) {
        BufferedImage img = null;
        try {
            img = ImageIO.read(new File(nombref));
            return img;
        } catch (IOException e) {
            return null;
        }
    }

    public ImpresorTicket(String nombreImpresoraDeseada) {
        conf = gestor.Configuracion.instanciaUnica();
        codigos = conf.codigosCorteTicket;
        nombreImpresora = nombreImpresoraDeseada;
        try {
            altoPapel = pmm(conf.altoTicket);
            anchoPapel = pmm(conf.anchoTicket);
            margenIzquierdo = pmm(conf.margenTicketIzquierdo);
            margenDerecho = pmm(conf.margenTicketDerecho);
            margenSuperior = pmm(conf.margenTicketSuperior);
            margenInferior = pmm(conf.margenTicketInferior);
            imprimirHoraCita = conf.imprimirHoraCita;
            imprimirHoraTicket = conf.imprimirHoraTicket;
            if (imprimirHoraCita && imprimirHoraTicket) {
                altoPapel += pmm(6);
            }
            altoPapel += pmm(1);
            textoHoraCita = conf.textoHoraCita;
            textoHoraTicket = conf.textoHoraTicket;
            imprimirlogo = conf.imprimirLogo;

            if (imprimirlogo) {
                if (conf.iconoImpresion.length() > 4) {
                    BufferedImage buffer = leerficheroexterno(conf.iconoImpresion);
                    logo = resizeImageWithHint(buffer);
                } else {
                    logo = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/recursos/logoTique.gif"));

                }
            }
            fntArial_Grande = new Font("Arial", Font.BOLD, 48);
            fntTimes_14 = new Font("Times New Roman", Font.PLAIN, 13);
            fntTimes_12 = new Font("Times New Roman", Font.PLAIN, 12);
            fntTimes_11 = new Font("Times New Roman", Font.PLAIN, 10);
            fntTimes_10 = new Font("Times New Roman", Font.BOLD, 10);
            fntTimes_8 = new Font("Times New Roman", Font.PLAIN, 8);
            dateFormat = new SimpleDateFormat("dd/MM/yyyy  HH:mm");
            pj = PrinterJob.getPrinterJob();
            prt = buscarImpresora(nombreImpresora);
            if (prt == null) {
                pj.setPrintService(PrintServiceLookup.lookupDefaultPrintService());
                prt = pj.getPrintService();
            } else {
                pj.setPrintService(prt);
            }

            PageFormat format = pj.defaultPage();
            Paper papelTicket = format.getPaper();
            papelTicket.setSize(anchoPapel, altoPapel);
            papelTicket.setImageableArea(margenIzquierdo, margenSuperior,
                    anchoPapel - margenIzquierdo - margenDerecho, altoPapel - margenSuperior - margenInferior);
            format.setPaper(papelTicket);
            pj.setJobName("Tique Ateneo");
            pj.setPrintable(new pagina(), format);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    PrintService buscarImpresora(String nombre) {
        if (nombre != null && nombre.length() > 0) {
            PrintService[] ps = PrintServiceLookup.lookupPrintServices(null, null);
            for (PrintService p : ps) {
                if (p.getName().equalsIgnoreCase(nombre)) {
                    return p;
                }
            }
        }
        return null;
    }

    public void print() {
        try {
            pj.print();
            if (imprimirCorte) {
                cortaTicket();
            }
        } catch (Exception e) {
            javax.swing.JOptionPane.showMessageDialog(null, e.getMessage());
        }
    }

    public void cortaTicket() {
        try {
            DocFlavor flavor = DocFlavor.BYTE_ARRAY.AUTOSENSE;
            HashDocAttributeSet att = new HashDocAttributeSet();
            att.add(new DocumentName("Corte Tique", null));
            Doc docCorte = new SimpleDoc(codigos, flavor, att);
            HashPrintRequestAttributeSet attpr = new HashPrintRequestAttributeSet();
            attpr.add(new JobName("Corte Tique", null));
            DocPrintJob pjCorte = prt.createPrintJob();
            pjCorte.print(docCorte, attpr);
        } catch (Exception exc) {
            exc.printStackTrace();
        }
    }

    float pmm(float mm) {
        return mm * puntosMm;
    }

    float pmm(int mm) {
        return (float) mm * puntosMm;
    }

    class pagina implements Printable {

        float posX = 0f;
        float posY = 0f;
        Graphics2D g2;
        FontRenderContext frc;
        boolean primeraPasada = true;

        @Override
        public int print(Graphics g, PageFormat pf, int indicePag) {
            if (indicePag == 1) {
                return Printable.NO_SUCH_PAGE;
            }
            if (primeraPasada) {
                primeraPasada = false;
                return Printable.PAGE_EXISTS;
            } else {
                primeraPasada = true;  // para la proxima vuelta...

            }

            g2 = (Graphics2D) g;
            float anchoTicket = (float) pf.getImageableWidth();
            float altoTicket = (float) pf.getImageableHeight();
            posX = 0f;
            posY = 0f;
            g2.translate((int) pf.getImageableX(), (int) pf.getImageableY());
            if (imprimirlogo) {
                //  g2.translate((int) pf.getImageableX(), (int) pf.getImageableY());
                g2.drawImage(logo, 0, 0, null);
                posY = 0f;
                posX = logo.getWidth(null);
            }
            float derechaDelLogo = anchoTicket - posX;		// ancho a la derecha del logo
            ponFuente(fntTimes_14);
            imprimeTextoCentrado(conf.textoCortoAgenciaTributaria, derechaDelLogo);
            ponFuente(fntTimes_11);
            imprimeTextoCentrado(plataforma, derechaDelLogo);
            posY += pmm(4);
            posX = 0;
            ponFuente(fntTimes_12);
            imprimeTextoCentrado(nombreCola, anchoTicket);
            posX = 0;
            posY = posY - pmm(4);
            ponFuente(fntArial_Grande);
            imprimeTextoCentrado(numTicket, anchoTicket);
            posY += pmm(2);
            if (imprimirHoraCita) {
                ponFuente(fntTimes_11);
                imprimeTextoCentrado(horaCalculada, anchoTicket);
            }
            if (imprimirHoraTicket) {
                ponFuente(fntTimes_11);
                imprimeTextoCentrado(horaEmision, anchoTicket);
            }
            posY += pmm(1);
            if (textoTicket.length() > 3) {
                ponFuente(fntTimes_11);
                conf = Configuracion.instanciaUnica();
                imprimeTextoCentrado(conf.textoSalaEspera, anchoTicket);
                ponFuente(fntTimes_12);
                posY += pmm(2);
                imprimeTextoCentrado(textoTicket, anchoTicket);
            }
            ponFuente(fntTimes_8);
            imprimeLinea(idTicket + (nif.equalsIgnoreCase("XXX") ? "" : " - " + nif));
            ponFuente(fntTimes_11);
            String relleno = " ";
            Rectangle2D r2d = g2.getFont().getStringBounds(relleno, frc);
            float altoRelleno = (float) r2d.getHeight();
            int vueltas = (int) ((altoTicket - posY) / altoRelleno) - 1;
            for (int i = 0; i < vueltas; i++) {
                imprimeLinea(relleno);
            }
            imprimeTextoCentrado("_", anchoTicket);
            return Printable.PAGE_EXISTS;
        }

        void ponFuente(Font fuente) {
            g2.setFont(fuente);
            frc = g2.getFontRenderContext();
        }

        void imprimeTextoCentrado(String txt, float ancho) {
            Rectangle2D r2d = g2.getFont().getStringBounds(txt, frc);
            posY += (int) r2d.getHeight();
            float deltaAncho = (ancho - (float) r2d.getWidth()) / 2;
            if (deltaAncho < 0) {
                deltaAncho = 0;
            }
            g2.drawString(txt, posX + deltaAncho, posY);
        }

        void imprimeLinea(String txt) {
            Rectangle2D r2d = g2.getFont().getStringBounds(txt, frc);
            posY += (int) r2d.getHeight();
            g2.drawString(txt, posX, posY);
        }
    }
}
