package com.hero.objects.characteristics;

import org.jdom.Element;

import com.hero.HeroDesigner;
import com.hero.objects.CharAffectingObject;
import com.hero.objects.powers.CompoundPower;
import com.hero.objects.powers.Power;
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 Presence extends Characteristic {

    private static String xmlID = "PRE";

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

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

    /**
     * Returns the number of dice of PRE Attack the character can do (split if
     * necessary)
     * 
     * @return
     */
    public String getPREAttack() {
        String roll = "";
        double whole = (getSecondaryValue() - Rounder
                .roundDown(getSecondaryValue()) % 5) / 5;
        int frac = (int) Rounder.roundDown(getSecondaryValue()) % 5;
        if (frac > 2) {
            roll = Rounder.roundHalfUp(whole) + " 1/2";
        } else {
            roll = "" + Rounder.roundHalfUp(whole);
        }
        String roll2 = "";
        double whole2 = (getPrimaryValue() - Rounder
                .roundDown(getPrimaryValue()) % 5) / 5;
        int frac2 = (int) Rounder.roundDown(getPrimaryValue()) % 5;
        if (frac2 > 2) {
            roll2 = Rounder.roundHalfUp(whole2) + " 1/2";
        } else {
            roll2 = "" + Rounder.roundHalfUp(whole2);
        }
        if (!roll.equals(roll2)) {
            roll = roll2 + "d6 / " + roll;
        }
        return roll + "d6";
    }

    @Override
    public String getDisplayNotes() {
        return "PRE Attack: " + getPREAttack();
    }

    @Override
    void calcBaseValue() {
        double bonus = 0;
        if (HeroDesigner.getActiveHero() != null) {
            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.getPREIncreaseValue();
                    doubleBase += mult;
                    bonus += Rounder.roundHalfUp(mult);
                }
            }
            for (int i = 0; i < HeroDesigner.getActiveHero().getPowers().size(); i++) {
                if (HeroDesigner.getActiveHero().getPowers().get(i)
                        .getXMLID().equals(getXMLID())) {
                    continue; // only interested in figured
                } else if (HeroDesigner.getActiveHero().getPowers().get(i) instanceof CompoundPower) {
                    CompoundPower cp = (CompoundPower) HeroDesigner
                            .getActiveHero().getPowers().get(i);
                    for (int j = 0; j < cp.getPowers().size(); j++) {
                        if (cp.getPowers().get(j).getXMLID().equals(
                                getXMLID())) {
                            continue; // only interested in figured
                        } else if (cp.getPowers().get(j) instanceof Characteristic) {
                            CharAffectingObject power = (CharAffectingObject) cp
                                    .getPowers().get(j);
                            if (power.getIncreaseLevels(getType()) > 0
                                    && power.getIncrease(getType()) != 0) {
                                if (power.getAffectPrimary()
                                        && CharAffectingObject.checkFigured(power, getType())
                                        && power.getAffectTotal()) {
                                    double mult = power.getIncreaseValue(
                                            getType(), true);
                                    doubleBase += mult;
                                    bonus += Rounder.roundHalfUp(mult);
                                }
                            }
                        }
                    }
                } else if (HeroDesigner.getActiveHero().getPowers().get(i) instanceof Characteristic) {
                    CharAffectingObject power = (CharAffectingObject) HeroDesigner
                            .getActiveHero().getPowers().get(i);
                    if (power.getIncreaseLevels(getType()) > 0
                            && power.getIncrease(getType()) != 0) {
                        if (power.getAffectPrimary()
                                && CharAffectingObject.checkFigured(power, getType())
                                && power.getAffectTotal()) {
                            double mult = power.getIncreaseValue(getType(),
                                    true);
                            doubleBase += mult;
                            bonus += Rounder.roundHalfUp(mult);
                        }
                    }
                }
            }
            for (int i = 0; i < HeroDesigner.getActiveHero().getEquipment()
                    .size(); i++) {
                if (HeroDesigner.getActiveHero().getEquipment().get(i)
                        .getXMLID().equals(getXMLID())) {
                    continue; // only interested in figured
                } else if (HeroDesigner.getActiveHero().getEquipment().get(i) instanceof CompoundPower) {
                    CompoundPower cp = (CompoundPower) HeroDesigner
                            .getActiveHero().getEquipment().get(i);
                    for (int j = 0; j < cp.getPowers().size(); j++) {
                        if (cp.getPowers().get(j).getXMLID().equals(
                                getXMLID())) {
                            continue; // only interested in figured
                        } else if (cp.getPowers().get(j) instanceof Characteristic) {
                            CharAffectingObject power = (CharAffectingObject) cp
                                    .getPowers().get(j);
                            if (power.getIncreaseLevels(getType()) > 0
                                    && power.getIncrease(getType()) != 0) {
                                if (power.getAffectPrimary()
                                        && CharAffectingObject.checkFigured(power, getType())
                                        && power.getAffectTotal()) {
                                    double mult = power.getIncreaseValue(
                                            getType(), true);
                                    doubleBase += mult;
                                    bonus += Rounder.roundHalfUp(mult);
                                }
                            }
                        }
                    }
                } else if (HeroDesigner.getActiveHero().getEquipment().get(i) instanceof Characteristic) {
                    CharAffectingObject power = (CharAffectingObject) HeroDesigner
                            .getActiveHero().getEquipment().get(i);
                    if (power.getIncreaseLevels(getType()) > 0
                            && power.getIncrease(getType()) != 0) {
                        if (power.getAffectPrimary()
                                && CharAffectingObject.checkFigured(power, getType())
                                && power.getAffectTotal()) {
                            double mult = power.getIncreaseValue(getType(),
                                    true);
                            doubleBase += mult;
                            bonus += Rounder.roundHalfUp(mult);
                        }
                    }
                }
            }
        }
        if (baseLevel + bonus < maxVal) {
            baseValue = baseLevel + bonus;
        } else {
            baseValue = maxVal;
        }

        baseValueCalcTime = System.currentTimeMillis();
    }

    @Override
    void calcFiguredMinValue() {
        double bonus = 0;
        if (HeroDesigner.getActiveHero() != null) {
            baseLevel = origBaseLevel;
            doubleBase = 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.getPREIncreaseValue();
                    doubleBase += mult;
                    bonus += Rounder.roundHalfUp(mult);
                }
            }
            for (int i = 0; i < HeroDesigner.getActiveHero().getPowers().size(); i++) {
                if (HeroDesigner.getActiveHero().getPowers().get(i)
                        .getXMLID().equals(getXMLID())) {
                    continue;
                } else if (HeroDesigner.getActiveHero().getPowers().get(i) instanceof Power) {
                    CharAffectingObject power = (CharAffectingObject) HeroDesigner
                            .getActiveHero().getPowers().get(i);
                    if (power.getIncreaseLevels(getType()) > 0) {
                        if (power.getAffectPrimary() && power.getAffectTotal()) {
                            if (CharAffectingObject.checkFigured(power, getType())) {
                                double mult = power.getIncreaseValue(getType(),
                                        true);
                                doubleBase += mult;
                                bonus += Rounder.roundHalfUp(mult);
                            }
                        }
                    }
                }
            }
            for (int i = 0; i < HeroDesigner.getActiveHero().getEquipment()
                    .size(); i++) {
                if (HeroDesigner.getActiveHero().getEquipment().get(i)
                        .getXMLID().equals(getXMLID())) {
                    continue;
                } else if (HeroDesigner.getActiveHero().getEquipment().get(i) instanceof Power) {
                    CharAffectingObject power = (CharAffectingObject) HeroDesigner
                            .getActiveHero().getEquipment().get(i);
                    if (power.getIncreaseLevels(getType()) > 0) {
                        if (power.getAffectPrimary() && power.getAffectTotal()) {
                            if (CharAffectingObject.checkFigured(power, getType())) {
                                double mult = power.getIncreaseValue(getType(),
                                        true);
                                doubleBase += mult;
                                bonus += Rounder.roundHalfUp(mult);
                            }
                        }
                    }
                }
            }
        }
        if (baseLevel + bonus < maxVal) {
            figuredMinValue = baseLevel + bonus;
        } else {
            figuredMinValue = maxVal;
        }

        figuredMinValueCalcTime = System.currentTimeMillis();
    }

    @Override
    void calcNCMCharValue() {
        double bonus = getLevels() + origBaseLevel;
        if (HeroDesigner.getActiveHero() != null) {
            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.getPREIncreaseValue();
                    doubleBase += mult;
                    bonus += Rounder.roundHalfUp(mult);
                }
            }

            if (bonus < maxVal) {
                ncmCharValue = bonus;
            } else {
                ncmCharValue = maxVal;
            }

            ncmCharValueCalcTime = System.currentTimeMillis();
        }
    }

    /**
     * returns the base value plus any figured effects from other
     * Characteristics, Powers, and Equipment. Levels are not included.
     * 
     * @param figuredChar
     * @return
     */
    @Override
    public double getFiguredBaseValue(int figuredChar) {
        double bonus = 0;
        if (HeroDesigner.getActiveHero() != null) {
            baseLevel = origBaseLevel;
            doubleBase = 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
                        && CharAffectingObject.checkFigured(ch, getType())) {
                    double mult = ch.getPREIncreaseValue();
                    doubleBase += mult;
                    bonus += Rounder.roundHalfUp(mult);
                }
            }
            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()
                            && CharAffectingObject.checkFigured(power, figuredChar)) {
                        bonus += power.getLevels();
                    }
                } else if (HeroDesigner.getActiveHero().getPowers().get(i) instanceof Power) {
                    CharAffectingObject power = (CharAffectingObject) HeroDesigner
                            .getActiveHero().getPowers().get(i);
                    if (power.getIncreaseLevels(getType()) > 0) {
                        if (power.getAffectPrimary() && power.getAffectTotal()) {
                            if (CharAffectingObject.checkFigured(power, getType())) {
                                double mult = power.getIncreaseValue(getType(),
                                        true);
                                doubleBase += mult;
                                bonus += Rounder.roundHalfUp(mult);
                            }
                        }
                    }
                }
            }
            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()
                            && CharAffectingObject.checkFigured(power, figuredChar)) {
                        bonus += power.getLevels();
                    }
                } else if (HeroDesigner.getActiveHero().getEquipment().get(i) instanceof Power) {
                    CharAffectingObject power = (CharAffectingObject) HeroDesigner
                            .getActiveHero().getEquipment().get(i);
                    if (power.getIncreaseLevels(getType()) > 0) {
                        if (power.getAffectPrimary() && power.getAffectTotal()) {
                            if (CharAffectingObject.checkFigured(power, getType())) {
                                double mult = power.getIncreaseValue(getType(),
                                        true);
                                doubleBase += mult;
                                bonus += Rounder.roundHalfUp(mult);
                            }
                        }
                    }
                }
            }
        }
        if (baseLevel + bonus < maxVal) {
            return baseLevel + bonus;
        } else {
            return maxVal;
        }
    }

}