/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.ctecinf;

import br.com.ctecinf.swing.OptionPane;
import br.com.ctecinf.table.Table;
import br.com.ctecinf.text.DateFormatter;
import br.com.ctecinf.text.NumberFormatter;
import br.com.ctecinf.text.TimeFormatter;
import br.com.ctecinf.text.TimestampFormatter;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.FontFactory;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Date;
import javax.swing.JTable;

/**
 *
 * @author Cássio Conceição
 * @since 03/07/2019
 * @version 201907
 * @see http://ctecinf.com.br/
 */
public class PDF extends PdfPageEventHelper {

    private Document document;
    private File file;

    @Override
    public void onStartPage(PdfWriter writer, Document document) {

        try {

            Rectangle pageSize = document.getPageSize();
            PdfContentByte directContent = writer.getDirectContent();

            directContent.setFontAndSize(BaseFont.createFont(), 6);

            directContent.setTextMatrix(pageSize.getLeft(10), pageSize.getBottom(10));
            directContent.showText("ctecinf.com.br - Sistemas gerenciais");

            if (!Config.get("logo.path").isEmpty()) {

                Image img = null;

                File f = new File(Config.get("logo.path"));

                if (f.exists()) {
                    img = Image.getInstance(f.getAbsolutePath());
                }

                if (img != null) {

                    img.setAbsolutePosition(pageSize.getLeft(10), pageSize.getTop(35));
                    img.scaleToFit(55f, 30f);

                    directContent.addImage(img);
                }
            }

        } catch (DocumentException | IOException ex) {
            OptionPane.error(ex);
        }
    }

    @Override
    public void onEndPage(PdfWriter writer, Document document) {

        final int currentPageNumber = writer.getCurrentPageNumber();

        try {

            Rectangle pageSize = document.getPageSize();
            PdfContentByte directContent = writer.getDirectContent();

            directContent.setFontAndSize(BaseFont.createFont(), 8);

            directContent.setTextMatrix(pageSize.getRight((pageSize.getWidth() / 2) + 10), pageSize.getBottom(10));
            directContent.showText("Página " + currentPageNumber);

        } catch (DocumentException | IOException ex) {
            OptionPane.error(ex);
        }
    }

    /**
     * Abre o documento para criacao do PDF
     *
     * @param fileName
     * @return Document
     * @throws DocumentException
     * @throws java.io.FileNotFoundException
     */
    public Document open(String fileName) throws DocumentException, FileNotFoundException {

        file = new File("pdf", fileName);

        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }

        document = new Document(PageSize.A4, 10, 10, 36, 20);

        PdfWriter.getInstance(document, new FileOutputStream(file)).setPageEvent(PDF.this);

        document.open();

        return document;
    }

    /**
     * Encerra documento para gerar o arquivo PDF
     */
    public void close() {
        document.close();
    }

    /**
     * Arquivo PDF gerado
     *
     * @return java.io.File
     */
    public File getFile() {
        return file;
    }

    /**
     * Gera o arquivo PDF de uma tabela
     *
     * @param table
     * @return
     * @throws Exception
     */
    public File parse(JTable table) throws Exception {
        return parse(null, table);
    }

    /**
     * Gera o arquivo PDF de uma tabela
     *
     * @param title
     * @param table
     * @return
     * @throws Exception
     */
    public File parse(String title, JTable table) throws Exception {

        if (table.getRowCount() == 0) {
            throw new Exception("Lista vazia.");
        }

        String dt = TimestampFormatter.format().format(new Date());

        if (title == null) {
            title = "Sistemas Gerenciais - Relatório(" + dt + ")";
        }

        Document doc = open(title.replace("Sistemas Gerenciais - ", "").replace("(", "_").replace(")", "_").replace("/", "_").replace(":", "_").replace(" ", "_") + ".pdf");

        Font fontHeader = FontFactory.getFont(Font.FontFamily.COURIER.name(), 8, Font.BOLD);
        Font fontData = FontFactory.getFont(Font.FontFamily.COURIER.name(), 8, Font.NORMAL);

        Paragraph paragraph = new Paragraph(title, fontHeader);
        paragraph.setSpacingAfter(10);
        paragraph.setAlignment(Paragraph.ALIGN_CENTER);

        doc.add(paragraph);

        int[] widths = new int[table.getColumnCount()];

        if (table instanceof Table) {

            for (int i = 0; i < table.getColumnCount(); i++) {
                int w = ((Table) table).getColumnWidth(i);
                widths[i] = w == 0 ? table.getColumn(table.getColumnName(i)).getWidth() : w;
            }

        } else {
            for (int i = 0; i < table.getColumnCount(); i++) {
                widths[i] = table.getColumn(table.getColumnName(i)).getWidth();
            }
        }

        PdfPTable pdfTable = new PdfPTable(table.getColumnCount());
        pdfTable.setWidthPercentage(100);
        pdfTable.setWidths(widths);

        for (int i = 0; i < table.getColumnCount(); i++) {

            String col = table.getColumnName(i);

            PdfPCell cell = new PdfPCell(new Phrase(col, fontHeader));
            cell.setBorder(0);
            cell.setBorderWidthBottom(1f);
            cell.setBorderColorBottom(BaseColor.BLACK);

            pdfTable.addCell(cell);
        }

        for (int i = 0; i < table.getRowCount(); i++) {

            for (int j = 0; j < table.getColumnCount(); j++) {

                Object value = table.getValueAt(i, j);
                String str = "";

                if (value != null && value.getClass().isAssignableFrom(Boolean.class)) {
                    str = (Boolean) value ? "Sim" : "Não";
                } else if (value != null && (value.getClass().isAssignableFrom(Date.class) || value.getClass().isAssignableFrom(java.sql.Date.class))) {
                    str = DateFormatter.format().format(value);
                } else if (value != null && value.getClass().isAssignableFrom(Time.class)) {
                    str = TimeFormatter.format().format(value);
                } else if (value != null && value.getClass().isAssignableFrom(Timestamp.class)) {
                    str = TimestampFormatter.format().format(value);
                } else if (value != null && (value.getClass().isAssignableFrom(Long.class) || value.getClass().isAssignableFrom(long.class))) {
                    str = NumberFormatter.format(0).format(value);
                } else if (value != null && (value.getClass().isAssignableFrom(Integer.class) || value.getClass().isAssignableFrom(int.class))) {
                    str = NumberFormatter.format(0).format(value);
                } else if (value != null && (value.getClass().isAssignableFrom(Double.class) || value.getClass().isAssignableFrom(double.class))) {
                    str = NumberFormatter.format().format(value);
                } else if (value != null && value.getClass().isAssignableFrom(BigDecimal.class)) {
                    str = NumberFormatter.format().format(value);
                } else if (value != null && (value.getClass().isAssignableFrom(Float.class) || value.getClass().isAssignableFrom(float.class))) {
                    str = NumberFormatter.format().format(value);
                } else if (value != null) {
                    str = value.toString();
                }

                PdfPCell cell = new PdfPCell(new Phrase(str, fontData));
                cell.setBorder(0);
                cell.setBorderWidthBottom(0.3f);
                cell.setBorderColorBottom(BaseColor.BLACK);

                pdfTable.addCell(cell);
            }
        }

        doc.add(pdfTable);

        close();

        return getFile();
    }
}
