package com.hero.objects.characteristics;

import java.util.ArrayList;

import org.jdom.Element;

import com.hero.HeroDesigner;
import com.hero.objects.CharAffectingObject;
import com.hero.objects.GenericObject;
import com.hero.objects.modifiers.Modifier;
import com.hero.objects.powers.CompoundPower;
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 Running extends Characteristic {

	private static String xmlID = "RUNNING";

	public Running(Element root) {
		super(root, Running.xmlID);
	}

	@Override
	public void init(Element element) {
		display = "Running";
		levelCost = 2;
		levelValue = 1;
		minimumCost = 2;
		baseCost = 0;
		super.init(element);
	}

	public boolean verified() {
		return true;
	}

	public String getTotalDisplay() {
		boolean is6E = HeroDesigner.getActiveTemplate().is6E();
		double primary = getPrimaryValue();
		double secondary = getSecondaryValue();
		String ret = Rounder.roundHalfUp(primary) + (is6E ? "m" : "\"");
		if (primary != secondary) {
			ret += "/" + Rounder.roundHalfUp(secondary) + (is6E ? "m" : "\"");
		}
		return ret;
	}

	@Override
	public String getDamageDisplay() {
		boolean is6E = HeroDesigner.getActiveTemplate().is6E();
		String ret = "";
		if (getAffectTotal() && getLevels() > 0) {
			ret += "+";
		}

		ret += getLevels() + (is6E ? "m" : "\"");
		return ret;
	}

	@Override
	public int getType() {
		return Constants.RUNNING;
	}

	@Override
	public String getRoll() {
		return "";
	}

	@Override
	public String getColumn2Output() {
		if (getLevels() == 0 && addModifiersToBase()
				&& getModifierString().trim().length() > 0) {
			String mods = getModifierString();
			if (mods.trim().startsWith(",")) {
				mods = mods.trim().substring(1, mods.length()).trim();
			}
			mods += " applied to " + getAlias();

			if (getName() != null && getName().trim().length() > 0) {
				mods = "<i>" + getName() + ":</i>  " + mods;
			}

			return mods;
		}
		String ret = getAlias() + " " + getDamageDisplay();
		if (getName().trim().length() > 0) {
			ret = "<i>" + getName() + ":</i>  " + ret;
		}
		if (getInput() != null && getInput().trim().length() > 0) {
			ret += ":  " + getInput();
		}
		if (getAffectTotal()) {
			ret += " (" + getTotalDisplay() + " total)";
		}
		if (getSelectedOption() != null) {
			ret += " (";
			ret += getSelectedOption().getAlias();

			String adderString = getAdderString();
			if (adderString.trim().length() > 0) {
				ret += "; " + adderString;
			}
			ret += ")";
		} else {
			String adderString = getAdderString();
			if (adderString.trim().length() > 0) {
				ret += ", " + adderString;
			}
		}
		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 String getValueDisplay() {
		boolean is6E = HeroDesigner.getActiveTemplate().is6E();
		if (getPrimaryValue() != getSecondaryValue()) {
			return Rounder.roundHalfUp(getPrimaryValue()) + (is6E ? "m" : "\"")
					+ "/" + Rounder.roundHalfUp(getSecondaryValue())
					+ (is6E ? "m" : "\"") + ",";
		} else {
			return "" + Rounder.roundHalfUp(getPrimaryValue())
					+ (is6E ? "m" : "\"");
		}
	}

	@Override
	public String getDisplayNotes() {
		String ret = "";
		ret += "END [";
		int end = getPrimaryEND();
		ret += end;
		int end2 = getSecondaryEND();
		if (!(end == end2)) {
			ret += "/" + end2 + "]";
		} else {
			ret += "]";
		}
		return ret;
	}

	public int getSecondaryEND() {
		double bonus = getBaseEND();
		if (bonus < 0) {
			bonus = 0;
		}
		for (int i = 0; i < HeroDesigner.getActiveHero().getPowers().size(); i++) {
			if (HeroDesigner.getActiveHero().getPowers().get(i).getXMLID()
					.equals(getXMLID())) {
				Characteristic power = (Characteristic) HeroDesigner
						.getActiveHero().getPowers().get(i);
				if (power.getAffectTotal()) {
					bonus += power.getEndUsage();
				}
			} else if (HeroDesigner.getActiveHero().getPowers().get(i) instanceof CompoundPower) {
				CompoundPower pow = (CompoundPower) HeroDesigner
						.getActiveHero().getPowers().get(i);
				for (int j = 0; j < pow.getPowers().size(); j++) {
					if (pow.getPowers().get(j).getXMLID().equals(getXMLID())) {
						Characteristic power = (Characteristic) pow.getPowers()
								.get(j);
						if (power.getAffectPrimary() && power.getAffectTotal()) {
							bonus += power.getEndUsage();
						}
					} else if (pow.getPowers().get(j) instanceof CharAffectingObject) {
						CharAffectingObject power = (CharAffectingObject) pow
								.getPowers().get(j);
						if (power.getIncreaseLevels(getType()) > 0
								&& power.getAffectPrimary()
								&& CharAffectingObject.checkFigured(power,
										getType()) && power.getAffectTotal()) {
							double add = power
									.getIncreaseValue(getType(), true);
							if (getAPPerEnd() > 0) {
								double bd = add * getLevelCost()
										/ getAPPerEnd();
								bonus += bd;
							}
						}
					}
				}
			} else if (HeroDesigner.getActiveHero().getPowers().get(i) instanceof CharAffectingObject) {
				CharAffectingObject power = (CharAffectingObject) HeroDesigner
						.getActiveHero().getPowers().get(i);
				if (power.getIncreaseLevels(getType()) > 0
						&& CharAffectingObject.checkFigured(power, getType())
						&& power.getAffectTotal()) {
					double add = power.getIncreaseValue(getType(), false);
					add += power.getIncreaseValue(getType(), true);
					if (getAPPerEnd() > 0) {
						double bd = Rounder.roundHalfDown(add * getLevelCost()
								/ getAPPerEnd());
						bonus += bd;
					}
				}
			}
		}
		for (int i = 0; i < HeroDesigner.getActiveHero().getEquipment().size(); i++) {
			if (HeroDesigner.getActiveHero().getEquipment().get(i).getXMLID()
					.equals(getXMLID())) {
				Characteristic power = (Characteristic) HeroDesigner
						.getActiveHero().getEquipment().get(i);
				if (power.getAffectTotal()) {
					bonus += power.getEndUsage();
				}
			} else if (HeroDesigner.getActiveHero().getEquipment().get(i) instanceof CompoundPower) {
				CompoundPower pow = (CompoundPower) HeroDesigner
						.getActiveHero().getEquipment().get(i);
				for (int j = 0; j < pow.getPowers().size(); j++) {
					if (pow.getPowers().get(j).getXMLID().equals(getXMLID())) {
						Characteristic power = (Characteristic) pow.getPowers()
								.get(j);
						if (power.getAffectPrimary() && power.getAffectTotal()) {
							bonus += power.getEndUsage();
						}
					} else if (pow.getPowers().get(j) instanceof CharAffectingObject) {
						CharAffectingObject power = (CharAffectingObject) pow
								.getPowers().get(j);
						if (power.getIncreaseLevels(getType()) > 0
								&& power.getAffectPrimary()
								&& CharAffectingObject.checkFigured(power,
										getType()) && power.getAffectTotal()) {
							double add = power
									.getIncreaseValue(getType(), true);
							if (getAPPerEnd() > 0) {
								double bd = add * getLevelCost()
										/ getAPPerEnd();
								bonus += bd;
							}
						}
					}
				}
			} else if (HeroDesigner.getActiveHero().getEquipment().get(i) instanceof CharAffectingObject) {
				CharAffectingObject power = (CharAffectingObject) HeroDesigner
						.getActiveHero().getEquipment().get(i);
				if (power.getIncreaseLevels(getType()) > 0
						&& CharAffectingObject.checkFigured(power, getType())
						&& power.getAffectTotal()) {
					double add = power.getIncreaseValue(getType(), false);
					add += power.getIncreaseValue(getType(), true);
					if (getAPPerEnd() > 0) {
						double bd = Rounder.roundHalfDown(add * getLevelCost()
								/ getAPPerEnd());
						bonus += bd;
					}
				}
			}
		}
		return (int) Rounder.roundHalfDown(bonus);
	}

	public int getPrimaryEND() {
		double bonus = getBaseEND();
		if (bonus < 0) {
			bonus = 0;
		}
		for (int i = 0; i < HeroDesigner.getActiveHero().getPowers().size(); i++) {
			if (HeroDesigner.getActiveHero().getPowers().get(i).getXMLID()
					.equals(getXMLID())) {
				Characteristic power = (Characteristic) HeroDesigner
						.getActiveHero().getPowers().get(i);
				if (power.getAffectPrimary() && power.getAffectTotal()) {
					bonus += power.getEndUsage();
				}
			} else if (HeroDesigner.getActiveHero().getPowers().get(i) instanceof CompoundPower) {
				CompoundPower pow = (CompoundPower) HeroDesigner
						.getActiveHero().getPowers().get(i);
				for (int j = 0; j < pow.getPowers().size(); j++) {
					if (pow.getPowers().get(j).getXMLID().equals(getXMLID())) {
						Characteristic power = (Characteristic) pow.getPowers()
								.get(j);
						if (power.getAffectPrimary() && power.getAffectTotal()) {
							bonus += power.getEndUsage();
						}
					} else if (pow.getPowers().get(j) instanceof CharAffectingObject) {
						CharAffectingObject power = (CharAffectingObject) pow
								.getPowers().get(j);
						if (power.getIncreaseLevels(getType()) > 0
								&& power.getAffectPrimary()
								&& CharAffectingObject.checkFigured(power,
										getType()) && power.getAffectTotal()) {
							double add = power
									.getIncreaseValue(getType(), true);
							if (getAPPerEnd() > 0) {
								double bd = add * getLevelCost()
										/ getAPPerEnd();
								bonus += bd;
							}
						}
					}
				}
			} else if (HeroDesigner.getActiveHero().getPowers().get(i) instanceof CharAffectingObject) {
				CharAffectingObject power = (CharAffectingObject) HeroDesigner
						.getActiveHero().getPowers().get(i);
				if (power.getIncreaseLevels(getType()) > 0
						&& power.getAffectPrimary()
						&& CharAffectingObject.checkFigured(power, getType())
						&& power.getAffectTotal()) {
					double add = power.getIncreaseValue(getType(), true);
					if (getAPPerEnd() > 0) {
						double bd = add * getLevelCost() / getAPPerEnd();
						bonus += bd;
					}
				}
			}
		}
		for (int i = 0; i < HeroDesigner.getActiveHero().getEquipment().size(); i++) {
			if (HeroDesigner.getActiveHero().getEquipment().get(i).getXMLID()
					.equals(getXMLID())) {
				Characteristic power = (Characteristic) HeroDesigner
						.getActiveHero().getEquipment().get(i);
				if (power.getAffectPrimary() && power.getAffectTotal()) {
					bonus += power.getEndUsage();
				}
			} else if (HeroDesigner.getActiveHero().getEquipment().get(i) instanceof CompoundPower) {
				CompoundPower pow = (CompoundPower) HeroDesigner
						.getActiveHero().getEquipment().get(i);
				for (int j = 0; j < pow.getPowers().size(); j++) {
					if (pow.getPowers().get(j).getXMLID().equals(getXMLID())) {
						Characteristic power = (Characteristic) pow.getPowers()
								.get(j);
						if (power.getAffectPrimary() && power.getAffectTotal()) {
							bonus += power.getEndUsage();
						}
					} else if (pow.getPowers().get(j) instanceof CharAffectingObject) {
						CharAffectingObject power = (CharAffectingObject) pow
								.getPowers().get(j);
						if (power.getIncreaseLevels(getType()) > 0
								&& power.getAffectPrimary()
								&& CharAffectingObject.checkFigured(power,
										getType()) && power.getAffectTotal()) {
							double add = power
									.getIncreaseValue(getType(), true);
							if (getAPPerEnd() > 0) {
								double bd = add * getLevelCost()
										/ getAPPerEnd();
								bonus += bd;
							}
						}
					}
				}
			} else if (HeroDesigner.getActiveHero().getEquipment().get(i) instanceof CharAffectingObject) {
				CharAffectingObject power = (CharAffectingObject) HeroDesigner
						.getActiveHero().getEquipment().get(i);
				if (power.getIncreaseLevels(getType()) > 0
						&& power.getAffectPrimary()
						&& CharAffectingObject.checkFigured(power, getType())
						&& power.getAffectTotal()) {
					double add = power.getIncreaseValue(getType(), true);
					if (getAPPerEnd() > 0) {
						double bd = add * getLevelCost() / getAPPerEnd();
						bonus += bd;
					}
				}
			}
		}
		return (int) Rounder.roundHalfDown(bonus);
	}

	public int getBaseEND() {
		double bonus = 0;
		double check = 0;
		if (HeroDesigner.getActiveHero() != null) {
			check = origBaseLevel;
			for (int i = 0; i < HeroDesigner.getActiveHero()
					.getCharacteristics().size(); i++) {
				Characteristic ch = (Characteristic) HeroDesigner
						.getActiveHero().getCharacteristics().get(i);
				if (!ch.getXMLID().equals(getXMLID())
						&& ch.getIncreaseLevels(getType()) > 0
						&& ch.getIncrease(getType()) != 0) {
					double mult = ch.getValue(true, getType())
							* ch.getIncrease(getType())
							/ ch.getIncreaseLevels(getType());
					bonus += mult;
				}
			}
		}
		if (check + bonus + getLevels() > maxVal) {
			check = maxVal;
		} else {
			check = check + bonus + getLevels();
		}
		double active = check / getLevelValue() * getLevelCost();
		int denom = getAPPerEnd();
		double ret = 0;
		double mult = 1;
		ArrayList<Modifier> vec = (ArrayList<Modifier>) getAssignedModifiers()
				.clone();
		if (getParentList() != null) {
			vec.addAll(getParentList().getAssignedModifiers());
		}
		if (GenericObject.findObjectByID(vec, "CHARGES") != null) {
			denom = 0;
		}
		if (GenericObject.findObjectByID(vec, "COSTSEND") != null) {
			denom = HeroDesigner.getActiveHero().getRules().getAPPerEND();
		}
		if (GenericObject.findObjectByID(vec, "REDUCEDEND") != null) {
			GenericObject mod = GenericObject.findObjectByID(vec, "REDUCEDEND");
			if (mod.getSelectedOption().getXMLID().equals("HALFEND")) {
				denom = denom * 2;
			} else {
				denom = 0;
			}
		}
		if (GenericObject.findObjectByID(vec, "INCREASEDEND") != null) {
			GenericObject mod = GenericObject.findObjectByID(vec,
					"INCREASEDEND");
			if (GenericObject.findObjectByID(mod.getAssignedAdders(),
					"CIRCUMSTANCE") == null) {
				mult = mod.getSelectedOption().getLevelValue();
			}
		}
		if (denom != 0) {
			ret = active / denom;
		}
		ret = ret * mult;
		if (ret < 0) {
			ret = 0;
		}
		if (Rounder.roundHalfDown(ret) == 0 && active > 0 && denom != 0) {
			ret = 1;
		}
		return (int) Rounder.roundHalfDown(ret);
	}
}