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 Strength extends Characteristic {

    private static String xmlID = "STR";

    public Strength(Element template) {
        super(template, Strength.xmlID);
    }

    @Override
    public int getType() {
        return Constants.STR;
    }
    
    public double getPrimaryLift() {
    	double liftVal1 = 25d;
        double pow1 = getPrimaryValue() / 5d;
        if (pow1 > 0) {
            liftVal1 = Math.pow(2, pow1) * liftVal1;
        } else {
            liftVal1 = liftVal1 / Math.pow(2, Math.abs(pow1));
        }
        return liftVal1;
    }
    
    public double getSecondaryLift() {
    	double liftVal1 = 25d;
        double pow1 = getSecondaryValue() / 5d;
        if (pow1 > 0) {
            liftVal1 = Math.pow(2, pow1) * liftVal1;
        } else {
            liftVal1 = liftVal1 / Math.pow(2, Math.abs(pow1));
        }
        return liftVal1;
    }

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

	public String getHthDamageString() {
		String roll;
		double whole = (getPrimaryValue() - (int) getPrimaryValue() % 5) / 5;
        if (whole < 0) {
            whole = 0;
        }
        int frac = (int) getPrimaryValue() % 5;
        if (HeroDesigner.getActiveHero().getRules()
                .useIncreasedDamageDifferentiation()) {
            if (frac == 4) {
                roll = Rounder.roundHalfUp(whole + 1) + "d6-1";
            } else if (frac == 3) {
                if (whole > 0) {
                    roll = Rounder.roundHalfUp(whole) + " 1/2d6";
                } else {
                    roll = "1/2d6";
                }
            } else if (frac == 2) {
                if (whole > 0) {
                    roll = Rounder.roundHalfUp(whole) + "d6+1";
                } else {
                    roll = "1 pip";
                }
            } else {
                roll = "" + Rounder.roundHalfUp(whole) + "d6";
            }
        } else {
            if (frac > 2 && whole > 0) {
                roll = Rounder.roundHalfUp(whole) + " 1/2";
            } else if (frac > 2) {
                roll = "1/2";
            } else {
                roll = "" + Rounder.roundHalfUp(whole);
            }
            roll = roll + "d6";
        }
        String roll2 = "";
        double whole2 = (getSecondaryValue() - Rounder
                .roundDown(getSecondaryValue()) % 5) / 5;
        if (whole2 < 0) {
            whole2 = 0;
        }
        int frac2 = (int) Rounder.roundDown(getSecondaryValue()) % 5;
        if (HeroDesigner.getActiveHero().getRules()
                .useIncreasedDamageDifferentiation()) {
            if (frac2 == 4) {
                roll2 = Rounder.roundHalfUp(whole2 + 1) + "d6-1";
            } else if (frac2 == 3) {
                if (whole2 > 0) {
                    roll2 = Rounder.roundHalfUp(whole2) + " 1/2d6";
                } else {
                    roll2 = "1/2d6";
                }
            } else if (frac2 == 2) {
                if (whole2 > 0) {
                    roll2 = Rounder.roundHalfUp(whole2) + "d6+1";
                } else {
                    roll2 = "1 pip";
                }
            } else {
                roll2 = "" + Rounder.roundHalfUp(whole2) + "d6";
            }
        } else {
            if (frac2 > 2 && whole2 > 0) {
                roll2 = Rounder.roundHalfUp(whole2) + " 1/2";
            } else if (frac2 > 2) {
                roll2 = "1/2";
            } else {
                roll2 = "" + Rounder.roundHalfUp(whole2);
            }
            roll2 = roll2 + "d6";
        }
        if (roll.equals(roll2)) {
        	return roll;
        } else {
        	return roll + "/" + roll2;
        }
	}

    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 (getOrigAPPerEnd() > 0
                                && power.getIncreaseLevels(getType()) > 0
                                && power.getAffectPrimary()
                                && CharAffectingObject.checkFigured(power, getType())
                                && power.getAffectTotal()) {
                            double add = power
                                    .getIncreaseValue(getType(), true);
                            double bd = add * getLevelCost()
                                    / getOrigAPPerEnd();
                            bonus += bd;
                        }
                    }
                }
            } else if (HeroDesigner.getActiveHero().getPowers().get(i) instanceof CharAffectingObject) {
                CharAffectingObject power = (CharAffectingObject) HeroDesigner
                        .getActiveHero().getPowers().get(i);
                if (getOrigAPPerEnd() > 0
                        && power.getIncreaseLevels(getType()) > 0
                        && CharAffectingObject.checkFigured(power, getType())
                        && power.getAffectTotal()) {
                    double add = power.getIncreaseValue(getType(), false);
                    add += power.getIncreaseValue(getType(), true);
                    double bd = Rounder.roundHalfDown(add * getLevelCost()
                            / getOrigAPPerEnd());
                    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 (getOrigAPPerEnd() > 0
                                && power.getIncreaseLevels(getType()) > 0
                                && power.getAffectPrimary()
                                && CharAffectingObject.checkFigured(power, getType())
                                && power.getAffectTotal()) {
                            double add = power
                                    .getIncreaseValue(getType(), true);
                            double bd = add * getLevelCost()
                                    / getOrigAPPerEnd();
                            bonus += bd;
                        }
                    }
                }
            } else if (HeroDesigner.getActiveHero().getEquipment().get(i) instanceof CharAffectingObject) {
                CharAffectingObject power = (CharAffectingObject) HeroDesigner
                        .getActiveHero().getEquipment().get(i);
                if (getOrigAPPerEnd() > 0
                        && power.getIncreaseLevels(getType()) > 0
                        && CharAffectingObject.checkFigured(power, getType())
                        && power.getAffectTotal()) {
                    double add = power.getIncreaseValue(getType(), false);
                    add += power.getIncreaseValue(getType(), true);
                    double bd = Rounder.roundHalfDown(add * getLevelCost()
                            / getOrigAPPerEnd());
                    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 (getOrigAPPerEnd() > 0
                                && power.getIncreaseLevels(getType()) > 0
                                && power.getAffectPrimary()
                                && CharAffectingObject.checkFigured(power, getType())
                                && power.getAffectTotal()) {
                            double add = power
                                    .getIncreaseValue(getType(), true);
                            double bd = add * getLevelCost()
                                    / getOrigAPPerEnd();
                            bonus += bd;
                        }
                    }
                }
            } else if (HeroDesigner.getActiveHero().getPowers().get(i) instanceof CharAffectingObject) {
                CharAffectingObject power = (CharAffectingObject) HeroDesigner
                        .getActiveHero().getPowers().get(i);
                if (getOrigAPPerEnd() > 0
                        && power.getIncreaseLevels(getType()) > 0
                        && power.getAffectPrimary()
                        && CharAffectingObject.checkFigured(power, getType())
                        && power.getAffectTotal()) {
                    double add = power.getIncreaseValue(getType(), true);
                    double bd = add * getLevelCost() / getOrigAPPerEnd();
                    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 (getOrigAPPerEnd() > 0
                                && power.getIncreaseLevels(getType()) > 0
                                && power.getAffectPrimary()
                                && CharAffectingObject.checkFigured(power, getType())
                                && power.getAffectTotal()) {
                            double add = power
                                    .getIncreaseValue(getType(), true);
                            double bd = add * getLevelCost()
                                    / getOrigAPPerEnd();
                            bonus += bd;
                        }
                    }
                }
            } else if (HeroDesigner.getActiveHero().getEquipment().get(i) instanceof CharAffectingObject) {
                CharAffectingObject power = (CharAffectingObject) HeroDesigner
                        .getActiveHero().getEquipment().get(i);
                if (getOrigAPPerEnd() > 0
                        && power.getIncreaseLevels(getType()) > 0
                        && power.getAffectPrimary()
                        && CharAffectingObject.checkFigured(power, getType())
                        && power.getAffectTotal()) {
                    double add = power.getIncreaseValue(getType(), true);
                    double bd = add * getLevelCost() / getOrigAPPerEnd();
                    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().getSTRAPPerEND();
        }
        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);
    }
}