package com.hero.ui.dialog;

import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.HeadlessException;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Hashtable;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

import com.hero.Hero;
import com.hero.HeroDesigner;
import com.hero.util.Constants;
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 CombatRecordDialog extends JDialog {
	class CharacterCheck extends JCheckBox {
		private static final long serialVersionUID = -6546866554165081474L;

		Hero hero;

		public CharacterCheck(Hero h) {
			super(h.getCharacterName().trim().length() > 0 ? h
					.getCharacterName() : "[unknown]");
			hero = h;
			setSelected(true);
			addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					for (int i = 0; i < characterChecks.size(); i++) {
						CharacterCheck check = characterChecks.get(i);
						if (check.isSelected()) {
							doneBtn.setEnabled(true);
							return;
						}
					}
					doneBtn.setEnabled(false);
				}
			});
		}

		public Hero getHero() {
			return hero;
		}
	}

	private class HeroContainer {
		public String name1;

		public int dex1;

		public int spd1;

		public int tot1;

		public HeroContainer(String name, int dex, int spd, int tot) {
			name1 = name;
			dex1 = dex;
			spd1 = spd;
			tot1 = tot;
		}
	}

	private static final long serialVersionUID = -8368091814848273922L;

	private JLabel selectCharactersLbl;

	private ArrayList<CharacterCheck> characterChecks;

	private JLabel sortCharactersByLbl;

	private JLabel sortCharactersByLbl2;

	private JComboBox sortOptionsCombo;

	private JComboBox sortOptionsCombo2;

	private JCheckBox ascendingCB;

	private JCheckBox ascendingCB2;

	private JButton doneBtn;

	private JButton cancelBtn;

	private boolean cancelButtonClicked;

	private ArrayList<Hero> availableHeroes;

	private Hashtable<Hero, HeroContainer> heroValues;

	public CombatRecordDialog(ArrayList<Hero> avail) throws HeadlessException {
		super(HeroDesigner.getAppFrame(), "Combat Record Character Selection",
				true);
		cancelButtonClicked = true;
		availableHeroes = avail;
		initWidgets();
		initListeners();
		layoutComponent();
	}

	public boolean cancelButtonClicked() {
		return cancelButtonClicked;
	}

	/**
	 * Returns the Vector of selected Characters to export, sorted according to
	 * the selections.
	 * 
	 * @return
	 */
	public ArrayList<Hero> getCharacters() {
		ArrayList<Hero> ret = new ArrayList<Hero>();
		Hero orig = HeroDesigner.getActiveHero();
		heroValues = new Hashtable<Hero, HeroContainer>();
		for (int i = 0; i < characterChecks.size(); i++) {
			CharacterCheck check = characterChecks.get(i);
			if (check.isSelected()) {
				ret.add(check.getHero());
				HeroDesigner.getInstance().setActiveHero(check.getHero());
				String name = check.getHero().getCharacterName();
				int dex = 0;
				if (check.getHero().getCharacteristic(Constants.DEX) != null) {
					dex = (int) Rounder.roundHalfUp(check.getHero()
							.getCharacteristic(Constants.DEX)
							.getSecondaryValue());
				}
				int spd = 0;
				if (check.getHero().getCharacteristic(Constants.SPD) != null) {
					spd = (int) Rounder.roundDown(check.getHero()
							.getCharacteristic(Constants.SPD)
							.getSecondaryValue());
				}
				int tot = 0;
				tot = check.getHero().getBasePoints()
						+ check.getHero().getDisadPoints()
						+ check.getHero().getExperience();
				if (HeroDesigner.getActiveTemplate().is6E()) {
					tot -= check.getHero().getDisadPoints();
				}
				HeroContainer heroCont = new HeroContainer(name, dex, spd, tot);
				heroValues.put(check.getHero(), heroCont);
			}
		}
		HeroDesigner.getInstance().setActiveHero(orig);
		Comparator comparator = new Comparator() {
			public int compare(Object o1, Object o2) {
				if ((o1 instanceof Hero) && (o2 instanceof Hero)) {
					Hero h1 = (Hero) o1;
					Hero h2 = (Hero) o2;
					HeroContainer con1 = heroValues.get(h1);
					HeroContainer con2 = heroValues.get(h2);
					String name1 = con1.name1;
					if ((name1 == null) || (name1.trim().length() == 0)) {
						name1 = "[unknown]";
					}
					String name2 = con2.name1;
					if ((name2 == null) || (name2.trim().length() == 0)) {
						name2 = "[unknown]";
					}
					int dex1 = con1.dex1;
					int dex2 = con2.dex1;
					int spd1 = con1.spd1;
					int spd2 = con2.spd1;
					int tot1 = con1.tot1;
					int tot2 = con2.tot1;
					if (sortOptionsCombo.getSelectedIndex() <= 0) {
						if (name1.compareTo(name2) == 0) {
							if (sortOptionsCombo2.getSelectedIndex() <= 0) {
								return name1.compareTo(name2);
							} else if (sortOptionsCombo2.getSelectedIndex() == 1) {
								if (ascendingCB2.isSelected()) {
									return dex1 - dex2;
								} else {
									return dex2 - dex1;
								}
							} else if (sortOptionsCombo2.getSelectedIndex() == 2) {
								if (ascendingCB2.isSelected()) {
									return spd1 - spd2;
								} else {
									return spd2 - spd1;
								}
							} else {
								if (ascendingCB2.isSelected()) {
									return tot1 - tot2;
								} else {
									return tot2 - tot1;
								}
							}
						} else if (ascendingCB.isSelected()) {
							return name1.compareTo(name2);
						} else {
							return name2.compareTo(name1);
						}
					} else if (sortOptionsCombo.getSelectedIndex() == 1) {
						if (dex1 == dex2) {
							if (sortOptionsCombo2.getSelectedIndex() <= 0) {
								if (ascendingCB2.isSelected()) {
									return name1.compareTo(name2);
								} else {
									return name2.compareTo(name1);
								}
							} else if (sortOptionsCombo2.getSelectedIndex() == 1) {
								if (ascendingCB2.isSelected()) {
									return dex1 - dex2;
								} else {
									return dex2 - dex1;
								}
							} else if (sortOptionsCombo2.getSelectedIndex() == 2) {
								if (ascendingCB2.isSelected()) {
									return spd1 - spd2;
								} else {
									return spd2 - spd1;
								}
							} else {
								if (ascendingCB2.isSelected()) {
									return tot1 - tot2;
								} else {
									return tot2 - tot1;
								}
							}
						} else if (ascendingCB.isSelected()) {
							return dex1 - dex2;
						} else {
							return dex2 - dex1;
						}
					} else if (sortOptionsCombo.getSelectedIndex() == 2) {
						if (spd1 == spd2) {
							if (sortOptionsCombo2.getSelectedIndex() <= 0) {
								if (ascendingCB2.isSelected()) {
									return name1.compareTo(name2);
								} else {
									return name2.compareTo(name1);
								}
							} else if (sortOptionsCombo2.getSelectedIndex() == 1) {
								if (ascendingCB2.isSelected()) {
									return dex1 - dex2;
								} else {
									return dex2 - dex1;
								}
							} else if (sortOptionsCombo2.getSelectedIndex() == 2) {
								if (ascendingCB2.isSelected()) {
									return spd1 - spd2;
								} else {
									return spd2 - spd1;
								}
							} else {
								if (ascendingCB2.isSelected()) {
									return tot1 - tot2;
								} else {
									return tot2 - tot1;
								}
							}
						} else if (ascendingCB.isSelected()) {
							return spd1 - spd2;
						} else {
							return spd2 - spd1;
						}
					} else {
						if (tot1 == tot2) {
							if (sortOptionsCombo2.getSelectedIndex() <= 0) {
								if (ascendingCB2.isSelected()) {
									return name1.compareTo(name2);
								} else {
									return name2.compareTo(name1);
								}
							} else if (sortOptionsCombo2.getSelectedIndex() == 1) {
								if (ascendingCB2.isSelected()) {
									return dex1 - dex2;
								} else {
									return dex2 - dex1;
								}
							} else if (sortOptionsCombo2.getSelectedIndex() == 2) {
								if (ascendingCB2.isSelected()) {
									return spd1 - spd2;
								} else {
									return spd2 - spd1;
								}
							} else {
								if (ascendingCB2.isSelected()) {
									return tot1 - tot2;
								} else {
									return tot2 - tot1;
								}
							}
						} else if (ascendingCB.isSelected()) {
							return tot1 - tot2;
						} else {
							return tot2 - tot1;
						}
					}
				} else {
					return o1.toString().compareTo(o2.toString());
				}
			}
		};
		Collections.sort(ret, comparator);
		return ret;
	}

	private void initListeners() {
		cancelBtn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				cancelButtonClicked = true;
				setVisible(false);
			}
		});
		doneBtn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				cancelButtonClicked = false;
				setVisible(false);
			}
		});
	}

	private void initWidgets() {
		selectCharactersLbl = new JLabel("Select Characters for Export:");
		characterChecks = new ArrayList<CharacterCheck>();
		for (int i = 0; i < availableHeroes.size(); i++) {
			Hero h = availableHeroes.get(i);
			CharacterCheck check = new CharacterCheck(h);
			characterChecks.add(check);
		}
		sortCharactersByLbl = new JLabel("Sort Characters By");
		sortCharactersByLbl2 = new JLabel("Then By");
		String[] ops = { "Name", "DEX", "SPD", "Character Points" };
		sortOptionsCombo = new JComboBox(ops);
		sortOptionsCombo2 = new JComboBox(ops);
		ascendingCB = new JCheckBox("Ascending");
		ascendingCB2 = new JCheckBox("Ascending");
		doneBtn = new JButton("Done");
		cancelBtn = new JButton("Cancel");
	}

	private void layoutComponent() {
		JPanel panel = new JPanel(new GridBagLayout());
		GridBagConstraints gbc = new GridBagConstraints();
		gbc.gridx = 0;
		gbc.gridy = 0;
		gbc.gridwidth = GridBagConstraints.REMAINDER;
		gbc.gridheight = 1;
		gbc.weightx = 1;
		gbc.weighty = 0;
		gbc.fill = GridBagConstraints.NONE;
		gbc.anchor = GridBagConstraints.WEST;
		gbc.insets = new Insets(5, 5, 5, 5);
		panel.add(selectCharactersLbl, gbc);
		gbc.gridy++;
		JPanel checks = new JPanel(new GridBagLayout());
		for (CharacterCheck check : characterChecks) {
			checks.add(check, gbc);
			gbc.gridy++;
		}
		gbc.weighty = 1;
		gbc.fill = GridBagConstraints.BOTH;
		panel.add(new JScrollPane(checks), gbc);
		gbc.gridy++;
		gbc.weighty = 0;
		gbc.gridwidth = 1;
		gbc.anchor = GridBagConstraints.EAST;
		gbc.fill = GridBagConstraints.NONE;
		gbc.weightx = 0;
		panel.add(sortCharactersByLbl, gbc);
		gbc.gridx = 1;
		gbc.anchor = GridBagConstraints.WEST;
		gbc.fill = GridBagConstraints.HORIZONTAL;
		gbc.weightx = 1;
		panel.add(sortOptionsCombo, gbc);
		gbc.weightx = 0;
		gbc.gridx = 2;
		gbc.fill = GridBagConstraints.NONE;
		panel.add(ascendingCB, gbc);
		gbc.gridy++;
		gbc.weighty = 0;
		gbc.gridwidth = 1;
		gbc.anchor = GridBagConstraints.EAST;
		gbc.weightx = 0;
		gbc.gridx = 0;
		panel.add(sortCharactersByLbl2, gbc);
		gbc.gridx = 1;
		gbc.anchor = GridBagConstraints.WEST;
		gbc.weightx = 1;
		gbc.fill = GridBagConstraints.HORIZONTAL;
		panel.add(sortOptionsCombo2, gbc);
		gbc.weightx = 0;
		gbc.gridx = 2;
		gbc.fill = GridBagConstraints.NONE;
		panel.add(ascendingCB2, gbc);
		JPanel buttons = new JPanel(new FlowLayout(FlowLayout.CENTER));
		buttons.add(doneBtn);
		buttons.add(cancelBtn);
		gbc.gridy++;
		gbc.gridx = 0;
		gbc.gridwidth = GridBagConstraints.REMAINDER;
		gbc.anchor = GridBagConstraints.CENTER;
		panel.add(buttons, gbc);
		setContentPane(panel);
	}
}