/* ====================================================================
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
==================================================================== */

package org.apache.poi.ss.formula.functions;

import java.util.Arrays;

import org.apache.poi.ss.formula.TwoDEval;
import org.apache.poi.ss.formula.eval.AreaEval;
import org.apache.poi.ss.formula.eval.BlankEval;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.NumericValueEval;
import org.apache.poi.ss.formula.eval.RefEval;
import org.apache.poi.ss.formula.eval.StringEval;
import org.apache.poi.ss.formula.eval.ValueEval;


/**
 * Implementation for the Excel function SUMPRODUCT<p>
 *
 * Syntax : <br>
 *  SUMPRODUCT ( array1[, array2[, array3[, ...]]])
 *    <table border="0" cellpadding="1" cellspacing="0" summary="Parameter descriptions">
 *      <tr><th>array1, ... arrayN&nbsp;&nbsp;</th><td>typically area references,
 *      possibly cell references or scalar values</td></tr>
 *    </table><br>
 *
 * Let A<b>n</b><sub>(<b>i</b>,<b>j</b>)</sub> represent the element in the <b>i</b>th row <b>j</b>th column
 * of the <b>n</b>th array<br>
 * Assuming each array has the same dimensions (W, H), the result is defined as:<br>
 * SUMPRODUCT = &Sigma;<sub><b>i</b>: 1..H</sub> &nbsp;
 * 	(&nbsp; &Sigma;<sub><b>j</b>: 1..W</sub> &nbsp;
 * 	  (&nbsp; &Pi;<sub><b>n</b>: 1..N</sub>
 * 			A<b>n</b><sub>(<b>i</b>,<b>j</b>)</sub>&nbsp;
 *    )&nbsp;
 *  )
 * </p>
 * @author Josh Micich
 */
public final class Sumproduct implements Function {


	public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {

		int maxN = args.length;

		if(maxN < 1) {
			return ErrorEval.VALUE_INVALID;
		}
		ValueEval firstArg = args[0];
		try {
			if(firstArg instanceof NumericValueEval) {
				return evaluateSingleProduct(args);
			}
			if(firstArg instanceof RefEval) {
				return evaluateSingleProduct(args);
			}
			if (firstArg instanceof TwoDEval) {
				TwoDEval ae = (TwoDEval) firstArg;
				if(ae.isRow() && ae.isColumn()) {
					return evaluateSingleProduct(args);
				}
				return evaluateAreaSumProduct(args);
			}
		} catch (EvaluationException e) {
			return e.getErrorEval();
		}
		throw new RuntimeException("Invalid arg type for SUMPRODUCT: ("
				+ firstArg.getClass().getName() + ")");
	}

	private static ValueEval evaluateSingleProduct(ValueEval[] evalArgs) throws EvaluationException {
		int maxN = evalArgs.length;

		double term = 1D;
		for(int n=0; n<maxN; n++) {
			double val = getScalarValue(evalArgs[n]);
			term *= val;
		}
		return new NumberEval(term);
	}

	private static double getScalarValue(ValueEval arg) throws EvaluationException {

		ValueEval eval;
		if (arg instanceof RefEval) {
			RefEval re = (RefEval) arg;
			if (re.getNumberOfSheets() > 1) {
                throw new EvaluationException(ErrorEval.VALUE_INVALID);
			}
			eval = re.getInnerValueEval(re.getFirstSheetIndex());
		} else {
			eval = arg;
		}

		if (eval == null) {
			throw new RuntimeException("parameter may not be null");
		}
		if (eval instanceof AreaEval) {
			AreaEval ae = (AreaEval) eval;
			// an area ref can work as a scalar value if it is 1x1
			if(!ae.isColumn() || !ae.isRow()) {
				throw new EvaluationException(ErrorEval.VALUE_INVALID);
			}
			eval = ae.getRelativeValue(0, 0);
		}

		return getProductTerm(eval, true);
	}

	private static ValueEval evaluateAreaSumProduct(ValueEval[] evalArgs) throws EvaluationException {
		int maxN = evalArgs.length;
		TwoDEval[] args;
		try {
			args = Arrays.copyOf(evalArgs, maxN, TwoDEval[].class);
		} catch (ArrayStoreException e) {
			// one of the other args was not an AreaRef
			return ErrorEval.VALUE_INVALID;
		}


		TwoDEval firstArg = args[0];

		int height = firstArg.getHeight();
		int width = firstArg.getWidth(); // TODO - junit

		// first check dimensions
		if (!areasAllSameSize(args, height, width)) {
			// normally this results in #VALUE!,
			// but errors in individual cells take precedence
			for (int i = 1; i < args.length; i++) {
				throwFirstError(args[i]);
			}
			return ErrorEval.VALUE_INVALID;
		}

		double acc = 0;

		for (int rrIx=0; rrIx<height; rrIx++) {
			for (int rcIx=0; rcIx<width; rcIx++) {
				double term = 1D;
				for(int n=0; n<maxN; n++) {
					double val = getProductTerm(args[n].getValue(rrIx, rcIx), false);
					term *= val;
				}
				acc += term;
			}
		}

		return new NumberEval(acc);
	}

	private static void throwFirstError(TwoDEval areaEval) throws EvaluationException {
		int height = areaEval.getHeight();
		int width = areaEval.getWidth();
		for (int rrIx=0; rrIx<height; rrIx++) {
			for (int rcIx=0; rcIx<width; rcIx++) {
				ValueEval ve = areaEval.getValue(rrIx, rcIx);
				if (ve instanceof ErrorEval) {
					throw new EvaluationException((ErrorEval) ve);
				}
			}
		}
	}

	private static boolean areasAllSameSize(TwoDEval[] args, int height, int width) {
		for (int i = 0; i < args.length; i++) {
			TwoDEval areaEval = args[i];
			// check that height and width match
			if(areaEval.getHeight() != height) {
				return false;
			}
			if(areaEval.getWidth() != width) {
				return false;
			}
		}
		return true;
	}


	/**
	 * Determines a <code>double</code> value for the specified <code>ValueEval</code>.
	 * @param isScalarProduct <code>false</code> for SUMPRODUCTs over area refs.
	 * @throws EvaluationException if <code>ve</code> represents an error value.
	 * <p>
	 * Note - string values and empty cells are interpreted differently depending on
	 * <code>isScalarProduct</code>.  For scalar products, if any term is blank or a string, the
	 * error (#VALUE!) is raised.  For area (sum)products, if any term is blank or a string, the
	 * result is zero.
	 */
	private static double getProductTerm(ValueEval ve, boolean isScalarProduct) throws EvaluationException {

		if(ve instanceof BlankEval || ve == null) {
			// TODO - shouldn't BlankEval.INSTANCE be used always instead of null?
			// null seems to occur when the blank cell is part of an area ref (but not reliably)
			if(isScalarProduct) {
				throw new EvaluationException(ErrorEval.VALUE_INVALID);
			}
			return 0;
		}

		if(ve instanceof ErrorEval) {
			throw new EvaluationException((ErrorEval)ve);
		}
		if(ve instanceof StringEval) {
			if(isScalarProduct) {
				throw new EvaluationException(ErrorEval.VALUE_INVALID);
			}
			// Note for area SUMPRODUCTs, string values are interpreted as zero
			// even if they would parse as valid numeric values
			return 0;
		}
		if(ve instanceof NumericValueEval) {
			NumericValueEval nve = (NumericValueEval) ve;
			return nve.getNumberValue();
		}
		throw new RuntimeException("Unexpected value eval class ("
				+ ve.getClass().getName() + ")");
	}
}
