package geniusweb.bidspace.pareto;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import geniusweb.issuevalue.Bid;
import geniusweb.profile.utilityspace.LinearAdditive;

/**
 * A Paretopoint is a Bid together with an N-dimensional utility vector. This is
 * also a caching mechanism to avoid repeated utility computation of good bids.
 * This is a internal utility class to streamline pareto computations.
 */
class ParetoPoint {

	private final Bid bid;
	// ArrayList is faster in indexing which is main reason for this class
	private final ArrayList<BigDecimal> utilities;

	/**
	 * 
	 * @param bid    a (possibly partial) {@link Bid}
	 * @param spaces the {@link LinearAdditive}s to consider
	 */
	public ParetoPoint(Bid bid, List<LinearAdditive> spaces) {
		this.bid = bid;
		utilities = new ArrayList<>();
		for (LinearAdditive space : spaces) {
			utilities.add(space.getUtility(bid));
		}
	}

	private ParetoPoint(List<BigDecimal> utils, Bid bid) {
		this.bid = bid;
		this.utilities = new ArrayList<>(utils);
	}

	/**
	 * Merges the issues from both bids and adds the utilities. This only works
	 * correctly if the issues in other point are completely disjoint from our
	 * bid issues.
	 * 
	 * @param otherpoint with the utils summed and the issue values merged
	 */
	public ParetoPoint merge(ParetoPoint otherpoint) {
		List<BigDecimal> summedutils = new LinkedList<>();
		for (int n = 0; n < utilities.size(); n = n + 1) {
			summedutils.add(utilities.get(n).add(otherpoint.utilities.get(n)));
		}

		return new ParetoPoint(summedutils, bid.merge(otherpoint.getBid()));
	}

	/**
	 * 
	 * @param other
	 * @return true if this ParetoPoint is dominated by the other. That means
	 *         other has better or equal utilities in ALL dimensions.
	 */
	public boolean isDominatedBy(ParetoPoint other) {
		ArrayList<BigDecimal> otherutils = other.getUtilities();
		for (int i = 0; i < utilities.size(); i = i + 1) {
			if (otherutils.get(i).compareTo(utilities.get(i)) < 0) {
				return false;
			}
		}
		return true;
	}

	protected ArrayList<BigDecimal> getUtilities() {
		return utilities;
	}

	public Bid getBid() {
		return bid;
	}

}