package com.hero.objects.perks;

import java.util.ArrayList;

import org.jdom.Element;

import com.hero.HeroDesigner;
import com.hero.objects.GenericObject;
import com.hero.objects.Multipower;
import com.hero.objects.enhancers.Enhancer;
import com.hero.objects.modifiers.Modifier;
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 Favor extends Perk {

	private static String xmlID = "FAVOR";

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

	/**
	 * Favors get an override of getRealCostPreList() due to their behavior with
	 * WellConnected: A 1-pt Favor is halved in cost, giving 2 for 1 point. More
	 * than 1-pt Favor is reduced by 1-pt (as usual). This overridden method
	 * takes care of the 1/2 point.
	 */
	@Override
	public double getRealCostPreList() {
		enhancerApplied = null;
		double active = getActiveCost();
		boolean limitationsApplied = false;
		double limitationTotal = 0d;
		for (Modifier mod : assignedModifiers) {
			if (mod.getTotalValue() < 0) {
				limitationTotal += mod.getTotalValue();
				limitationsApplied = true;
			}
		}
		if (getParentList() != null) {
			ArrayList<Modifier> parentMods = getParentList()
					.getAssignedModifiers();
			LOOP: for (Modifier mod : parentMods) {
				if (mod.getTypes().contains("VPP")) {
					continue LOOP;
				}
				if (mod.getXMLID().equals("CHARGES")
						&& (getParentList() instanceof Multipower)) {
					continue LOOP;
				}
				if ((mod.getTotalValue() < 0)
						&& ((GenericObject.findObjectByID(assignedModifiers,
								mod.getXMLID()) == null)
								|| mod.getXMLID().equals("GENERIC_OBJECT") || mod
								.getXMLID().equals("CUSTOM_MODIFIER"))) {
					limitationTotal += mod.getTotalValue();
					limitationsApplied = true;
				}
			}
		}
		double ret = active / (1d + Math.abs(limitationTotal));
		if (limitationsApplied) {
			ret = Rounder.roundHalfDown(ret);
		}
		if ((getTypes() != null) && (getTypes().size() > 0)) {
			ArrayList<GenericObject> enhancers = HeroDesigner.getActiveHero()
					.getSkills();
			OUTER: for (GenericObject o : enhancers) {
				if (o instanceof Enhancer) {
					Enhancer enhancer = (Enhancer) o;
					for (String s : getTypes()) {
						if (enhancer.appliesToType(s)) {
							enhancerApplied = enhancer;
							if (!enhancer.getObjects().contains(this)) {
								enhancer.getObjects().add(this);
							}
							// just take the first match and leave it at
							// that...
							if (ret > enhancer.getCostSavings()) {
								ret -= enhancer.getCostSavings();
							} else if (ret > 0) {
								ret = ret / 2d;
							}
							break OUTER;
						}
					}
				}
			}
			enhancers = HeroDesigner.getActiveHero().getPerks();
			OUTER: for (GenericObject o : enhancers) {
				if (o instanceof Enhancer) {
					Enhancer enhancer = (Enhancer) o;
					for (String s : getTypes()) {
						if (enhancer.appliesToType(s)) {
							enhancerApplied = enhancer;
							// just take the first match and leave it at
							// that...
							if (ret > enhancer.getCostSavings()) {
								ret -= enhancer.getCostSavings();
							} else if (ret > 0) {
								ret = ret / 2d;
							}
							break OUTER;
						}
					}
				}
			}
		}

		if ((HeroDesigner.getActiveHero() != null)
				&& HeroDesigner.getActiveHero().getRules().multiplierAllowed()
				&& (getMultiplier() != 1)) {
			ret = ret * getMultiplier();
			ret = Rounder.roundHalfDown(ret);
		} else if ((HeroDesigner.getActiveHero() != null)
				&& HeroDesigner.getActiveHero().getRules().multiplierAllowed()
				&& (getParentList() != null)
				&& (getParentList().getMultiplier() != 1)) {
			ret = ret * getParentList().getMultiplier();
			ret = Rounder.roundHalfDown(ret);
		}
		if (getQuantity() > 1) {
			double q = getQuantity();
			int doublings = 0;
			while (q > 1d) {
				doublings += 1;
				q = q / 2d;
			}
			ret += doublings * 5;
		}

		return ret;
	}
}