package com.hero.ui;

import java.awt.Container;
import java.beans.PropertyVetoException;
import java.util.Enumeration;
import java.util.Hashtable;

import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import com.hero.HeroDesigner;
import com.hero.util.Utility;

/**
 * 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 MainContentPanel extends JTabbedPane {
	private static final long serialVersionUID = -5478235386418277609L;

	public BackgroundPanel backgroundPanel;

	public BasicInfoPanel basicInfoPanel;

	public CharacteristicsPanel characteristicsPanel;

	public DisadsPanel disadsPanel;

	public EquipmentPanel equipmentPanel;

	public ManeuversPanel maneuversPanel;

	public PerksPanel perksPanel;

	public PowersPanel powersPanel;

	public SkillsPanel skillsPanel;

	public TalentsPanel talentsPanel;

	JTextArea notes1TA;

	JTextArea notes2TA;

	JTextArea notes3TA;

	JTextArea notes4TA;

	JTextArea notes5TA;

	JScrollPane backgroundScroll;

	JScrollPane basicInfoScroll;

	JScrollPane characteristicsScroll;

	JScrollPane disadsScroll;

	JScrollPane equipmentScroll;

	JScrollPane maneuversScroll;

	JScrollPane perksScroll;

	JScrollPane powersScroll;

	JScrollPane skillsScroll;

	JScrollPane talentsScroll;

	JScrollPane notes1Scroll;

	JScrollPane notes2Scroll;

	JScrollPane notes3Scroll;

	JScrollPane notes4Scroll;

	JScrollPane notes5Scroll;

	private long lastEdit;

	public Hashtable states = new Hashtable();

	public Hashtable<JScrollPane, String> components = new Hashtable<JScrollPane, String>();

	public Hashtable<JScrollPane, AbilityFrame> frames = new Hashtable<JScrollPane, AbilityFrame>();

	public MainContentPanel() {
		super(SwingConstants.TOP, JTabbedPane.SCROLL_TAB_LAYOUT);
		initWidgets();
		initListeners();
		setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT);
	}

	public void hideFrames() {
		Enumeration enumer = frames.keys();
		while (enumer.hasMoreElements()) {
			Object k = enumer.nextElement();
			AbilityFrame f = frames.get(k);
			f.setVisible(false);
			f.dispose();
			frames.remove(k);
		}
		Hashtable prefs = HeroDesigner.getInstance().getPrefs()
				.getTearOffPrefs();
		enumer = components.keys();
		while (enumer.hasMoreElements()) {
			Object key = enumer.nextElement();
			Object tit = components.get(key);
			if ((prefs.get(tit) != null) && (states.get(key) != null)) {
				Integer[] vals = (Integer[]) prefs.get(tit);
				int state = Integer.parseInt(states.get(key).toString());
				vals[4] = new Integer(state);
				prefs.put(tit, vals);
			}
		}
	}

	private void initListeners() {
		notes1TA.getDocument().addDocumentListener(new DocumentListener() {
			public void changedUpdate(DocumentEvent e) {
				HeroDesigner.getActiveHero().setNotes1(notes1TA.getText());
			}

			public void insertUpdate(DocumentEvent e) {
				HeroDesigner.getActiveHero().setNotes1(notes1TA.getText());
			}

			public void removeUpdate(DocumentEvent e) {
				HeroDesigner.getActiveHero().setNotes1(notes1TA.getText());
			}
		});
		notes2TA.getDocument().addDocumentListener(new DocumentListener() {
			public void changedUpdate(DocumentEvent e) {
				HeroDesigner.getActiveHero().setNotes2(notes2TA.getText());
			}

			public void insertUpdate(DocumentEvent e) {
				HeroDesigner.getActiveHero().setNotes2(notes2TA.getText());
			}

			public void removeUpdate(DocumentEvent e) {
				HeroDesigner.getActiveHero().setNotes2(notes2TA.getText());
			}
		});
		notes3TA.getDocument().addDocumentListener(new DocumentListener() {
			public void changedUpdate(DocumentEvent e) {
				HeroDesigner.getActiveHero().setNotes3(notes3TA.getText());
			}

			public void insertUpdate(DocumentEvent e) {
				HeroDesigner.getActiveHero().setNotes3(notes3TA.getText());
			}

			public void removeUpdate(DocumentEvent e) {
				HeroDesigner.getActiveHero().setNotes3(notes3TA.getText());
			}
		});
		notes4TA.getDocument().addDocumentListener(new DocumentListener() {
			public void changedUpdate(DocumentEvent e) {
				HeroDesigner.getActiveHero().setNotes4(notes4TA.getText());
			}

			public void insertUpdate(DocumentEvent e) {
				HeroDesigner.getActiveHero().setNotes4(notes4TA.getText());
			}

			public void removeUpdate(DocumentEvent e) {
				HeroDesigner.getActiveHero().setNotes4(notes4TA.getText());
			}
		});
		notes5TA.getDocument().addDocumentListener(new DocumentListener() {
			public void changedUpdate(DocumentEvent e) {
				HeroDesigner.getActiveHero().setNotes5(notes5TA.getText());
			}

			public void insertUpdate(DocumentEvent e) {
				HeroDesigner.getActiveHero().setNotes5(notes5TA.getText());
			}

			public void removeUpdate(DocumentEvent e) {
				HeroDesigner.getActiveHero().setNotes5(notes5TA.getText());
			}
		});
		addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				int index = getSelectedIndex();
				if ((index < 0) || (getTabCount() < 4)) {
					return;
				}
				if ((index >= 0) && (index <= 9)) {
					HeroDesigner.getActiveHero().setLastTabIndex(index);
				}
				tabChanged(MainContentPanel.this.getComponentAt(index));

			}
		});
	}

	private void initWidgets() {
		basicInfoPanel = new BasicInfoPanel();
		basicInfoScroll = new JScrollPane(basicInfoPanel);
		characteristicsPanel = new CharacteristicsPanel();
		characteristicsScroll = new JScrollPane(characteristicsPanel);
		backgroundPanel = new BackgroundPanel();
		backgroundScroll = new JScrollPane(backgroundPanel);
		skillsPanel = new SkillsPanel();
		skillsScroll = new JScrollPane(skillsPanel);
		maneuversPanel = new ManeuversPanel();
		maneuversScroll = new JScrollPane(maneuversPanel);
		perksPanel = new PerksPanel();
		perksScroll = new JScrollPane(perksPanel);
		talentsPanel = new TalentsPanel();
		talentsScroll = new JScrollPane(talentsPanel);
		powersPanel = new PowersPanel();
		powersScroll = new JScrollPane(powersPanel);
		equipmentPanel = new EquipmentPanel();
		equipmentScroll = new JScrollPane(equipmentPanel);
		disadsPanel = new DisadsPanel();
		disadsScroll = new JScrollPane(disadsPanel);
		notes1TA = new JTextArea();
		notes1TA.setLineWrap(true);
		notes1TA.setWrapStyleWord(true);
		notes1TA.setTabSize(3);
		notes1Scroll = new JScrollPane(notes1TA);
		notes2TA = new JTextArea();
		notes2TA.setLineWrap(true);
		notes2TA.setWrapStyleWord(true);
		notes2TA.setTabSize(3);
		notes2Scroll = new JScrollPane(notes2TA);
		notes3TA = new JTextArea();
		notes3TA.setLineWrap(true);
		notes3TA.setWrapStyleWord(true);
		notes3TA.setTabSize(3);
		notes3Scroll = new JScrollPane(notes3TA);
		notes4TA = new JTextArea();
		notes4TA.setLineWrap(true);
		notes4TA.setWrapStyleWord(true);
		notes4TA.setTabSize(3);
		notes4Scroll = new JScrollPane(notes4TA);
		notes5TA = new JTextArea();
		notes5TA.setLineWrap(true);
		notes5TA.setWrapStyleWord(true);
		notes5TA.setTabSize(3);
		notes5Scroll = new JScrollPane(notes5TA);
		addTab("Basic Info.", basicInfoScroll);
		addTab("Background", backgroundScroll);
		addTab("Characteristics", characteristicsScroll);
		addTab("Skills", skillsScroll);
		addTab("Perks", perksScroll);
		addTab("Talents", talentsScroll);
		addTab("Martial Arts", maneuversScroll);
		addTab("Powers", powersScroll);
		addTab((HeroDesigner.getActiveTemplate().is6E() ? "Complications"
				: "Disadvantages"), disadsScroll);
		addTab("Equipment", equipmentScroll);
		addTab(HeroDesigner.getActiveHero().getRules().getNotes1Label(),
				notes1Scroll);
		addTab(HeroDesigner.getActiveHero().getRules().getNotes2Label(),
				notes2Scroll);
		addTab(HeroDesigner.getActiveHero().getRules().getNotes3Label(),
				notes3Scroll);
		addTab(HeroDesigner.getActiveHero().getRules().getNotes4Label(),
				notes4Scroll);
		addTab(HeroDesigner.getActiveHero().getRules().getNotes5Label(),
				notes5Scroll);
		components.put(basicInfoScroll, "Basic Info.");
		components.put(backgroundScroll, "Background");
		components.put(characteristicsScroll, "Characteristics");
		components.put(skillsScroll, "Skills");
		components.put(perksScroll, "Perks");
		components.put(talentsScroll, "Talents");
		components.put(maneuversScroll, "Martial Arts");
		components.put(powersScroll, "Powers");
		components.put(disadsScroll, "Disadvantages");
		components.put(equipmentScroll, "Equipment");
		components.put(notes1Scroll, HeroDesigner.getActiveHero().getRules()
				.getNotes1Label());
		components.put(notes2Scroll, HeroDesigner.getActiveHero().getRules()
				.getNotes2Label());
		components.put(notes3Scroll, HeroDesigner.getActiveHero().getRules()
				.getNotes3Label());
		components.put(notes4Scroll, HeroDesigner.getActiveHero().getRules()
				.getNotes4Label());
		components.put(notes5Scroll, HeroDesigner.getActiveHero().getRules()
				.getNotes5Label());
		states.put(basicInfoScroll, "0");
		states.put(backgroundScroll, "0");
		states.put(characteristicsScroll, "0");
		states.put(skillsScroll, "0");
		states.put(perksScroll, "0");
		states.put(talentsScroll, "0");
		states.put(maneuversScroll, "0");
		states.put(powersScroll, "0");
		states.put(disadsScroll, "0");
		states.put(equipmentScroll, "0");
		states.put(notes1Scroll, "0");
		states.put(notes2Scroll, "0");
		states.put(notes3Scroll, "0");
		states.put(notes4Scroll, "0");
		states.put(notes5Scroll, "0");

	}

	/**
	 * Recalculates and redisplays all tabs.
	 */
	public void recalcAll() {
		if (!isShowing()) {
			return;
		}
		if (characteristicsPanel != null) {
			characteristicsPanel.updateTotal();
		}
		if (skillsPanel != null) {
			skillsPanel.updateTotal();
		}
		if (perksPanel != null) {
			perksPanel.updateTotal();
		}
		if (talentsPanel != null) {
			talentsPanel.updateTotal();
		}
		if (powersPanel != null) {
			powersPanel.updateTotal();
		}
		if (maneuversPanel != null) {
			maneuversPanel.updateTotal();
		}
		if (disadsPanel != null) {
			disadsPanel.updateTotal();
		}
		if (equipmentPanel != null) {
			equipmentPanel.updateTotal();
		}
		if (basicInfoPanel != null) {
			basicInfoPanel.updateTotal();
		}

		lastEdit = System.currentTimeMillis();
	}

	/**
	 * Resets all panels, hiding any that are not part of the current template.
	 */
	public void reset() {
		removeAll();
		backgroundPanel.reset();
		basicInfoPanel.reset();
		characteristicsPanel.reset();
		disadsPanel.reset();
		// disadsPanel.updatePrefabs();
		equipmentPanel.reset();
		// equipmentPanel.updatePrefabs();
		maneuversPanel.reset();
		// maneuversPanel.updatePrefabs();
		perksPanel.reset();
		// perksPanel.updatePrefabs();
		powersPanel.reset();
		// powersPanel.updatePrefabs();
		skillsPanel.reset();
		// skillsPanel.updatePrefabs();
		talentsPanel.reset();
		// talentsPanel.updatePrefabs();
		notes1TA.setText(HeroDesigner.getActiveHero().getNotes1());
		notes2TA.setText(HeroDesigner.getActiveHero().getNotes2());
		notes3TA.setText(HeroDesigner.getActiveHero().getNotes3());
		notes4TA.setText(HeroDesigner.getActiveHero().getNotes4());
		notes5TA.setText(HeroDesigner.getActiveHero().getNotes5());
		if (states.get(basicInfoScroll).equals("0")) {
			addTab("Basic Info.", basicInfoScroll);
			if (frames.get(basicInfoScroll) != null) {
				AbilityFrame frame = frames.get(basicInfoScroll);
				frame.setVisible(false);
				frame.dispose();
				frames.remove(basicInfoScroll);
			}
		} else {
			if (frames.get(basicInfoScroll) != null) {
				AbilityFrame frame = frames.get(basicInfoScroll);
				frame.setContentPane(basicInfoScroll);
				if (!frame.isShowing()) {
					frame.setVisible(true);
				} else {
					frame.validate();
				}
			} else {
				AbilityFrame frame = new AbilityFrame(components.get(
						basicInfoScroll).toString(), basicInfoScroll);
				frames.put(basicInfoScroll, frame);
				frame.pack();
				frame.setVisible(true);
			}
		}
		if (HeroDesigner.getActiveTemplate().isBackgroundAllowed()
				&& !HeroDesigner.getActiveHero().isPrefab()) {
			if (states.get(backgroundScroll).equals("0")) {
				addTab("Background", backgroundScroll);
				if (frames.get(backgroundScroll) != null) {
					AbilityFrame frame = frames.get(backgroundScroll);
					frame.setVisible(false);
					frame.dispose();
					frames.remove(backgroundScroll);
				}
			} else {
				if (frames.get(backgroundScroll) != null) {
					AbilityFrame frame = frames.get(backgroundScroll);
					frame.setContentPane(backgroundScroll);
					if (!frame.isShowing()) {
						frame.setVisible(true);
					} else {
						frame.validate();
					}
				} else {
					AbilityFrame frame = new AbilityFrame(components.get(
							backgroundScroll).toString(), backgroundScroll);
					frames.put(backgroundScroll, frame);
					frame.pack();
					frame.setVisible(true);
				}
			}
		} else {
			if (frames.get(backgroundScroll) != null) {
				AbilityFrame frame = frames.get(backgroundScroll);
				frame.setVisible(false);
				frame.dispose();
				frames.remove(backgroundScroll);
			}
		}
		if (!HeroDesigner.getActiveHero().isPrefab()) {
			if (states.get(characteristicsScroll).equals("0")) {
				addTab("Characteristics", characteristicsScroll);
				if (frames.get(characteristicsScroll) != null) {
					AbilityFrame frame = frames.get(characteristicsScroll);
					frame.setVisible(false);
					frame.dispose();
					frames.remove(characteristicsScroll);
				}
			} else {
				if (frames.get(characteristicsScroll) != null) {
					AbilityFrame frame = frames.get(characteristicsScroll);
					frame.setContentPane(characteristicsScroll);
					if (!frame.isShowing()) {
						frame.setVisible(true);
					} else {
						frame.validate();
					}
				} else {
					AbilityFrame frame = new AbilityFrame(components.get(
							characteristicsScroll).toString(),
							characteristicsScroll);
					frames.put(characteristicsScroll, frame);
					frame.pack();
					frame.setVisible(true);
				}
			}
		} else {
			if (frames.get(characteristicsScroll) != null) {
				AbilityFrame frame = frames.get(characteristicsScroll);
				frame.setVisible(false);
				frame.dispose();
				frames.remove(characteristicsScroll);
			}
		}
		if (states.get(skillsScroll).equals("0")) {
			addTab("Skills", skillsScroll);
			if (frames.get(skillsScroll) != null) {
				AbilityFrame frame = frames.get(skillsScroll);
				frame.setVisible(false);
				frame.dispose();
				frames.remove(skillsScroll);
			}
		} else {
			if (frames.get(skillsScroll) != null) {
				AbilityFrame frame = frames.get(skillsScroll);
				frame.setContentPane(skillsScroll);
				if (!frame.isShowing()) {
					frame.setVisible(true);
				} else {
					frame.validate();
				}
			} else {
				AbilityFrame frame = new AbilityFrame(components.get(
						skillsScroll).toString(), skillsScroll);
				frames.put(skillsScroll, frame);
				frame.pack();
				frame.setVisible(true);
			}
		}
		if (states.get(perksScroll).equals("0")) {
			addTab("Perks", perksScroll);
			if (frames.get(perksScroll) != null) {
				AbilityFrame frame = frames.get(perksScroll);
				frame.setVisible(false);
				frame.dispose();
				frames.remove(perksScroll);
			}
		} else {
			if (frames.get(perksScroll) != null) {
				AbilityFrame frame = frames.get(perksScroll);
				frame.setContentPane(perksScroll);
				if (!frame.isShowing()) {
					frame.setVisible(true);
				} else {
					frame.validate();
				}
			} else {
				AbilityFrame frame = new AbilityFrame(components.get(
						perksScroll).toString(), perksScroll);
				frames.put(perksScroll, frame);
				frame.pack();
				frame.setVisible(true);
			}
		}
		if (states.get(talentsScroll).equals("0")) {
			addTab("Talents", talentsScroll);
			if (frames.get(talentsScroll) != null) {
				AbilityFrame frame = frames.get(talentsScroll);
				frame.setVisible(false);
				frame.dispose();
				frames.remove(talentsScroll);
			}
		} else {
			if (frames.get(talentsScroll) != null) {
				AbilityFrame frame = frames.get(talentsScroll);
				frame.setContentPane(talentsScroll);
				if (!frame.isShowing()) {
					frame.setVisible(true);
				} else {
					frame.validate();
				}
			} else {
				AbilityFrame frame = new AbilityFrame(components.get(
						talentsScroll).toString(), talentsScroll);
				frames.put(talentsScroll, frame);
				frame.pack();
				frame.setVisible(true);
			}
		}
		if (states.get(maneuversScroll).equals("0")) {
			addTab("Martial Arts", maneuversScroll);
			if (frames.get(maneuversScroll) != null) {
				AbilityFrame frame = frames.get(maneuversScroll);
				frame.setVisible(false);
				frame.dispose();
				frames.remove(maneuversScroll);
			}
		} else {
			if (frames.get(maneuversScroll) != null) {
				AbilityFrame frame = frames.get(maneuversScroll);
				frame.setContentPane(maneuversScroll);
				if (!frame.isShowing()) {
					frame.setVisible(true);
				} else {
					frame.validate();
				}
			} else {
				AbilityFrame frame = new AbilityFrame(components.get(
						maneuversScroll).toString(), maneuversScroll);
				frames.put(maneuversScroll, frame);
				frame.pack();
				frame.setVisible(true);
			}
		}
		if (states.get(powersScroll).equals("0")) {
			addTab("Powers", powersScroll);
			if (frames.get(powersScroll) != null) {
				AbilityFrame frame = frames.get(powersScroll);
				frame.setVisible(false);
				frame.dispose();
				frames.remove(powersScroll);
			}
		} else {
			if (frames.get(powersScroll) != null) {
				AbilityFrame frame = frames.get(powersScroll);
				frame.setContentPane(powersScroll);
				if (!frame.isShowing()) {
					frame.setVisible(true);
				} else {
					frame.validate();
				}
			} else {
				AbilityFrame frame = new AbilityFrame(components.get(
						powersScroll).toString(), powersScroll);
				frames.put(powersScroll, frame);
				frame.pack();
				frame.setVisible(true);
			}
		}
		if (states.get(disadsScroll).equals("0")) {
			addTab((HeroDesigner.getActiveTemplate().is6E() ? "Complications"
					: "Disadvantages"), disadsScroll);
			if (frames.get(disadsScroll) != null) {
				AbilityFrame frame = frames.get(disadsScroll);
				frame.setVisible(false);
				frame.dispose();
				frames.remove(disadsScroll);
			}
		} else {
			if (frames.get(disadsScroll) != null) {
				AbilityFrame frame = frames.get(disadsScroll);
				frame.setContentPane(disadsScroll);
				if (!frame.isShowing()) {
					frame.setVisible(true);
				} else {
					frame.validate();
				}
			} else {
				AbilityFrame frame = new AbilityFrame((HeroDesigner
						.getActiveTemplate().is6E() ? "Complications"
						: "Disadvantages"), disadsScroll);
				frames.put(disadsScroll, frame);
				frame.pack();
				frame.setVisible(true);
			}
		}

		if (HeroDesigner.getActiveHero().getRules().isEquipmentAllowed()
				|| HeroDesigner.getActiveHero().isPrefab()) {
			if (states.get(equipmentScroll).equals("0")) {
				addTab("Equipment", equipmentScroll);
				if (frames.get(equipmentScroll) != null) {
					AbilityFrame frame = frames.get(equipmentScroll);
					frame.setVisible(false);
					frame.dispose();
					frames.remove(equipmentScroll);
				}
			} else {
				if (frames.get(equipmentScroll) != null) {
					AbilityFrame frame = frames.get(equipmentScroll);
					frame.setContentPane(equipmentScroll);
					if (!frame.isShowing()) {
						frame.setVisible(true);
					} else {
						frame.validate();
					}
				} else {
					AbilityFrame frame = new AbilityFrame(components.get(
							equipmentScroll).toString(), equipmentScroll);
					frames.put(equipmentScroll, frame);
					frame.pack();
					frame.setVisible(true);
				}
			}
		} else {
			if (frames.get(equipmentScroll) != null) {
				AbilityFrame frame = frames.get(equipmentScroll);
				frame.setVisible(false);
				frame.dispose();
				frames.remove(equipmentScroll);
			}
		}

		if (HeroDesigner.getActiveHero().getRules().useNotes1()
				&& !HeroDesigner.getActiveHero().isPrefab()) {
			if (states.get(notes1Scroll).equals("0")) {
				addTab(
						HeroDesigner.getActiveHero().getRules()
								.getNotes1Label(), notes1Scroll);
				if (frames.get(notes1Scroll) != null) {
					AbilityFrame frame = frames.get(notes1Scroll);
					frame.setVisible(false);
					frame.dispose();
					frames.remove(notes1Scroll);
				}
			} else {
				if (frames.get(notes1Scroll) != null) {
					AbilityFrame frame = frames.get(notes1Scroll);
					frame.setContentPane(notes1Scroll);
					frame.setTitle(HeroDesigner.getActiveHero().getRules()
							.getNotes1Label());
					if (!frame.isShowing()) {
						frame.setVisible(true);
					} else {
						frame.validate();
					}
				} else {
					AbilityFrame frame = new AbilityFrame(HeroDesigner
							.getActiveHero().getRules().getNotes1Label(),
							notes1Scroll);
					frames.put(notes1Scroll, frame);
					frame.pack();
					frame.setVisible(true);
				}
			}
		} else {
			if (frames.get(notes1Scroll) != null) {
				AbilityFrame frame = frames.get(notes1Scroll);
				frame.setVisible(false);
				frame.dispose();
				frames.remove(notes1Scroll);
			}
		}
		if (HeroDesigner.getActiveHero().getRules().useNotes2()
				&& !HeroDesigner.getActiveHero().isPrefab()) {
			if (states.get(notes2Scroll).equals("0")) {
				addTab(
						HeroDesigner.getActiveHero().getRules()
								.getNotes2Label(), notes2Scroll);
				if (frames.get(notes2Scroll) != null) {
					AbilityFrame frame = frames.get(notes2Scroll);
					frame.setVisible(false);
					frame.dispose();
					frames.remove(notes2Scroll);
				}
			} else {
				if (frames.get(notes2Scroll) != null) {
					AbilityFrame frame = frames.get(notes2Scroll);
					frame.setContentPane(notes2Scroll);
					frame.setTitle(HeroDesigner.getActiveHero().getRules()
							.getNotes2Label());
					if (!frame.isShowing()) {
						frame.setVisible(true);
					} else {
						frame.validate();
					}
				} else {
					AbilityFrame frame = new AbilityFrame(HeroDesigner
							.getActiveHero().getRules().getNotes2Label(),
							notes2Scroll);
					frames.put(notes2Scroll, frame);
					frame.pack();
					frame.setVisible(true);
				}
			}
		} else {
			if (frames.get(notes2Scroll) != null) {
				AbilityFrame frame = frames.get(notes2Scroll);
				frame.setVisible(false);
				frame.dispose();
				frames.remove(notes2Scroll);
			}
		}
		if (HeroDesigner.getActiveHero().getRules().useNotes3()
				&& !HeroDesigner.getActiveHero().isPrefab()) {
			if (states.get(notes3Scroll).equals("0")) {
				addTab(
						HeroDesigner.getActiveHero().getRules()
								.getNotes3Label(), notes3Scroll);
				if (frames.get(notes3Scroll) != null) {
					AbilityFrame frame = frames.get(notes3Scroll);
					frame.setVisible(false);
					frame.dispose();
					frames.remove(notes3Scroll);
				}
			} else {
				if (frames.get(notes3Scroll) != null) {
					AbilityFrame frame = frames.get(notes3Scroll);
					frame.setContentPane(notes3Scroll);
					frame.setTitle(HeroDesigner.getActiveHero().getRules()
							.getNotes3Label());
					if (!frame.isShowing()) {
						frame.setVisible(true);
					} else {
						frame.validate();
					}
				} else {
					AbilityFrame frame = new AbilityFrame(HeroDesigner
							.getActiveHero().getRules().getNotes3Label(),
							notes3Scroll);
					frames.put(notes3Scroll, frame);
					frame.pack();
					frame.setVisible(true);
				}
			}
		} else {
			if (frames.get(notes3Scroll) != null) {
				AbilityFrame frame = frames.get(notes3Scroll);
				frame.setVisible(false);
				frame.dispose();
				frames.remove(notes3Scroll);
			}
		}
		if (HeroDesigner.getActiveHero().getRules().useNotes4()
				&& !HeroDesigner.getActiveHero().isPrefab()) {
			if (states.get(notes4Scroll).equals("0")) {
				addTab(
						HeroDesigner.getActiveHero().getRules()
								.getNotes4Label(), notes4Scroll);
				if (frames.get(notes4Scroll) != null) {
					AbilityFrame frame = frames.get(notes4Scroll);
					frame.setVisible(false);
					frame.dispose();
					frames.remove(notes4Scroll);
				}
			} else {
				if (frames.get(notes4Scroll) != null) {
					AbilityFrame frame = frames.get(notes4Scroll);
					frame.setContentPane(notes4Scroll);
					frame.setTitle(HeroDesigner.getActiveHero().getRules()
							.getNotes4Label());
					if (!frame.isShowing()) {
						frame.setVisible(true);
					} else {
						frame.validate();
					}
				} else {
					AbilityFrame frame = new AbilityFrame(HeroDesigner
							.getActiveHero().getRules().getNotes4Label(),
							notes4Scroll);
					frames.put(notes4Scroll, frame);
					frame.pack();
					frame.setVisible(true);
				}
			}
		} else {
			if (frames.get(notes4Scroll) != null) {
				AbilityFrame frame = frames.get(notes4Scroll);
				frame.setVisible(false);
				frame.dispose();
				frames.remove(notes4Scroll);
			}
		}

		if (HeroDesigner.getActiveHero().getRules().useNotes5()
				&& !HeroDesigner.getActiveHero().isPrefab()) {
			if (states.get(notes5Scroll).equals("0")) {
				addTab(
						HeroDesigner.getActiveHero().getRules()
								.getNotes5Label(), notes5Scroll);
				if (frames.get(notes5Scroll) != null) {
					AbilityFrame frame = frames.get(notes5Scroll);
					frame.setVisible(false);
					frame.dispose();
					frames.remove(notes5Scroll);
				}
			} else {
				if (frames.get(notes5Scroll) != null) {
					AbilityFrame frame = frames.get(notes5Scroll);
					frame.setContentPane(notes5Scroll);
					frame.setTitle(HeroDesigner.getActiveHero().getRules()
							.getNotes5Label());
					if (!frame.isShowing()) {
						frame.setVisible(true);
					} else {
						frame.validate();
					}
				} else {
					AbilityFrame frame = new AbilityFrame(HeroDesigner
							.getActiveHero().getRules().getNotes5Label(),
							notes5Scroll);
					frames.put(notes5Scroll, frame);
					frame.pack();
					frame.setVisible(true);
				}
			}
		} else {
			if (frames.get(notes5Scroll) != null) {
				AbilityFrame frame = frames.get(notes5Scroll);
				frame.setVisible(false);
				frame.dispose();
				frames.remove(notes5Scroll);
			}
		}

		for (int i = 0; (i < getTabCount()) && (i < 9); i++) {
			setMnemonicAt(i, String.valueOf((i + 1)).charAt(0));
		}
		if (getTabCount() > 9) {
			setMnemonicAt(9, '0');
		}
		components.put(notes1Scroll, HeroDesigner.getActiveHero().getRules()
				.getNotes1Label());
		components.put(notes2Scroll, HeroDesigner.getActiveHero().getRules()
				.getNotes2Label());
		components.put(notes3Scroll, HeroDesigner.getActiveHero().getRules()
				.getNotes3Label());
		components.put(notes4Scroll, HeroDesigner.getActiveHero().getRules()
				.getNotes4Label());
		components.put(notes5Scroll, HeroDesigner.getActiveHero().getRules()
				.getNotes5Label());

		int index = HeroDesigner.getActiveHero().getLastTabIndex();
		if ((index >= 0) && (index < getTabCount())) {
			setSelectedIndex(index);
		} else {
			setSelectedIndex(0);
		}

		setTabPlacement(HeroDesigner.getInstance().getPrefs().getTabPosition());

		updatePrefabs();

		lastEdit = System.currentTimeMillis();
		HeroDesigner.getInstance().fireDisplayReset();
	}

	public void setState(Object screen, boolean detached) {
		if (detached) {
			states.put(screen, "1");
		} else {
			states.put(screen, "0");
		}
		reset();
	}

	public void setStates() {
		Hashtable prefs = HeroDesigner.getInstance().getPrefs()
				.getTearOffPrefs();
		Enumeration enumer = components.keys();
		while (enumer.hasMoreElements()) {
			Object key = enumer.nextElement();
			Object tit = components.get(key);
			if ((prefs.get(tit) != null) && (states.get(key) != null)) {
				Integer[] vals = (Integer[]) prefs.get(tit);
				states.put(key, vals[4].toString());
			}
		}
	}

	public void tabChanged(Object tab) {
		try {
			if (tab.equals(skillsScroll)) {
				skillsPanel.getSelectionList().setSelected(true);
			} else if (tab.equals(perksScroll)) {
				perksPanel.getSelectionList().setSelected(true);
			} else if (tab.equals(talentsScroll)) {
				talentsPanel.getSelectionList().setSelected(true);
			} else if (tab.equals(maneuversScroll)) {
				maneuversPanel.getSelectionList().setSelected(true);
			} else if (tab.equals(powersScroll)) {
				powersPanel.getSelectionList().setSelected(true);
			} else if (tab.equals(disadsScroll)) {
				disadsPanel.getSelectionList().setSelected(true);
			} else if (tab.equals(equipmentScroll)) {
				equipmentPanel.getSelectionList().setSelected(true);
			}
		} catch (PropertyVetoException e) {
			e.printStackTrace();
		}
		if ((HeroDesigner.lastEdit > 0)
				&& ((lastEdit <= 0) || (lastEdit < HeroDesigner.lastEdit))) {
			if (tab.equals(basicInfoScroll)) {
				basicInfoPanel.updateTotal();
			} else if (tab.equals(characteristicsScroll)) {
				characteristicsPanel.updateTotal();
			} else if (tab.equals(skillsScroll)) {
				skillsPanel.updateTotal();
			} else if (tab.equals(perksScroll)) {
				perksPanel.updateTotal();
			} else if (tab.equals(talentsScroll)) {
				talentsPanel.updateTotal();
			} else if (tab.equals(maneuversScroll)) {
				maneuversPanel.updateTotal();
			} else if (tab.equals(powersScroll)) {
				powersPanel.updateTotal();
			} else if (tab.equals(disadsScroll)) {
				disadsPanel.updateTotal();
			} else if (tab.equals(equipmentScroll)) {
				equipmentPanel.updateTotal();
			}
			Thread runner = new Thread(new Runnable() {
				public void run() {
					try {
						Thread.sleep(1000);
					} catch (InterruptedException ex) {
					}
					SwingUtilities.invokeLater(new Runnable() {
						public void run() {
							if (HeroDesigner.getActiveHero() != null) {
								updateFrames(HeroDesigner.getAppFrame());
							}
						}
					});
					int i = getSelectedIndex();
					if ((i < 0) || (i >= getTabCount())) {
						i = 0;
					}
					String t = i < getTabCount() ? getTitleAt(i) : "";
					if (!t.equals("Basic Info.")) {
						SwingUtilities.invokeLater(new Runnable() {
							public void run() {
								if (HeroDesigner.getActiveHero() != null) {
									basicInfoPanel.updateTotal();
								}
							}
						});
					}
					if (!t.equals("Characteristics")) {
						SwingUtilities.invokeLater(new Runnable() {
							public void run() {
								if (HeroDesigner.getActiveHero() != null) {
									characteristicsPanel.updateTotal();
								}
							}
						});
					}
					if (!t.equals("Skills")) {
						SwingUtilities.invokeLater(new Runnable() {
							public void run() {
								if (HeroDesigner.getActiveHero() != null) {
									skillsPanel.updateTotal();
								}
							}
						});
					}
					if (!t.equals("Perks")) {
						SwingUtilities.invokeLater(new Runnable() {
							public void run() {
								if (HeroDesigner.getActiveHero() != null) {
									perksPanel.updateTotal();
								}
							}
						});
					}
					if (!t.equals("Talents")) {
						SwingUtilities.invokeLater(new Runnable() {
							public void run() {
								if (HeroDesigner.getActiveHero() != null) {
									talentsPanel.updateTotal();
								}
							}
						});
					}
					if (!t.equals("Martial Arts")) {
						SwingUtilities.invokeLater(new Runnable() {
							public void run() {
								if (HeroDesigner.getActiveHero() != null) {
									maneuversPanel.updateTotal();
								}
							}
						});
					}
					if (!t.equals("Powers")) {
						SwingUtilities.invokeLater(new Runnable() {
							public void run() {
								if (HeroDesigner.getActiveHero() != null) {
									powersPanel.updateTotal();
								}
							}
						});
					}
					if (!(t.equals("Disadvantages") || t
							.equals("Complications"))) {
						SwingUtilities.invokeLater(new Runnable() {
							public void run() {
								if (HeroDesigner.getActiveHero() != null) {
									disadsPanel.updateTotal();
								}
							}
						});
					}
					if (!t.equals("Equipment")) {
						SwingUtilities.invokeLater(new Runnable() {
							public void run() {
								if (HeroDesigner.getActiveHero() != null) {
									equipmentPanel.updateTotal();
								}
							}
						});
					}
				}
			});
			runner.start();
			lastEdit = System.currentTimeMillis();
			Utility.garbageCollect("Change to " + components.get(tab) + " tab");
			HeroDesigner.getInstance().fireTabChanged();
		}
	}

	public void tearOff() {
		if (getSelectedIndex() < 0) {
			return;
		}
		states.put(getComponentAt(getSelectedIndex()), "1");
		reset();
	}

	/**
	 * Updates the characteristics panel.
	 */
	public void updateCharacteristics() {
		if (characteristicsPanel != null) {
			characteristicsPanel.updateTotal();
		}
	}

	public void updateFrames(Container caller) {
		if (!isShowing()) {
			return;
		}
		if (HeroDesigner.getActiveHero().isLoading()) {
			return;
		}
		boolean callerIsFrame = false;
		Container parent = caller.getParent();
		while (parent != null) {
			if (parent instanceof AbilityFrame) {
				callerIsFrame = true;
				break;
			}
			parent = parent.getParent();
		}
		if (callerIsFrame && (getSelectedIndex() >= 0)
				&& !caller.equals(getComponentAt(getSelectedIndex()))) {
			// update selected index
			Object o = this.getComponentAt(getSelectedIndex());
			if ((characteristicsPanel != null)
					&& o.equals(characteristicsScroll)) {
				characteristicsPanel.updateTotal();
			}
			if ((skillsPanel != null) && o.equals(skillsScroll)) {
				skillsPanel.updateTotal();
			}
			if ((perksPanel != null) && o.equals(perksScroll)) {
				perksPanel.updateTotal();
			}
			if ((talentsPanel != null) && o.equals(talentsScroll)) {
				talentsPanel.updateTotal();
			}
			if ((powersPanel != null) & o.equals(powersScroll)) {
				powersPanel.updateTotal();
			}
			if ((maneuversPanel != null) && o.equals(maneuversScroll)) {
				maneuversPanel.updateTotal();
			}
			if ((disadsPanel != null) && o.equals(disadsScroll)) {
				disadsPanel.updateTotal();
			}
			if ((equipmentPanel != null) && o.equals(equipmentScroll)) {
				equipmentPanel.updateTotal();
			}
			if ((basicInfoPanel != null) & o.equals(basicInfoScroll)) {
				basicInfoPanel.updateTotal();
			}
		}
		Enumeration enumer = frames.keys();
		while (enumer.hasMoreElements()) {
			Object o = enumer.nextElement();
			if (o.equals(caller)) {
				continue;
			}
			AbilityFrame f = frames.get(o);
			if (!f.isShowing()) {
				continue;
			}
			if ((characteristicsPanel != null)
					&& o.equals(characteristicsScroll)) {
				characteristicsPanel.updateTotal();
			}
			if ((skillsPanel != null) && o.equals(skillsScroll)) {
				skillsPanel.updateTotal();
			}
			if ((perksPanel != null) && o.equals(perksScroll)) {
				perksPanel.updateTotal();
			}
			if ((talentsPanel != null) && o.equals(talentsScroll)) {
				talentsPanel.updateTotal();
			}
			if ((powersPanel != null) & o.equals(powersScroll)) {
				powersPanel.updateTotal();
			}
			if ((maneuversPanel != null) && o.equals(maneuversScroll)) {
				maneuversPanel.updateTotal();
			}
			if ((disadsPanel != null) && o.equals(disadsScroll)) {
				disadsPanel.updateTotal();
			}
			if ((equipmentPanel != null) && o.equals(equipmentScroll)) {
				equipmentPanel.updateTotal();
			}
			if ((basicInfoPanel != null) & o.equals(basicInfoScroll)) {
				basicInfoPanel.updateTotal();
			}
		}
	}

	/**
	 * Updates the prefabs displayed in each panel.
	 */
	public void updatePrefabs() {
		if (skillsPanel != null) {
			skillsPanel.updatePrefabs();
		}
		if (perksPanel != null) {
			perksPanel.updatePrefabs();
		}
		if (talentsPanel != null) {
			talentsPanel.updatePrefabs();
		}
		if (powersPanel != null) {
			powersPanel.updatePrefabs();
		}
		if (maneuversPanel != null) {
			maneuversPanel.updatePrefabs();
		}
		if (disadsPanel != null) {
			disadsPanel.updatePrefabs();
		}
		if (equipmentPanel != null) {
			equipmentPanel.updatePrefabs();
		}
	}

	/**
	 * Updates the selected tab.
	 */
	public void updateTabs() {
		if (!isShowing()) {
			return;
		}
		int index = getSelectedIndex();
		String title = getTitleAt(index);
		if (title.equals("Basic Info.")
				&& (HeroDesigner.getActiveHero() != null)) {
			basicInfoPanel.updateTotal();
		} else if (title.equals("Characteristics")
				&& (HeroDesigner.getActiveHero() != null)) {
			characteristicsPanel.updateTotal();
		} else if (title.equals("Skills")
				&& (HeroDesigner.getActiveHero() != null)) {
			skillsPanel.updateTotal();
		} else if (title.equals("Perks")
				&& (HeroDesigner.getActiveHero() != null)) {
			perksPanel.updateTotal();
		} else if (title.equals("Talents")
				&& (HeroDesigner.getActiveHero() != null)) {
			talentsPanel.updateTotal();
		} else if (title.equals("Martial Arts")
				&& (HeroDesigner.getActiveHero() != null)) {
			maneuversPanel.updateTotal();
		} else if (title.equals("Powers")
				&& (HeroDesigner.getActiveHero() != null)) {
			powersPanel.updateTotal();
		} else if ((title.equals("Disadvantages") || title
				.equals("Complications"))
				&& (HeroDesigner.getActiveHero() != null)) {
			disadsPanel.updateTotal();
		} else if (title.equals("Equipment")
				&& (HeroDesigner.getActiveHero() != null)) {
			equipmentPanel.updateTotal();
		}
	}

	/**
	 * Runs index checks on all purchase lists.
	 */
	public void verify() {
		disadsPanel.checkIndices();
		equipmentPanel.checkIndices();
		maneuversPanel.checkIndices();
		perksPanel.checkIndices();
		powersPanel.checkIndices();
		skillsPanel.checkIndices();
		talentsPanel.checkIndices();
	}
}