package com.hero.objects.powers;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;

import org.jdom.Element;

import com.hero.HeroDesigner;
import com.hero.objects.Adder;
import com.hero.objects.GenericObject;
import com.hero.ui.dialog.GenericDialog;
import com.hero.util.XMLUtility;

/**
 * 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 SenseAdder extends Power {

	private static ArrayList<SenseAdder> allSenseAdders = new ArrayList<SenseAdder>();

	/**
	 * Returns a Vector of SenseAdder objects representing all Sense Modifiers
	 * defined in the active template.
	 * 
	 * @return
	 */
	public static ArrayList<SenseAdder> getAllSenseAdders() {
		return SenseAdder.allSenseAdders;
	}

	/**
	 * Utility method to format the display value for a Detect.
	 * 
	 * @param val
	 * @return
	 */
	public static String getDetectDisplay(Detect val) {
		String ret = val.getAlias();
		String whatString = val.getSelectedOption().getAlias();
		boolean swap = false;
		ArrayList<Adder> assigned = val.assignedAdders;
		for (Adder ad : assigned) {
			if (ad.getXMLID().equals("EXTRA")) {
				whatString += ", " + ad.getAlias();
				swap = true;
				ad.setDisplayInString(false);
			}
		}
		if (swap) {
			whatString = whatString.substring(0, whatString.lastIndexOf(","))
					+ " and"
					+ whatString.substring(whatString.lastIndexOf(",") + 1,
							whatString.length());
		}
		ret += " " + whatString;
		return ret;
	}

	protected int allCost;

	private long assignedAddersLastCalc;

	private ArrayList<Adder> assignedAddersSaver;

	private long automaticAddersLastCalc;

	private ArrayList<Adder> automaticAddersSaver;

	private long availableAddersLastCalc;

	private ArrayList<Adder> availableAddersSaver;

	protected int groupCost;

	private long optionsLastCalc;

	private ArrayList<Adder> optionsSaver;

	public boolean selectedOptionLock;

	protected int senseCost;

	private long senseGroupsLastCalc;

	private ArrayList<String> senseGroupsSaver;

	private long sensesLastCalc;

	private ArrayList<String> sensesSaver;

	public SenseAdder(Element root) {
		super(root, "SENSEADDER");
		if ((xmlID != null) && (xmlID.trim().length() > 0)
				&& includedInTemplate()) {
			SenseAdder.allSenseAdders.add(this);
		}
	}

	public SenseAdder(Element root, String xmlid) {
		super(root, xmlid);
		if ((GenericObject.findObjectByID(SenseAdder.allSenseAdders, xmlid) == null)
				&& (xmlID != null)
				&& (xmlID.trim().length() > 0)
				&& includedInTemplate()) {
			SenseAdder.allSenseAdders.add(this);
		}
	}

	@Override
	public ArrayList<Adder> getAssignedAdders() {
		if ((assignedAddersSaver != null)
				&& (assignedAddersLastCalc > Power.lastSenseEdit)
				&& (Power.lastSenseEdit > 0)) {
			return assignedAddersSaver;
		}
		ArrayList<Adder> ret = super.getAssignedAdders();
		ArrayList<String> purchasedGroups = getSenseGroups();
		if (purchasedGroups == null) {
			purchasedGroups = new ArrayList<String>();
		}
		OUTER: for (int i = ret.size() - 1; i >= 0; i--) {
			Adder ad = ret.get(i);
			if (ad.getXMLID().equals("GROUP")
					&& (ad.getSelectedOption() != null)) {
				if (ad.getSelectedOption().getXMLID().equals(
						getSelectedOption().getXMLID())) {
					ret.remove(i);
					continue OUTER;
				}
				ArrayList<SenseGroup> groups = SenseGroup.getAllGroups();
				GROUPS: for (SenseGroup group : groups) {
					if (group.getXMLID().equals(
							ad.getSelectedOption().getXMLID())) {
						ArrayList<String> adders = group
								.getSenseAdders(getID());
						if (adders.contains(getXMLID())) {
							ret.remove(i);
							continue OUTER;
						}
						if (levelValue < 1) {
							ad.setBaseCost(groupCost);
						} else {
							ad.setBaseCost(groupCost * levels / levelValue);
						}
						break GROUPS;
					}
				}
			} else if (ad.getXMLID().endsWith("GROUP")) {
				if ((getSelectedOption() != null)
						&& ad.getXMLID().equals(getSelectedOption().getXMLID())) {
					ret.remove(i);
					continue OUTER;
				}
				ArrayList<SenseGroup> groups = SenseGroup.getAllGroups();
				GROUPS: for (SenseGroup group : groups) {
					if (group.getXMLID().equals(ad.getXMLID())) {
						ArrayList<String> adders = group
								.getSenseAdders(getID());
						if (adders.contains(getXMLID())) {
							ret.remove(i);
							continue OUTER;
						}
						if (levelValue < 1) {
							ad.setBaseCost(groupCost);
						} else {
							ad.setBaseCost(groupCost * levels / levelValue);
						}
						break GROUPS;
					}
				}
			} else if (ad.getXMLID().equals("SINGLE")
					&& (ad.getSelectedOption() != null)) {
				if (ad.getSelectedOption().getXMLID().equals(
						getSelectedOption().getXMLID())) {
					ret.remove(i);
					continue OUTER;
				}
				ArrayList<Sense> senses = Sense.getAllSenses();
				SENSES: for (Sense sense : senses) {
					if (sense.getXMLID().equals(
							ad.getSelectedOption().getXMLID())) {
						if (purchasedGroups.contains(sense.getGroup()
								.getXMLID())) {
							ret.remove(i);
							continue OUTER;
						}
						ArrayList<String> adders = sense
								.getBuiltInSenseAdders(getID());
						if (adders.contains(getXMLID())) {
							ret.remove(i);
							continue OUTER;
						}
						if (levelValue < 1) {
							ad.setBaseCost(senseCost);
						} else {
							ad.setBaseCost(senseCost * levels / levelValue);
						}
						break SENSES;
					}
				}
			} else {
				if ((getSelectedOption() != null)
						&& ad.getXMLID().equals(getSelectedOption().getXMLID())
						&& ad.getDisplay().equals(
								getSelectedOption().getDisplay())) {
					ret.remove(i);
					continue OUTER;
				}
				ArrayList<Sense> senses = Sense.getAllSenses();
				SENSES: for (Sense sense : senses) {
					if (sense.getXMLID().equals(ad.getXMLID())) {
						if (sense.getXMLID().equals("DETECT")) {
							String comp = SenseAdder
									.getDetectDisplay((Detect) sense);
							if (!comp.equals(ad.getDisplay())) {
								continue SENSES;
							}
						}
						if ((sense.getGroup() != null)
								&& purchasedGroups.contains(sense.getGroup()
										.getXMLID())) {
							ret.remove(i);
							continue OUTER;
						}
						ArrayList<String> adders = sense
								.getBuiltInSenseAdders(getID());
						if (adders.contains(getXMLID())) {
							ret.remove(i);
							continue OUTER;
						}
						if (levelValue < 1) {
							ad.setBaseCost(senseCost);
						} else {
							ad.setBaseCost(senseCost * levels / levelValue);
						}
						break SENSES;
					}
				}
			}
		}
		assignedAddersSaver = ret;
		assignedAddersLastCalc = System.currentTimeMillis();
		return ret;
	}

	protected ArrayList<Adder> getAutomaticAdders() {
		if ((automaticAddersSaver != null)
				&& (automaticAddersLastCalc > Power.lastSenseEdit)
				&& (Power.lastSenseEdit > 0)) {
			return automaticAddersSaver;
		}
		ArrayList<Adder> ret = new ArrayList<Adder>();
		ArrayList<String> purchasedGroups = getSenseGroups();
		if ((getSelectedOption() == null)
				|| (getSelectedOption().getXMLID() == null)) {
			return ret;
		}
		if ((groupCost > 0) && !getSelectedOption().getXMLID().equals("ALL")) {
			ArrayList<String> groups = getSenseGroups();
			ArrayList<SenseGroup> allGroups = SenseGroup.getOwnedGroups();
			for (SenseGroup group : allGroups) {
				if (group.getXMLID().equals("UNUSUALGROUP")
						|| group.getXMLID().equals("NOGROUP")) {
					continue;
				} else if (groups.contains(group.getXMLID())) {
					continue;
				} else {
					ArrayList<String> adders = group.getSenseAdders(getID());
					if (adders.contains(getXMLID())) {
						continue;
					}
					Adder g = new Adder(group);
					g.setAvailableAdders(new ArrayList<Adder>());
					g.setAssignedAdders(new ArrayList<Adder>());
					g.setExclusive(true);
					if (levelValue < 1) {
						g.setBaseCost(groupCost);
					} else {
						g.setLevelValue(-1);
						g.setBaseCost(groupCost * levels / levelValue);
					}
					ret.add(g);
				}
			}
		}
		if (senseCost > 0) {
			ArrayList<String> senses = getSenses();
			ArrayList<Sense> allSenses = Sense.getOwnedSenses();
			LOOP: for (Sense sense : allSenses) {
				if (senses.contains(sense.getXMLID())
						&& !sense.getXMLID().equals("DETECT")) {
					continue;
				} else if (purchasedGroups
						.contains(sense.getGroup().getXMLID())) {
					continue;
				} else {
					if (sense.getXMLID().equals("DETECT")) {
						String comp = SenseAdder
								.getDetectDisplay((Detect) sense);
						if (comp.equals(getSelectedOption().getDisplay())) {
							continue LOOP;
						}
						ArrayList<Adder> assigned = getAssignedAdders();
						for (Adder ad : assigned) {
							if (ad.getDisplay().equals(comp)) {
								continue LOOP;
							}
						}
					}
					ArrayList<String> adders = sense
							.getBuiltInSenseAdders(getID());
					if (adders.contains(getXMLID())) {
						continue;
					}
					Adder g = new Adder(sense);
					if (sense.getXMLID().equals("DETECT")) {
						g.setDisplay(SenseAdder
								.getDetectDisplay((Detect) sense));
						g.setAlias(SenseAdder.getDetectDisplay((Detect) sense));
						g.setOptions(new ArrayList<Adder>());
						g.setLevelValue(-1);
						g.setLevelCost(-1);
						g.setSelectedOption(null);
					}
					g.setExclusive(true);
					g.setAvailableAdders(new ArrayList<Adder>());
					g.setAssignedAdders(new ArrayList<Adder>());
					if (levelValue < 1) {
						g.setBaseCost(senseCost);
					} else {
						g.setBaseCost(senseCost * levels / levelValue);
					}
					ret.add(g);
				}
			}
		}
		automaticAddersSaver = ret;
		automaticAddersLastCalc = System.currentTimeMillis();
		return ret;
	}

	@Override
	public ArrayList<Adder> getAvailableAdders() {
		if ((availableAddersSaver != null)
				&& (availableAddersLastCalc > Power.lastSenseEdit)
				&& (Power.lastSenseEdit > 0)) {
			return availableAddersSaver;
		}
		ArrayList<Adder> ret = super.getAvailableAdders();
		ArrayList<Adder> all = new ArrayList<Adder>();
		all.addAll(getAssignedAdders());
		Collections.sort(all);
		ArrayList<Adder> auto = getAutomaticAdders();
		OUTER: for (Adder ad : auto) {
			if (GenericObject.findObjectByID(all, ad.getXMLID()) == null) {
				ret.add(ad);
			} else if (ad.getXMLID().equals("DETECT")) {
				for (int j = 0; j < all.size(); j++) {
					Adder comp = all.get(j);
					if (comp.getDisplay().equals(ad.getDisplay())) {
						continue OUTER;
					}
				}
				ret.add(ad);
			}
		}
		Collections.sort(ret);
		all.addAll(ret);
		availableAddersSaver = all;
		availableAddersLastCalc = System.currentTimeMillis();
		return all;
	}

	@Override
	public String getColumn2Output() {
		String ret = getAlias();
		if (getName().trim().length() > 0) {
			ret = "<i>" + getName() + ":</i>  " + ret;
		}

		if ((getInput() != null) && (getInput().trim().length() > 0)) {
			ret += ":  " + getInput();
		}
		String withString = " with ";
		if (getSelectedOption() != null) {
			withString += getSelectedOption().getAlias();

			String adderString = getAdderString();
			if (adderString.trim().length() > 0) {
				withString += ", " + adderString;
				withString = withString.substring(0, withString
						.lastIndexOf(","))
						+ " and"
						+ withString.substring(withString.lastIndexOf(",") + 1,
								withString.length());
			}
		} else {
			String adderString = getAdderString();
			if (adderString.trim().length() > 0) {
				withString += " " + adderString;
				if (withString.indexOf(", ") > 0) {
					withString = withString.substring(0, withString
							.lastIndexOf(","))
							+ " and"
							+ withString.substring(
									withString.lastIndexOf(",") + 1, withString
											.length());
				}
			}
		}
		if (!withString.equals(" for")) {
			ret += withString;
		}
		ret += getModifierString();
		if ((getEndUsage() > 0)
				&& (GenericObject.findObjectByID(HeroDesigner.getActiveHero()
						.getPowers(), "ENDURANCERESERVE") != null)
				&& (GenericObject.findObjectByID(getAllAssignedModifiers(),
						"ENDRESERVEOREND") == null)
				&& !HeroDesigner.getInstance().getPrefs().useWG()) {
			if (getUseENDReserve()) {
				ret += " (uses END Reserve)";
			} else {
				ret += " (uses Personal END)";
			}
		}

		return ret;
	}

	@Override
	public GenericDialog getDialog(boolean isNew, boolean isPower) {
		Power.lastSenseEdit = System.currentTimeMillis();
		return super.getDialog(isNew, isPower);
	}

	@Override
	public ArrayList<Adder> getOptions() {
		if ((optionsSaver != null) && (options.size() > 0)
				&& (optionsLastCalc > Power.lastSenseEdit)
				&& (Power.lastSenseEdit > 0)) {
			return optionsSaver;
		}
		ArrayList<Adder> ret = (ArrayList<Adder>) super.getOptions().clone();
		if ((allCost > 0) && (GenericObject.findObjectByID(ret, "ALL") == null)) {
			Adder allAdder = new Adder(new Element("ADDER"));
			allAdder.setXMLID("ALL");
			if (levelValue > 0) {
				allAdder.setLevelCost(allCost);
			} else {
				allAdder.setBaseCost(allCost);
			}
			allAdder.setDisplay("all Sense Groups");
			allAdder.setAlias("all Sense Groups");
			ret.add(allAdder);
		}
		if (groupCost > 0) {
			ArrayList<SenseGroup> all = SenseGroup.getOwnedGroups();
			for (SenseGroup gr : all) {
				if (getXMLID().startsWith("DIMENSIONAL")) {
					if (gr.getSenseAdders(getID())
							.contains("DIMENSIONALSINGLE")
							|| gr.getSenseAdders(getID()).contains(
									"DIMENSIONALALL")
							|| gr.getSenseAdders(getID()).contains(
									"DIMENSIONALGROUP")) {
						continue;
					}
				}
				if ((GenericObject.findObjectByID(ret, gr.getXMLID()) == null)
						&& (!gr.getSenseAdders(getID()).contains(getXMLID()) || (getLevelCost() > 0))) {
					Adder ad = new Adder(gr);
					if (levelValue > 0) {
						ad.setLevelCost(groupCost);
					} else {
						ad.setBaseCost(groupCost);
					}
					ret.add(ad);
				}
			}
		}
		if (senseCost > 0) {
			ArrayList<Sense> all = Sense.getOwnedSenses();
			OUTER: for (Sense gr : all) {
				if (getXMLID().startsWith("DIMENSIONAL")) {
					if (gr.getBuiltInSenseAdders(getID()).contains(
							"DIMENSIONALSINGLE")
							|| gr.getBuiltInSenseAdders(getID()).contains(
									"DIMENSIONALALL")
							|| gr.getBuiltInSenseAdders(getID()).contains(
									"DIMENSIONALGROUP")) {
						continue;
					}
				}
				if (!gr.getBuiltInSenseAdders(getID()).contains(getXMLID())
						|| (getLevelCost() > 0)) {
					String comp = gr.getDisplay();
					if (gr.getXMLID().equals("DETECT")) {
						comp = SenseAdder.getDetectDisplay((Detect) gr);
					}
					for (Adder ad : ret) {
						if (ad.getDisplay().equals(comp)) {
							continue OUTER;
						}
					}
					Adder ad = new Adder(gr);
					if (levelValue > 0) {
						ad.setBaseCost(0);
						ad.setLevelCost(senseCost);
					} else {
						ad.setLevelCost(0);
						ad.setLevelValue(-1);
						ad.setBaseCost(senseCost);
					}
					if (gr.getXMLID().equals("DETECT")) {
						ad.setDisplay(comp);
						ad.setAlias(comp);
						ad.setAvailableAdders(new ArrayList<Adder>());
						ad.setAssignedAdders(new ArrayList<Adder>());
					}
					ret.add(ad);
				}
			}
		}
		optionsSaver = ret;
		optionsLastCalc = System.currentTimeMillis();
		return ret;
	}

	@Override
	public Adder getSelectedOption() {
		Adder ret = super.getSelectedOption();
		return ret;
	}

	/**
	 * Returns a Vector of Strings defining the XMLIDs of all Sense Groups that
	 * this Sense Modifier affects.
	 * 
	 * @return
	 */
	public ArrayList<String> getSenseGroups() {
		if ((senseGroupsSaver != null)
				&& (senseGroupsLastCalc > Power.lastSenseEdit)
				&& (Power.lastSenseEdit > 0)) {
			return senseGroupsSaver;
		}
		ArrayList<String> ret = new ArrayList<String>();
		if (getSelectedOption() != null) {
			if (getSelectedOption().getXMLID().equals("ALL")) {
				ArrayList<SenseGroup> all = SenseGroup.getAllGroups();
				for (SenseGroup g : all) {
					ret.add(g.getXMLID());
				}
				senseGroupsSaver = ret;
				senseGroupsLastCalc = System.currentTimeMillis();
				return ret;
			}
			if (getSelectedOption().getXMLID().endsWith("GROUP")) {
				ret.add(getSelectedOption().getXMLID());
			}
		}
		for (Adder ad : super.getAssignedAdders()) {
			if (ad.getXMLID().equals("GROUP")) {
				if ((ad.getSelectedOption() != null)
						&& !ret.contains(ad.getSelectedOption().getXMLID())) {
					ret.add(ad.getSelectedOption().getXMLID());
				}
			} else if (ad.getXMLID().endsWith("GROUP")) {
				if (!ret.contains(ad.getXMLID())) {
					ret.add(ad.getXMLID());
				}
			}
		}
		senseGroupsSaver = ret;
		senseGroupsLastCalc = System.currentTimeMillis();
		return ret;
	}

	/**
	 * Returns a Vector of Strings defining the XMLIDs of all Senses that this
	 * Sense Modifier affects.
	 * 
	 * @return
	 */
	public ArrayList<String> getSenses() {
		if ((sensesSaver != null) && (sensesLastCalc > Power.lastSenseEdit)
				&& (Power.lastSenseEdit > 0)) {
			return sensesSaver;
		}
		ArrayList<String> ret = new ArrayList<String>();
		if (getSelectedOption() != null) {
			if (!getSelectedOption().getXMLID().endsWith("GROUP")) {
				ret.add(getSelectedOption().getXMLID());
			}
		}
		for (Adder ad : super.getAssignedAdders()) {
			if (!ad.getXMLID().endsWith("GROUP")) {
				if (ad.getSelectedOption() != null) {
					if (!ret.contains(ad.getSelectedOption().getXMLID())) {
						ret.add(ad.getSelectedOption().getXMLID());
					}
				} else if (!ret.contains(ad.getXMLID())) {
					ret.add(ad.getXMLID());
				}
			}
		}
		sensesSaver = ret;
		sensesLastCalc = System.currentTimeMillis();
		return ret;
	}

	@Override
	protected void init(Element element) {
		super.init(element);
		allCost = -1;
		groupCost = -1;
		senseCost = -1;
		String check = XMLUtility.getValue(element, "ALLCOST");
		if ((check != null) && (check.trim().length() > 0)) {
			try {
				int val = Integer.parseInt(check);
				allCost = val;
			} catch (Exception exp) {
			}
		}
		check = XMLUtility.getValue(element, "GROUPCOST");
		if ((check != null) && (check.trim().length() > 0)) {
			try {
				int val = Integer.parseInt(check);
				groupCost = val;
			} catch (Exception exp) {
			}
		}
		check = XMLUtility.getValue(element, "SENSECOST");
		if ((check != null) && (check.trim().length() > 0)) {
			try {
				int val = Integer.parseInt(check);
				senseCost = val;
			} catch (Exception exp) {
			}
		}
	}

	@Override
	public void restoreFromSave(Element root) {
		super.restoreFromSave(root);
		Power.lastSenseEdit = System.currentTimeMillis();
		// do some checking for v1 conversions...
		String option = null;
		String check = XMLUtility.getValue(root, "OPTIONID");
		if ((check != null) && (check.trim().length() > 0)) {
			option = check;
		} else {
			check = XMLUtility.getValue(root, "OPTION");
			if ((check != null) && (check.trim().length() > 0)) {
				option = check;
			}
		}
		if (option != null) {
			// instead of getting the available options for this part, we're
			// going to grab all senses and sense groups
			// the reason for this is to allow analyze to restore
			// properly...even if it is restored before the appropriate
			// sense with discriminatory is restored
			ArrayList<GenericObject> vec = new ArrayList<GenericObject>();
			vec.addAll(Sense.getAllSenses());
			vec.addAll(SenseGroup.getAllGroups());
			ArrayList<Adder> avail = new ArrayList<Adder>();
			for (GenericObject o : vec) {
				Adder ad = new Adder(o);
				if (levelValue > 0) {
					ad.setBaseCost(0);
					ad.setLevelCost(senseCost);
				} else {
					ad.setLevelCost(0);
					ad.setLevelValue(-1);
					ad.setBaseCost(senseCost);
				}
				avail.add(ad);
			}
			if ((allCost > 0)
					&& (GenericObject.findObjectByID(avail, "ALL") == null)) {
				Adder allAdder = new Adder(new Element("ADDER"));
				allAdder.setXMLID("ALL");
				if (levelValue > 0) {
					allAdder.setLevelCost(allCost);
				} else {
					allAdder.setBaseCost(allCost);
				}
				allAdder.setDisplay("all Sense Groups");
				allAdder.setAlias("all Sense Groups");
				avail.add(allAdder);
			}
			boolean matched = false;
			String opalias = XMLUtility.getValue(root, "OPTION_ALIAS");
			LOOP: for (Adder ad : avail) {
				if (ad.getXMLID().equals(option)
						|| ad.getDisplay().toUpperCase().equals(
								option.toUpperCase())) {
					if ((opalias != null) && (opalias.trim().length() > 0)) {
						ad.setAlias(opalias);
					}
					setSelectedOption(ad);
					matched = true;
					break LOOP;
				}
			}
			if (!matched) {
				if ((opalias != null) && (opalias.trim().length() > 0)) {
					LOOP: for (Adder ad : avail) {
						if (ad.getDisplay().toUpperCase().startsWith(
								opalias.trim().toUpperCase())
								|| opalias.trim().toUpperCase().startsWith(
										ad.getDisplay())
								|| ad.getAlias().equals(opalias)) {
							ad.setAlias(opalias);
							setSelectedOption(ad);
							matched = true;
							break LOOP;
						}
					}
				}
				if (!matched) {
					LOOP: for (Adder ad : avail) {
						if (ad.getBaseCost() == baseCost) {
							if ((opalias != null)
									&& (opalias.trim().length() > 0)) {
								ad.setAlias(opalias);
							}
							setSelectedOption(ad);
							matched = true;
							break LOOP;
						}
					}
				}
			}
		}
		ArrayList<Adder> holder = availableAdders;
		assignedAdders = new ArrayList<Adder>();
		availableAdders = new ArrayList<Adder>();
		ArrayList<Adder> avail = getAvailableAdders();
		availableAdders = holder;
		ArrayList<Adder> assigned = new ArrayList<Adder>();
		Iterator iter = root.getChildren("ADDER").iterator();
		OUTER: while (iter.hasNext()) {
			Element element = (Element) iter.next();
			String id = XMLUtility.getValue(element, "XMLID");
			if ((id != null)
					&& (id.trim().equals("SINGLE") || id.trim().equals("GROUP"))) {
				String adop = null;
				String val = XMLUtility.getValue(element, "OPTIONID");
				if ((val != null) && (val.trim().length() > 0)) {
					adop = val;
				} else {
					val = XMLUtility.getValue(element, "OPTION");
					if ((val != null) && (val.trim().length() > 0)) {
						adop = val;
					}
				}
				if ((adop != null) && (adop.trim().length() > 0)) {
					for (Adder ad : avail) {
						if (ad.getXMLID().startsWith(adop.trim().toUpperCase())
								|| adop.trim().toUpperCase().startsWith(
										ad.getXMLID())
								|| ad.getDisplay().equals(adop)) {
							try {
								ad = (Adder) ad.clone();
								ad.setSelected(true);
								assigned.add(ad);
								continue OUTER;
							} catch (Exception exp) {

							}
						}
					}
				}
			}
			Adder ad = new Adder(element);
			ad.setExclusive(false);
			ad.setAvailableCheck(false);
			ad.restoreFromSave(element);
			assigned.add(ad);
			ArrayList<Adder> opts = getOptions();
			if ((selectedOption == null) && (opts.size() > 0)) {
				setSelectedOption(opts.get(0));
			}
		}
		assignedAdders = assigned;
		Power.lastSenseEdit = System.currentTimeMillis();
	}

	@Override
	public void setSelectedOption(Adder option) {
		double orig = levelValue;
		Power.lastSenseEdit = System.currentTimeMillis();
		super.setSelectedOption(option);
		levelValue = orig;
		if (option != null) {
			baseCost = 0;
			levelCost = 0;
			if (option.getXMLID().equals("ALL")) {
				if (levelValue > 0) {
					levelCost = allCost;
				} else {
					baseCost = allCost;
				}
			} else if (option.getXMLID().endsWith("GROUP") && (groupCost > 0)) {
				if (levelValue > 0) {
					levelCost = groupCost;
				} else {
					baseCost = groupCost;
				}
			} else {
				if (levelValue > 0) {
					levelCost = senseCost;
				} else {
					baseCost = senseCost;
				}
			}
		}
		Power.lastSenseEdit = System.currentTimeMillis();
	}
}