package org.openlca.core.math;

import java.util.ArrayList;
import java.util.List;

import org.openlca.core.model.AllocationMethod;
import org.openlca.core.model.FlowPropertyFactor;
import org.openlca.core.model.ParameterRedef;
import org.openlca.core.model.ProductSystem;
import org.openlca.core.model.Unit;
import org.openlca.core.model.descriptors.ImpactMethodDescriptor;
import org.openlca.core.model.descriptors.NwSetDescriptor;

/**
 * A setup for a product system calculation.
 */
public class CalculationSetup {

	public final ProductSystem productSystem;
	public ImpactMethodDescriptor impactMethod;
	public boolean withCosts = false;
	public NwSetDescriptor nwSet;
	public AllocationMethod allocationMethod = AllocationMethod.NONE;
	public final List<ParameterRedef> parameterRedefs = new ArrayList<>();

	/** Only valid for Monte Carlo Simulations */
	public int numberOfRuns = -1;

	// properties with default values from the product system
	private Unit unit;
	private FlowPropertyFactor flowPropertyFactor;
	private Double amount;

	public CalculationSetup(ProductSystem productSystem) {
		this.productSystem = productSystem;
	}

	/**
	 * Optionally set another unit for the calculation than the one defined in
	 * the product system.
	 */
	public void setUnit(Unit unit) {
		this.unit = unit;
	}

	public Unit getUnit() {
		if (unit != null)
			return unit;
		else
			return productSystem.getTargetUnit();
	}

	/**
	 * Optionally set another flow property factor for the calculation than the
	 * one defined in the product system.
	 */
	public void setFlowPropertyFactor(FlowPropertyFactor flowPropertyFactor) {
		this.flowPropertyFactor = flowPropertyFactor;
	}

	public FlowPropertyFactor getFlowPropertyFactor() {
		if (flowPropertyFactor != null)
			return flowPropertyFactor;
		else
			return productSystem.getTargetFlowPropertyFactor();
	}

	/**
	 * Optionally set another target amount for the calculation than the one
	 * defined in the product system.
	 */
	public void setAmount(double amount) {
		this.amount = amount;
	}

	public double getAmount() {
		if (amount != null)
			return amount;
		else
			return productSystem.getTargetAmount();
	}
}

@@ -159,30 +159,106 @@
 del.Flow
-PropertyFactor
+;%0Aimport org.openlca.core.model.FlowPropertyFactor;%0Aimport org.openlca.core.model.FlowType
 ;%0Aimport
@@ -2193,54 +2193,368 @@
 ;%0A%09%09
-else%0A%09%09%09return productSystem.getTargetAmount()
+double refAmount = productSystem.getTargetAmount();%0A%09%09if (productSystem.getReferenceExchange() == null)%0A%09%09%09return refAmount;%0A%09%09Flow flow = productSystem.getReferenceExchange().getFlow();%0A%09%09if (flow != null && flow.getFlowType() == FlowType.WASTE_FLOW) %7B%0A%09%09%09// negative reference amount for waste treatment processes%0A%09%09%09return -refAmount;%0A%09%09%7D%0A%09%09return refAmount
 ;%0A%09%7D

switch sign of reference amount for waste as functional unit