package org.concord.energy2d.util;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JComponent;
import javax.swing.border.LineBorder;
import javax.swing.plaf.basic.BasicBorders;

/**
 * @author Charles Xie
 * 
 */

public class BackgroundComboBox extends JComponent implements FocusListener, PropertyChangeListener {

	private SelectionPanel selectionPanel;
	private JButton popButton;
	private ColorMenu colorMenu;

	public BackgroundComboBox(Component parent, boolean filled, JColorChooser colorChooser, TextureChooser textureChooser) {
		this(parent, new ColorMenu(parent, "Background", filled, colorChooser, textureChooser));
	}

	public BackgroundComboBox(Component parent, JColorChooser colorChooser, TextureChooser textureChooser) {
		this(parent, new ColorMenu(parent, "Background", colorChooser, textureChooser));
	}

	private BackgroundComboBox(Component parent, final ColorMenu colorMenu) {

		setLayout(new BorderLayout());
		setBorder(new BasicBorders.ButtonBorder(Color.lightGray, Color.white, Color.black, Color.gray));

		colorMenu.addPropertyChangeListener(this);
		this.colorMenu = colorMenu;

		selectionPanel = new SelectionPanel();
		selectionPanel.setPreferredSize(new Dimension(80, 18));
		selectionPanel.addMouseListener(new MouseAdapter() {
			public void mousePressed(MouseEvent e) {
				if (selectionPanel.isEnabled()) {
					colorMenu.getPopupMenu().show(selectionPanel, 0, selectionPanel.getHeight());
				}
			}
		});
		add(selectionPanel, BorderLayout.CENTER);

		popButton = new JButton(new DownTriangleIcon());
		popButton.setBorder(new BasicBorders.ButtonBorder(Color.gray, Color.black, Color.white, Color.lightGray));
		popButton.setPreferredSize(new Dimension(20, 18));
		popButton.setFocusPainted(false);
		popButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				colorMenu.getPopupMenu().show(selectionPanel, 0, selectionPanel.getHeight());
			}
		});

		add(popButton, BorderLayout.EAST);

		selectionPanel.addFocusListener(this);
		popButton.addFocusListener(this);

	}

	public void setParent(Component parent) {
		colorMenu.setParent(parent);
	}

	public ColorMenu getColorMenu() {
		return colorMenu;
	}

	public void setFillPattern(FillPattern fp) {
		selectionPanel.setFillPattern(fp);
	}

	public FillPattern getFillPattern() {
		return selectionPanel.getFillPattern();
	}

	public void setEnabled(boolean b) {
		selectionPanel.setEnabled(b);
		popButton.setEnabled(b);
	}

	public void focusLost(FocusEvent e) {
		selectionPanel.setBorder(new LineBorder(selectionPanel.unselectedColor, 2));
		selectionPanel.repaint();
	}

	public void focusGained(FocusEvent e) {
		selectionPanel.setBorder(new LineBorder(selectionPanel.selectedColor, 2));
		selectionPanel.repaint();
	}

	public void propertyChange(PropertyChangeEvent e) {

		String name = e.getPropertyName();

		if (name.equals(ColorMenu.FILLING)) {
			Object obj = e.getNewValue();
			if (obj instanceof ColorFill) {
				selectionPanel.setFillPattern((ColorFill) obj);
			} else if (obj instanceof Texture) {
				selectionPanel.setFillPattern((Texture) obj);
			}
			selectionPanel.repaint();
		}

	}

	protected class SelectionPanel extends JComponent {

		private Color selectedColor = Color.black;
		private Color unselectedColor = Color.white;
		private FillPattern fillPattern;

		public SelectionPanel() {
			setBorder(new LineBorder(unselectedColor, 2));
		}

		public boolean getLockRatio() {
			return false;
		}

		public void setFillPattern(FillPattern fp) {
			fillPattern = fp;
		}

		public FillPattern getFillPattern() {
			return fillPattern;
		}

		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			if (fillPattern instanceof Texture) {
				Graphics2D g2 = (Graphics2D) g;
				g2.setPaint(((Texture) fillPattern).getPaint());
				g2.fillRect(0, 0, getWidth(), getHeight());
			} else if (fillPattern instanceof ColorFill) {
				g.setColor(((ColorFill) fillPattern).getColor());
				g.fillRect(0, 0, getWidth(), getHeight());
			}
		}

	}

	private class DownTriangleIcon implements Icon {

		public void paintIcon(Component c, Graphics g, int x, int y) {
			int w = getIconWidth();
			int h = getIconHeight();
			Polygon triangle = new Polygon();
			triangle.addPoint(x, y);
			triangle.addPoint(x + w, y);
			triangle.addPoint(x + w / 2, y + h);
			g.setColor(popButton.isEnabled() ? SystemColor.textText : SystemColor.textInactiveText);
			g.fillPolygon(triangle);
		}

		public int getIconWidth() {
			return 6;
		}

		public int getIconHeight() {
			return 4;
		}

	}

}