package com.hero.ui.widgets;

import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;

import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import com.hero.objects.Adder;
import com.hero.objects.GenericObject;
import com.hero.objects.List;
import com.hero.objects.modifiers.Modifier;
import com.hero.ui.dialog.GenericDialog;
import com.hero.util.Rounder;

/**
 * Copyright (c) 2000 - 2005, CompNet Design, Inc. All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, is prohibited unless the following conditions are met: 1.
 * Express written consent of CompNet Design, Inc. is obtained by the developer.
 * 2. Redistributions must retain this copyright notice. THIS SOFTWARE IS
 * PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * @author CompNet Design, Inc.
 * @version $Revision$
 */

public class CustomAdderPanel extends JPanel {
	private static final long serialVersionUID = 8344531362573596991L;

	Adder adder;

	GenericObject parent;

	GenericDialog main;

	JCheckBox checkbox;

	LevelTF pointsTF;

	FractionTF fracTF;

	JTextField aliasTF;

	ArrayList<ActionListener> listeners;

	ActionListener checkboxListener;

	boolean selectionLocked = false;

	public CustomAdderPanel(GenericObject object, Adder ad, GenericDialog dialog) {
		super();
		setLayout(new GridBagLayout());
		setOpaque(true);
		listeners = new ArrayList<ActionListener>();
		setBackground(Color.white);
		adder = ad;
		parent = object;
		main = dialog;
		aliasTF = new JTextField(adder.getAlias());
		aliasTF.setOpaque(false);
		aliasTF.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
		aliasTF.getDocument().addDocumentListener(new DocumentListener() {
			public void changedUpdate(DocumentEvent e) {
				adder.setAlias(aliasTF.getText());
			}

			public void insertUpdate(DocumentEvent e) {
				adder.setAlias(aliasTF.getText());
			}

			public void removeUpdate(DocumentEvent e) {
				adder.setAlias(aliasTF.getText());
			}
		});
		checkbox = new JCheckBox();
		checkbox.setOpaque(false);
		checkbox.setSelected(adder.isSelected());
		aliasTF.setFont(checkbox.getFont());
		checkboxListener = new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (checkbox.isSelected()) {
					addToParent();
				} else {
					removeFromParent();
				}
				revalidate();
				dispatch();
			}
		};
		checkbox.addActionListener(checkboxListener);
		if (parent instanceof Modifier) {
			fracTF = new FractionTF(adder.getBaseCost(), 10, -10);
			fracTF.getDocument().addDocumentListener(new DocumentListener() {
				public void changedUpdate(DocumentEvent e) {
					adder.setBaseCost(fracTF.getCurrent());
					dispatch();
				}

				public void insertUpdate(DocumentEvent e) {
					adder.setBaseCost(fracTF.getCurrent());
					dispatch();
				}

				public void removeUpdate(DocumentEvent e) {
					adder.setBaseCost(fracTF.getCurrent());
					dispatch();
				}
			});
		} else {
			pointsTF = new LevelTF((int) Rounder.roundHalfDown(adder
					.getBaseCost()), 999, -999);
			pointsTF.addPropertyChangeListener("Level",
					new PropertyChangeListener() {
						public void propertyChange(PropertyChangeEvent e) {
							adder.setBaseCost(pointsTF.getCurrent());
							dispatch();
						}
					});
		}

		GridBagConstraints gbc = new GridBagConstraints();
		gbc.gridx = 0;
		gbc.gridy = 0;
		gbc.weightx = 0;
		gbc.weighty = 1;
		gbc.gridwidth = 1;
		gbc.gridheight = 1;
		gbc.fill = GridBagConstraints.NONE;
		gbc.anchor = GridBagConstraints.NORTHWEST;
		gbc.insets = new Insets(0, 5, 0, 3);
		add(checkbox, gbc);
		gbc.gridx++;
		gbc.insets = new Insets(0, 0, 0, 3);
		gbc.fill = GridBagConstraints.HORIZONTAL;
		gbc.weightx = 1;
		add(aliasTF, gbc);
		gbc.gridx++;
		gbc.weightx = 0;
		gbc.fill = GridBagConstraints.NONE;
		gbc.anchor = GridBagConstraints.EAST;
		if (parent instanceof Modifier) {
			add(fracTF, gbc);
		} else {
			add(pointsTF, gbc);
		}
		addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				main.updateValues();
			}
		});
	}

	public void addActionListener(ActionListener listener) {
		listeners.add(listener);
	}

	private void addToParent() {
		adder = (Adder) adder.clone();
		adder.setSelected(checkbox.isSelected());
		if ((parent instanceof List) && adder.isPrivate()) {
			if (!((List) parent).getPrivateAdders().contains(adder)) {
				((List) parent).getPrivateAdders().add(adder);
			}
		} else {
			if (!parent.getAssignedAdders().contains(adder)) {
				parent.getAssignedAdders().add(adder);
			}
		}
	}

	public void dispatch() {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				for (int i = 0; i < listeners.size(); i++) {
					ActionListener listener = listeners.get(i);
					listener.actionPerformed(null);
				}
			}
		});
	}

	public Adder getAdder() {
		return adder;
	}

	public boolean isSelected() {
		return checkbox.isSelected();
	}

	private void removeFromParent() {
		adder.setSelected(checkbox.isSelected());
		if (!adder.isSelected()) {
			if (adder.getAssignedAdders().size() == 0) {
				if ((parent instanceof List) && adder.isPrivate()) {
					((List) parent).getPrivateAdders().remove(adder);
				} else {
					parent.getAssignedAdders().remove(adder);
				}
			}
		}
	}

	@Override
	public void setEnabled(boolean enabled) {
		checkbox.setEnabled(enabled);
		if (parent instanceof Modifier) {
			fracTF.setEnabled(enabled);
		} else {
			pointsTF.setEnabled(enabled);
		}
		aliasTF.setEnabled(enabled);
	}

	public void setSelected(boolean selected) {
		checkbox.setSelected(selected);
		adder.setSelected(selected);
		if (selected) {
			addToParent();
		} else {
			removeFromParent();
		}
	}

	public void setSelectionLocked(boolean val) {
		selectionLocked = val;
	}

	public void updateValues() {
		checkbox.removeActionListener(checkboxListener);
		checkbox.setSelected(parent.getAssignedAdders().contains(adder)
				&& adder.isSelected());
		checkbox.addActionListener(checkboxListener);
		if (parent instanceof Modifier) {
			fracTF.setCurrent(adder.getBaseCost());
		} else {
			pointsTF.setCurrent((int) Rounder
					.roundHalfDown(adder.getBaseCost()));
		}
	}
}