/* $Id: HistoryToolBar.java 350 2011-09-11 15:16:44Z ohura $ */
package smart_gs.swingui.toolbar;

import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Vector;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JToolBar;
import javax.swing.JToolTip;
import javax.swing.SwingUtilities;
import javax.swing.plaf.metal.MetalToolTipUI;

import smart_gs.GSConstants;
import smart_gs.logical.Spread;
import smart_gs.swingui.AbstractGSWindow;
import smart_gs.swingui.WorkspaceWindow;

@SuppressWarnings("serial")
public class HistoryToolBar extends JToolBar implements ActionListener {
	protected ArrayList<Spread> historyList = new ArrayList<Spread>();
	protected static ArrayList<Integer> historyCanvasScale = new ArrayList<Integer>();

	protected JButton prev;
	private String prevString = "Move to previous page in history.";
	protected JButton next;
	private String nextString = "Move to next page in history.";

	protected int historycounter = 0;

	private final int DEFAULT_WIDTH = 1200;
	private final int ZOOM_VALUE = 200;
	private AbstractGSWindow parent;

	public HistoryToolBar(AbstractGSWindow parent) {
		prev = new JButton(new ImageIcon(GSConstants.ICON_PATH + "prev_history.png")){
		      public JToolTip createToolTip() {
		          MultiLineToolTip tip = new MultiLineToolTip();
		          tip.setComponent(this);
		          return tip;
		        }
		      };
		prev.setEnabled(false);
		prev.addActionListener(this);
		prev.setActionCommand("prev");
		prev.setToolTipText(prevString);
		prev.setMnemonic(KeyEvent.VK_LEFT);
		this.add(prev);
		next = new JButton(new ImageIcon(GSConstants.ICON_PATH + "next_history.png")){
		      public JToolTip createToolTip() {
		          MultiLineToolTip tip = new MultiLineToolTip();
		          tip.setComponent(this);
		          return tip;
		        }
		      };
		next.setEnabled(false);
		next.addActionListener(this);
		next.setActionCommand("next");
		next.setToolTipText(nextString);
		next.setMnemonic(KeyEvent.VK_RIGHT);
		this.add(next);

		this.parent = parent;
	}

	public void actionPerformed(ActionEvent e) {
		if (e.getActionCommand().equals("prev")) {
			historycounter--;
			Spread spread = historyList.get(historycounter);
			int scale = historyCanvasScale.get(historycounter);

			WorkspaceWindow.getInstance().setSpread(spread, false);
			WorkspaceWindow.getInstance().setImageSearch(spread.toString());
			WorkspaceWindow.getInstance().getSpreadCanvas().imageLabel.setScale(scale);
			WorkspaceWindow.getInstance().getSpreadCanvas().imageLabel.showImage();
			if (historycounter < 1) {
				prev.setEnabled(false);
				prev.setToolTipText(null);
			} else {
				{
					StringBuffer tipsBuf = new StringBuffer();
					tipsBuf.append(prevString + "\n");
					for (int i =( historycounter - 1); i >= 0; i--) {
						Spread spreadTemp = historyList.get(i);
						tipsBuf.append(spreadTemp.getViewName() + "\n");
					}
					prev.setToolTipText(tipsBuf.toString());
				}
			}
			StringBuffer tipsBuf = new StringBuffer();
			tipsBuf.append(nextString + "\n");
			for (int i = (historycounter + 1); i < historyList.size(); i++) {
				Spread spreadTemp = historyList.get(i);
				tipsBuf.append(spreadTemp.getViewName() + "\n");
			}
			next.setEnabled(true);
			next.setToolTipText(tipsBuf.toString());
		} else if (e.getActionCommand().equals("next")) {
			historycounter++;
			Spread spread = historyList.get(historycounter);
			int scale = historyCanvasScale.get(historycounter);	

			WorkspaceWindow.getInstance().setSpread(spread, false);
			WorkspaceWindow.getInstance().setImageSearch(spread.toString());
			WorkspaceWindow.getInstance().getSpreadCanvas().imageLabel.setScale(scale);
			WorkspaceWindow.getInstance().getSpreadCanvas().imageLabel.showImage();			
			if (historyList.size() - 1 <= historycounter) {
				next.setEnabled(false);
				next.setToolTipText(null);
			} else {
				StringBuffer tipsBuf = new StringBuffer();
				tipsBuf.append(nextString + "\n");
				for (int i = (historycounter + 1); i < historyList.size(); i++) {
					Spread spreadTemp = historyList.get(i);
					tipsBuf.append(spreadTemp.getViewName() + "\n");
				}
				next.setToolTipText(tipsBuf.toString());
			}
			if (historycounter >= 1) {
				StringBuffer tipsBuf = new StringBuffer();
				tipsBuf.append(prevString + "\n");
				for (int i =( historycounter - 1); i >= 0; i--) {
					Spread spreadTemp = historyList.get(i);
					tipsBuf.append(spreadTemp.getViewName() + "\n");
				}
				prev.setEnabled(true);
				prev.setToolTipText(tipsBuf.toString());
			}
		}
	}

	public void addHistory(Spread spread, int scale) {
		if (historycounter != historyList.size() - 1) {
			for (int i = historycounter; i < historyList.size(); i++) {
				historyList.remove((historycounter + 1));
				historyCanvasScale.remove((historycounter + 1));
			}
		}
		historyList.add(spread);
		historyCanvasScale.add(scale);
		historycounter = historyList.size() - 1;
		if (historycounter >= 1) {
			StringBuffer tipsBuf = new StringBuffer();
			for (int i =( historycounter - 1); i >= 0; i--) {
				Spread spreadTemp = historyList.get(i);
				tipsBuf.append(spreadTemp.getViewName() + "\n");
			}
			prev.setEnabled(true);
			prev.setToolTipText(tipsBuf.toString());
		}
		next.setEnabled(false);
		next.setToolTipText(null);
	}

	public void zoomInHistoryCanvasScale() {
		int scale = historyCanvasScale.remove(historycounter);
		scale++;
		historyCanvasScale.add(historycounter, scale);
	}

	public void zoomOutHistoryCanvasScale() {
		int scale = historyCanvasScale.remove(historycounter);
		scale--;
		historyCanvasScale.add(historycounter, scale);
	}

	public void fullSizeHistoryCanvasScale() {
		this.setHistoryCanvasScale(0);
	}

	public void fitWidthHistoryCanvasScale() {
		int width = this.parent.getSpreadCanvas().getWidth();
		int scale = (width - DEFAULT_WIDTH) / ZOOM_VALUE - 1;
		this.setHistoryCanvasScale(scale);
	}

	public void fitHeightHistoryCanvasScale() {
		int height = this.parent.getSpreadCanvas().getHeight();
		double ratio = (double) this.parent.getSpreadCanvas().imageLabel.getImageWidth() 
				/ (double) this.parent.getSpreadCanvas().imageLabel.getImageHeight();
		int scale = (int) ((ratio * (double) height - DEFAULT_WIDTH) / ZOOM_VALUE - 1);
		this.setHistoryCanvasScale(scale);
	}

	public void setHistoryCanvasScale(int scale) {
		historyCanvasScale.remove(historycounter);
		historyCanvasScale.add(historycounter, scale);
	}

	class MultiLineToolTip extends JToolTip {
		public MultiLineToolTip() {
			setUI(new MultiLineToolTipUI());
		}
	}

	class MultiLineToolTipUI extends MetalToolTipUI {
		private String[] strs;

		private int maxWidth = 0;

		public void paint(Graphics g, JComponent c) {
			FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(
					g.getFont());
			Dimension size = c.getSize();
			g.setColor(c.getBackground());
			g.fillRect(0, 0, size.width, size.height);
			g.setColor(c.getForeground());
			if (strs != null) {
				for (int i = 0; i < strs.length; i++) {
					g.drawString(strs[i], 3, (metrics.getHeight()) * (i + 1));
				}
			}
		}

		public Dimension getPreferredSize(JComponent c) {
			FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(
					c.getFont());
			String tipText = ((JToolTip) c).getTipText();
			if (tipText == null) {
				tipText = "";
			}
			BufferedReader br = new BufferedReader(new StringReader(tipText));
			String line;
			int maxWidth = 0;
			Vector v = new Vector();
			try {
				while ((line = br.readLine()) != null) {
					int width = SwingUtilities
							.computeStringWidth(metrics, line);
					maxWidth = (maxWidth < width) ? width : maxWidth;
					v.addElement(line);
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
			int lines = v.size();
			if (lines < 1) {
				strs = null;
				lines = 1;
			} else {
				strs = new String[lines];
				int i = 0;
				for (Enumeration e = v.elements(); e.hasMoreElements(); i++) {
					strs[i] = (String) e.nextElement();
				}
			}
			int height = metrics.getHeight() * lines;
			this.maxWidth = maxWidth;
			return new Dimension(maxWidth + 6, height + 4);
		}
	}

}
