/*
 *  ====================================================================
 *    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 org.apache.poi.ss.formula.TwoDEval;
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.RefEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.formula.functions.LookupUtils.ValueVector;

/**
 * Base class for linear regression functions.
 *
 * Calculates the linear regression line that is used to predict y values from x values<br/>
 * (http://introcs.cs.princeton.edu/java/97data/LinearRegression.java.html)
 * <b>Syntax</b>:<br/>
 * <b>INTERCEPT</b>(<b>arrayX</b>, <b>arrayY</b>)<p/>
 * or
 * <b>SLOPE</b>(<b>arrayX</b>, <b>arrayY</b>)<p/>
 *
 *
 * @author Johan Karlsteen
 */
public final class LinearRegressionFunction extends Fixed2ArgFunction {
	
	private static abstract class ValueArray implements ValueVector {
		private final int _size;
		protected ValueArray(int size) {
			_size = size;
		}

		public ValueEval getItem(int index) {
			if (index < 0 || index > _size) {
				throw new IllegalArgumentException("Specified index " + index
						+ " is outside range (0.." + (_size - 1) + ")");
			}
			return getItemInternal(index);
		}
		protected abstract ValueEval getItemInternal(int index);

		public final int getSize() {
			return _size;
		}
	}

	private static final class SingleCellValueArray extends ValueArray {
		private final ValueEval _value;
		public SingleCellValueArray(ValueEval value) {
			super(1);
			_value = value;
		}

		protected ValueEval getItemInternal(int index) {
			return _value;
		}
	}

	private static final class RefValueArray extends ValueArray {
		private final RefEval _ref;
		private final int _width;
		public RefValueArray(RefEval ref) {
			super(ref.getNumberOfSheets());
			_ref = ref;
			_width = ref.getNumberOfSheets();
		}

		protected ValueEval getItemInternal(int index) {
		    int sIx = (index % _width) + _ref.getFirstSheetIndex(); 
			return _ref.getInnerValueEval(sIx);
		}
	}

	private static final class AreaValueArray extends ValueArray {
		private final TwoDEval _ae;
		private final int _width;

		public AreaValueArray(TwoDEval ae) {
			super(ae.getWidth() * ae.getHeight());
			_ae = ae;
			_width = ae.getWidth();
		}

		protected ValueEval getItemInternal(int index) {
			int rowIx = index / _width;
			int colIx = index % _width;
			return _ae.getValue(rowIx, colIx);
		}
	}

	public enum FUNCTION {INTERCEPT, SLOPE}
	public FUNCTION function;
	
	public LinearRegressionFunction(FUNCTION function) {
		this.function = function;
	}
	
	public ValueEval evaluate(int srcRowIndex, int srcColumnIndex,
			ValueEval arg0, ValueEval arg1) {
		double result;
		try {
			ValueVector vvY = createValueVector(arg0);
			ValueVector vvX = createValueVector(arg1);
			int size = vvX.getSize();
			if (size == 0 || vvY.getSize() != size) {
				return ErrorEval.NA;
			}
			result = evaluateInternal(vvX, vvY, size);
		} catch (EvaluationException e) {
			return e.getErrorEval();
		}
		if (Double.isNaN(result) || Double.isInfinite(result)) {
			return ErrorEval.NUM_ERROR;
		}
		return new NumberEval(result);
	}
	
	private double evaluateInternal(ValueVector x, ValueVector y, int size)
			throws EvaluationException {

		// error handling is as if the x is fully evaluated before y
		ErrorEval firstXerr = null;
		ErrorEval firstYerr = null;
		boolean accumlatedSome = false;
        // first pass: read in data, compute xbar and ybar
        double sumx = 0.0, sumy = 0.0;
        
		for (int i = 0; i < size; i++) {
			ValueEval vx = x.getItem(i);
			ValueEval vy = y.getItem(i);
			if (vx instanceof ErrorEval) {
				if (firstXerr == null) {
					firstXerr = (ErrorEval) vx;
					continue;
				}
			}
			if (vy instanceof ErrorEval) {
				if (firstYerr == null) {
					firstYerr = (ErrorEval) vy;
					continue;
				}
			}
			// only count pairs if both elements are numbers
			if (vx instanceof NumberEval && vy instanceof NumberEval) {
				accumlatedSome = true;
				NumberEval nx = (NumberEval) vx;
				NumberEval ny = (NumberEval) vy;
				sumx  += nx.getNumberValue();
	            sumy  += ny.getNumberValue();
			} else {
				// all other combinations of value types are silently ignored
			}
		}
		double xbar = sumx / size;
        double ybar = sumy / size;
		
		 // second pass: compute summary statistics
        double xxbar = 0.0, xybar = 0.0;
        for (int i = 0; i < size; i++) {
			ValueEval vx = x.getItem(i);
			ValueEval vy = y.getItem(i);
			
			if (vx instanceof ErrorEval) {
				if (firstXerr == null) {
					firstXerr = (ErrorEval) vx;
					continue;
				}
			}
			if (vy instanceof ErrorEval) {
				if (firstYerr == null) {
					firstYerr = (ErrorEval) vy;
					continue;
				}
			}
			
			// only count pairs if both elements are numbers
			if (vx instanceof NumberEval && vy instanceof NumberEval) {
				NumberEval nx = (NumberEval) vx;
				NumberEval ny = (NumberEval) vy;
	            xxbar += (nx.getNumberValue() - xbar) * (nx.getNumberValue() - xbar);
	            xybar += (nx.getNumberValue() - xbar) * (ny.getNumberValue() - ybar);
			} else {
				// all other combinations of value types are silently ignored
			}
        }
        double beta1 = xybar / xxbar;
        double beta0 = ybar - beta1 * xbar;
		
		if (firstXerr != null) {
			throw new EvaluationException(firstXerr);
		}
		if (firstYerr != null) {
			throw new EvaluationException(firstYerr);
		}
		if (!accumlatedSome) {
			throw new EvaluationException(ErrorEval.DIV_ZERO);
		}
		
		if(function == FUNCTION.INTERCEPT) {
			return beta0;
		} else {
			return beta1;
		}
	}

	private static ValueVector createValueVector(ValueEval arg) throws EvaluationException {
		if (arg instanceof ErrorEval) {
			throw new EvaluationException((ErrorEval) arg);
		}
		if (arg instanceof TwoDEval) {
			return new AreaValueArray((TwoDEval) arg);
		}
		if (arg instanceof RefEval) {
			return new RefValueArray((RefEval) arg);
		}
		return new SingleCellValueArray(arg);
	}
}

