import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JToolBar;

import org.jpedal.PdfDecoder;

public class PdfViewer extends JFrame {

	int width = 0;

	int height = 0;

	/** the actual JPanel/decoder object */
	private PdfDecoder pdfDecoder;

	/** current page number (first page is 1) */
	private int currentPage = 1;

	/** minimum screen width to ensure menu buttons are visible */
	private int minimumScreenWidth = 680;

	/** scaling factors on the page */
	protected JComboBox scalingBox;

	private final int defaultSelection = 0;

	/** page scaling to use 1=100% */
	protected float scaling = 1;

	private final JLabel pageCounter1 = new JLabel("Page ");

	private JTextField pageCounter2 = new JTextField(4);

	private JLabel pageCounter3 = new JLabel("of");

	protected String[] scalingValues = { "25%", "50%", "100%", "150%", "200%" };

	/** scaling values as floats to save conversion */
	protected float[] scalingFloatValues = { .25f, .5f, 1.0f, 1.5f, 2.0f };

	/**
	 * construct a pdf viewer, passing in the full file name
	 */
	public PdfViewer(byte[] pdfStream) {

		pdfDecoder = new PdfDecoder();

		try {
			//this opens the PDF and reads its internal details
            byte[] bytes = PdfWaterMarker.addWatermark(pdfStream);
			pdfDecoder.openPdfArray(bytes);

			//these 2 lines opens page 1 at 100% scaling
			pdfDecoder.decodePage(currentPage);
			pdfDecoder.setPageParameters(1, 1);
			pdfDecoder.invalidate();

		} catch (Exception e) {
			e.printStackTrace();
		}

		//setup our GUI display
		initializeViewer();

		//set page number display
		pageCounter2.setText(currentPage + "");
		pageCounter3.setText("of " + pdfDecoder.getPageCount());
	}

	/**
	 * setup the viewer and its components
	 */
	private void initializeViewer() {
		Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
		width = screen.width / 2;
		height = screen.height / 2;
		if (width < minimumScreenWidth)
			width = minimumScreenWidth;
		setSize(width, height);

		Container cPane = getContentPane();
		cPane.setLayout(new BorderLayout());
		cPane.setSize(width, height);

		scalingBox = new JComboBox(scalingValues);
		scalingBox.setSelectedIndex(2);
		scalingBox.setBackground(Color.WHITE);
		JPanel pageChanger = menuPanel();

		JToolBar topBar = new JToolBar(JToolBar.HORIZONTAL);
		topBar.add(pageChanger);
		cPane.add(topBar, BorderLayout.NORTH);

		JScrollPane display = initPDFDisplay();
		cPane.add(display, BorderLayout.CENTER);
		cPane.setEnabled(true);
		pack();

		setLocationRelativeTo(null);//centre on screen
		setVisible(true);
		this.setEnabled(true);
	}

	/**
	 * returns the scrollpane with pdfDecoder set as the viewport
	 */
	private JScrollPane initPDFDisplay() {

		JScrollPane currentScroll = new JScrollPane();
		currentScroll
				.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		currentScroll
				.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);

		currentScroll.setViewportView(pdfDecoder);

		return currentScroll;
	}

	/**
	 * setup the page display and changer panel and return it
	 */
	private JPanel menuPanel() {

		JPanel currentBar1 = new JPanel();
		currentBar1.setLayout(new FlowLayout(FlowLayout.LEADING, 0, 0));

		/** zoom in */
		JLabel plus = new JLabel("Zoom ");
		currentBar1.add(plus);
		plus.setToolTipText("Zoom");
		currentBar1.add(scalingBox);
		scalingBox.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

				try {
					zoom();
				} catch (Exception e1) {
					System.err.println("zoom error");
					e1.printStackTrace();
				}

				pageCounter2.setText(currentPage + "");

			}
		});

		/** back to page 1 */
		JButton start = new JButton();
		start.setBorderPainted(false);
		/*
		 * URL startImage = ClassLoader
		 * .getSystemResource("com/ameripath/test/lis/reporting/viewer/firstpage.gif");
		 * start.setIcon(new ImageIcon(startImage));
		 */
		start.setText("|<<");
		start.setToolTipText("Page 1");
		currentBar1.add(start);
		start.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (currentPage != 1) {
					currentPage = 1;
					try {
						pdfDecoder.decodePage(currentPage);
						pdfDecoder.invalidate();
						repaint();
					} catch (Exception e1) {
						System.err.println("Page 1");
						e1.printStackTrace();
					}

					//set page number display
					pageCounter2.setText(currentPage + "");
				}
			}
		});

		/** back icon */
		JButton back = new JButton();
		back.setBorderPainted(false);
		/*
		 * URL backImage = ClassLoader
		 * .getSystemResource("com/ameripath/test/lis/reporting/viewer/prevpage.gif");
		 * back.setIcon(new ImageIcon(backImage));
		 */
		back.setText("<<");
		back.setToolTipText("Back");
		currentBar1.add(back);
		back.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (currentPage > 1) {
					currentPage -= 1;
					try {
						pdfDecoder.decodePage(currentPage);
						pdfDecoder.invalidate();
						repaint();
					} catch (Exception e1) {
						System.err.println("Back");
						e1.printStackTrace();
					}

					// set page number display
					pageCounter2.setText(currentPage + "");
				}
			}
		});

		pageCounter2.setEditable(true);
		pageCounter2.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent a) {

				String value = (String) pageCounter2.getText().trim();
				int newPage;

				//allow for bum values
				try {
					newPage = Integer.parseInt(value);

					if ((newPage > pdfDecoder.getPageCount()) | (newPage < 1)) {
						return;
					}

					currentPage = newPage;
					try {
						pdfDecoder.decodePage(currentPage);
						pdfDecoder.invalidate();
						repaint();
					} catch (Exception e) {
						System.err.println("Page Number Entered");
						e.printStackTrace();
					}

				} catch (Exception e) {
					JOptionPane.showMessageDialog(null, ">" + value
							+ "< is Not a valid Value.\nPlease enter a number between 1 and "
							+ pdfDecoder.getPageCount());
					return;
				}

			}

		});

		/** put page count in middle of forward and back */
		currentBar1.add(pageCounter1);
		currentBar1.add(new JPanel());//add gap
		currentBar1.add(pageCounter2);
		currentBar1.add(new JPanel());//add gap
		currentBar1.add(pageCounter3);

		/** forward icon */
		JButton forward = new JButton();
		forward.setBorderPainted(false);
		/*
		 * URL fowardImage = ClassLoader
		 * .getSystemResource("com/ameripath/test/lis/reporting/viewer/nextpage.gif");
		 * forward.setIcon(new ImageIcon(fowardImage));
		 */
		forward.setText(">>");
		forward.setToolTipText("Forward");
		currentBar1.add(forward);
		forward.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (currentPage < pdfDecoder.getPageCount()) {
					currentPage += 1;
					try {
						pdfDecoder.decodePage(currentPage);
						pdfDecoder.invalidate();
						repaint();
					} catch (Exception e1) {
						System.err.println("Forward");
						e1.printStackTrace();
					}

					// set page number display
					pageCounter2.setText(currentPage + "");
				}
			}
		});

		/** goto last page */
		JButton end = new JButton();
		end.setBorderPainted(false);
		/*
		 * URL endImage = ClassLoader
		 * .getSystemResource("com/ameripath/test/lis/reporting/viewer/lastpage.gif");
		 * end.setIcon(new ImageIcon(endImage));
		 */
		end.setText(">>|");
		end.setToolTipText("Last Page");
		currentBar1.add(end);
		end.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (currentPage < pdfDecoder.getPageCount()) {
					currentPage = pdfDecoder.getPageCount();
					try {
						pdfDecoder.decodePage(currentPage);
						pdfDecoder.invalidate();
						repaint();
					} catch (Exception e1) {
						System.err.println("Last Page");
						e1.printStackTrace();
					}

					// set page number display
					pageCounter2.setText(currentPage + "");
				}
			}
		});

		return currentBar1;
	}

	/** zoom into page */
	public void zoom() {

		if (pdfDecoder != null) {

			/** update value and GUI */
			float zoom = 1;
			//int index = scalingBox.getSelectedIndex();
			int idx = scalingBox.getSelectedIndex();
			zoom = scalingFloatValues[idx];
			pdfDecoder.setPageParameters(zoom, currentPage);
			pdfDecoder.invalidate();
			repaint();
			validate();

		}

	}

}