/*
 ______________________________________________________________________
 *
 * Copyright (c) 1996-2004 QUEST SOFTWARE INC.  All Rights Reserved.
 * http://java.quest.com
 *
 * This software is the confidential and proprietary information of
 * Quest Software Inc. ("Confidential Information").  You shall not disclose
 * such Confidential Information and shall use it only in accordance with the
 * terms of the license agreement you entered into with Quest Software.
 *
 * QUEST SOFTWARE MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY
 * OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 * PURPOSE, OR NON-INFRINGEMENT. QUEST SOFTWARE SHALL NOT BE LIABLE FOR ANY
 * DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 * ______________________________________________________________________
 */
//   RCSID -- $RCSfile: WepsPrintPreview.java,v $ $Revision: 1.2 $
//            $Date: 2007-06-05 21:36:06 $  $Locker:  $  Quest Software Inc.
package usda.weru.util.table;

import com.klg.jclass.table.JCPrintTable;
import com.klg.jclass.table.resources.LocaleBundle;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; 

/**
 * The <CODE>WepsPrintPreview</CODE> frame displays table print pages. It allows
 * users to flip through the pages and send the current page or all the pages
 * to the printer.
 */
public class WepsPrintPreview extends JFrame implements WindowListener, ActionListener, Printable {

    private static final long serialVersionUID = 1L;

    private static final transient Logger logger = LogManager.getLogger(WepsPrintPreview.class);

    /**
     *
     */
    protected JButton first_button;

    /**
     *
     */
    protected JButton prev_button;

    /**
     *
     */
    protected JButton next_button;

    /**
     *
     */
    protected JButton last_button;

    /**
     *
     */
    protected JButton format_button;

    /**
     *
     */
    protected JButton print_button;

    /**
     *
     */
    protected JButton printall_button;

    /**
     *
     */
    protected JButton close_button;

    /**
     *
     */
    protected JLabel status;

    /**
     *
     */
    protected JScrollPane pane;

    /**
     *
     */
    protected JCPrintTable table;

    /**
     *
     */
    protected PageFormat page_format;

    /**
     *
     */
    protected PrinterJob job;

    /**
     *
     */
    protected PageImage page_image;

    /**
     *
     */
    protected int current_page = 0;

    /**
     *
     */
    protected int num_pages = 0;

    /**
     *
     */
    protected int width;

    /**
     *
     */
    protected int height;

    /**
     * Creates a new <CODE>JCPrintPreview</CODE> frame.
     * @param table The table to preview.
     * @param title The title of the frame.
     */
    public WepsPrintPreview(String title, JCPrintTable table) {
        super(title);

        this.table = table;
        job = PrinterJob.getPrinterJob();
        if (job == null) {
            return;
        }

        job.setJobName(LocaleBundle.string(LocaleBundle.PRINT_JOB_NAME));
        page_format = table.getPageFormat();
        if (page_format == null) {
            page_format = job.defaultPage();
        }
        job.setPrintable(table);

        try {
            setupPrintTable();
        } catch (Exception e) {
            //System.out.println("The table cannot be printed: " + e.getMessage());
            return;
        }

        getContentPane().setLayout(new BorderLayout());
        setBackground(Color.lightGray);

        JPanel buttons = new JPanel();
        buttons.setLayout(new FlowLayout(FlowLayout.LEFT, 1, 1));
        first_button = new JButton(LocaleBundle.string(LocaleBundle.PP_FIRST));
        buttons.add(first_button);
        first_button.addActionListener(this);
        prev_button = new JButton(LocaleBundle.string(LocaleBundle.PP_PREVIOUS));
        buttons.add(prev_button);
        prev_button.addActionListener(this);
        next_button = new JButton(LocaleBundle.string(LocaleBundle.PP_NEXT));
        buttons.add(next_button);
        next_button.addActionListener(this);
        last_button = new JButton(LocaleBundle.string(LocaleBundle.PP_LAST));
        buttons.add(last_button);
        last_button.addActionListener(this);
        format_button
                = new JButton(LocaleBundle.string(LocaleBundle.PP_PAGE_FORMAT));
        buttons.add(format_button);
        format_button.addActionListener(this);
        print_button = new JButton(LocaleBundle.string(LocaleBundle.PP_PRINT));
        buttons.add(print_button);
        print_button.addActionListener(this);
        printall_button
                = new JButton(LocaleBundle.string(LocaleBundle.PP_PRINTALL));
        buttons.add(printall_button);
        printall_button.addActionListener(this);
        close_button = new JButton(LocaleBundle.string(LocaleBundle.PP_CLOSE));
        buttons.add(close_button);
        close_button.addActionListener(this);

        getContentPane().add(buttons, BorderLayout.NORTH);

        Dimension d = new Dimension((int) (width * 1.05), (int) (height * 1.05));

        page_image = new PageImage(d);
        page_image.setSize(page_image.getPreferredSize());

        pane = new JScrollPane(page_image);

        getContentPane().add(pane, BorderLayout.CENTER);
        getContentPane().add(status = new JLabel("", JLabel.LEFT),
                BorderLayout.SOUTH);

        addWindowListener(this);

        setSize(600, 500);
        setVisible(true);
    }

    /**
     *
     */
    public void setupPrintTable() {
        Dimension pd = new Dimension(0, 0);
        table.setPageFormat(page_format);
        pd.height = (int) page_format.getHeight();
        pd.width = (int) page_format.getWidth();
        this.height = pd.height;
        this.width = pd.width;
        table.setPageDimensions(pd.width, pd.height);
        num_pages = table.getNumPages();
    }

    /**
     * Generates a new table page image and posts it to the
     * <CODE>JCPrintPage</CODE> canvas for display.
     * @param page The index of the page to display
     */
    public void showPage(int page) {
        if (job == null) {
            return;
        }

        current_page = page;
        Image image = getPageImage(page);

        status.setText(LocaleBundle.string(LocaleBundle.PRINT_PAGE_FIRST)
                + (current_page + 1)
                + LocaleBundle.string(LocaleBundle.PRINT_PAGE_SECOND)
                + num_pages);
    }

    /**
     *
     * @param page
     * @return
     */
    private Image getPageImage(int page) {
        Image image = createImage(width, height);
        Graphics gc = image.getGraphics();
        table.printPage(gc, page);
        page_image.setImage(image);
        gc.dispose();
        return image;
    }

    /**
     * <CODE>ActionListener</CODE> method.
     * @param e The event generated by the action.
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() instanceof JButton) {
            JButton button = (JButton) e.getSource();
            if (button.equals(first_button)) {
                showPage(0);
            } else if (button.equals(prev_button)) {
                if (current_page > 0) {
                    showPage(current_page - 1);
                }
            } else if (button.equals(next_button)) {
                if (current_page + 1 < num_pages) {
                    showPage(current_page + 1);
                }
            } else if (button.equals(last_button)) {
                showPage(num_pages - 1);
            } else if (button.equals(format_button)) {
                page_format = job.pageDialog(page_format);
                setupPrintTable();

                // Resize the page_image to reflect the new page format size
                page_image.preferredDimension = new Dimension((int) (width * 1.05),
                        (int) (height * 1.05));
                page_image.setSize(new Dimension((int) (width * 1.05),
                        (int) (height * 1.05)));

                // Move to the first page since the current page may actually
                // not exist any more depending on format choices.
                showPage(0);

                pane.revalidate();
            } else if (button.equals(print_button)) {
                if (job != null) {
                    table.setPrintPage(current_page);
                    job.setPrintable(table, page_format);
                    try {
                        setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
                        Thread.yield();
                        job.print();
                        setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                    } catch (PrinterException pe) {
                        //System.out.println(pe);
                    }

                }
            } else if (button.equals(printall_button)) {
                if (job != null) {

                    table.setPrintPage(JCPrintTable.ALL_PAGES);
                    job.setPrintable(table, page_format);

                    try {
                        setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
                        Thread.yield();
                        job.print();
                        setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                    } catch (PrinterException pe) {
                        //System.out.println(pe);
                    }

                }
            } else if (button.equals(close_button)) {
                setVisible(false);
                dispose();
            }
        }
    }

    /**
     * <CODE>WindowListener</CODE> methods.
     * @param e
     */
    @Override
    public void windowActivated(WindowEvent e) {
    }

    /**
     *
     * @param e
     */
    @Override
    public void windowClosed(WindowEvent e) {
    }

    /**
     *
     * @param e
     */
    @Override
    public void windowClosing(WindowEvent e) {
        setVisible(false);
        dispose();
    }

    /**
     *
     * @param e
     */
    @Override
    public void windowDeactivated(WindowEvent e) {
    }

    /**
     *
     * @param e
     */
    @Override
    public void windowDeiconified(WindowEvent e) {
    }

    /**
     *
     * @param e
     */
    @Override
    public void windowIconified(WindowEvent e) {
    }

    /**
     *
     * @param e
     */
    @Override
    public void windowOpened(WindowEvent e) {
    }

    /**
     *
     */
    protected static class PageImage extends JPanel {

        private static final long serialVersionUID = 1L;

        /**
         *
         */
        protected Image page;

        /**
         *
         */
        protected Dimension preferredDimension;

        /**
         * Constructs a Dimension and initializes it to the specified preferred
         * dimension.
         * @param d
         */
        PageImage(Dimension d) {
            preferredDimension = d;
        }

        /**
         * Sets the page image.
         * @param page
         */
        public void setImage(Image page) {
            this.page = page;
            repaint();
        }

        /**
         * Gets the preferred size of the page.
         * @return
         */
        @Override
        public Dimension getPreferredSize() {
            return (preferredDimension);
        }

        /**
         * Paints the table image centered on the screen.
         * @param gc
         */
        @Override
        public void paintComponent(Graphics gc) {
            Dimension d = this.getSize();

            try {
                Image dbl = createImage(d.width, d.height);
                Graphics paint_gc = dbl.getGraphics();

                paint_gc.setColor(Color.gray);
                paint_gc.fillRect(0, 0, d.width, d.height);

                if (page != null) {
                    Dimension di = new Dimension(page.getWidth(this),
                            page.getHeight(this));
                    Point p = new Point((d.width - di.width) / 2,
                            (d.height - di.height) / 2);
                    paint_gc.setColor(Color.black);
                    paint_gc.drawRect(p.x - 2, p.y - 2, di.width + 2,
                            di.height + 2);
                    paint_gc.setColor(Color.white);
                    paint_gc.fillRect(p.x - 1, p.y - 1, di.width + 1,
                            di.height + 1);

                    paint_gc.drawImage(page, p.x, p.y, this);
                    gc.drawImage(dbl, 0, 0, this);
                }
            } catch (Exception e) {
                logger.error("Error drawing print preview.", e);
            }
        }
    } // End PageImage

    /**
     *
     * @param graphics
     * @param pageFormat
     * @param pageIndex
     * @return
     * @throws PrinterException
     */
    @Override
    public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
        if (pageIndex >= table.getNumPages()) {
            return Printable.NO_SUCH_PAGE;
        }
        Image image = getPageImage(pageIndex);
        if (image == null) {
            return Printable.NO_SUCH_PAGE;
        }
        ((Graphics2D) graphics).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        graphics.drawImage(image, 0, 0, null);
        return Printable.PAGE_EXISTS;
    }

}
