/* ====================================================================
   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.eval.*;

/**
 * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
 * @author Josh Micich
 * @author Stephen Wolke (smwolke at geistig.com)
 */
public abstract class NumericFunction implements Function {

	static final double ZERO = 0.0;
	static final double TEN = 10.0;
	static final double LOG_10_TO_BASE_e = Math.log(TEN);

	protected static final double singleOperandEvaluate(ValueEval arg, int srcRowIndex, int srcColumnIndex) throws EvaluationException {
		if (arg == null) {
			throw new IllegalArgumentException("arg must not be null");
		}
		ValueEval ve = OperandResolver.getSingleValue(arg, srcRowIndex, srcColumnIndex);
		double result = OperandResolver.coerceValueToDouble(ve);
		checkValue(result);
		return result;
	}

	/**
	 * @throws EvaluationException (#NUM!) if <tt>result</tt> is <tt>NaN</> or <tt>Infinity</tt>
	 */
	public static final void checkValue(double result) throws EvaluationException {
		if (Double.isNaN(result) || Double.isInfinite(result)) {
			throw new EvaluationException(ErrorEval.NUM_ERROR);
		}
	}

	public final ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
		double result;
		try {
			result = eval(args, srcCellRow, srcCellCol);
			checkValue(result);
		} catch (EvaluationException e) {
			return e.getErrorEval();
		}
		return new NumberEval(result);
	}

	protected abstract double eval(ValueEval[] args, int srcCellRow, int srcCellCol) throws EvaluationException;

	/* -------------------------------------------------------------------------- */
	// intermediate sub-classes (one-arg, two-arg and multi-arg)

	public static abstract class OneArg extends Fixed1ArgFunction {
		protected OneArg() {
			// no fields to initialise
		}
		public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
			double result;
			try {
				double d = singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex);
				result = evaluate(d);
				checkValue(result);
			} catch (EvaluationException e) {
				return e.getErrorEval();
			}
			return new NumberEval(result);
		}
		protected final double eval(ValueEval[] args, int srcCellRow, int srcCellCol) throws EvaluationException {
			if (args.length != 1) {
				throw new EvaluationException(ErrorEval.VALUE_INVALID);
			}
			double d = singleOperandEvaluate(args[0], srcCellRow, srcCellCol);
			return evaluate(d);
		}
		protected abstract double evaluate(double d) throws EvaluationException;
	}

	public static abstract class TwoArg extends Fixed2ArgFunction {
		protected TwoArg() {
			// no fields to initialise
		}


		public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
			double result;
			try {
				double d0 = singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex);
				double d1 = singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex);
				result =  evaluate(d0, d1);
				checkValue(result);
			} catch (EvaluationException e) {
				return e.getErrorEval();
			}
			return new NumberEval(result);
		}

		protected abstract double evaluate(double d0, double d1) throws EvaluationException;
	}

	/* -------------------------------------------------------------------------- */

	public static final Function ABS = new OneArg() {
		protected double evaluate(double d) {
			return Math.abs(d);
		}
	};
	public static final Function ACOS = new OneArg() {
		protected double evaluate(double d) {
			return Math.acos(d);
		}
	};
	public static final Function ACOSH = new OneArg() {
		protected double evaluate(double d) {
			return MathX.acosh(d);
		}
	};
	public static final Function ASIN = new OneArg() {
		protected double evaluate(double d) {
			return Math.asin(d);
		}
	};
	public static final Function ASINH = new OneArg() {
		protected double evaluate(double d) {
			return MathX.asinh(d);
		}
	};
	public static final Function ATAN = new OneArg() {
		protected double evaluate(double d) {
			return Math.atan(d);
		}
	};
	public static final Function ATANH = new OneArg() {
		protected double evaluate(double d) {
			return MathX.atanh(d);
		}
	};
	public static final Function COS = new OneArg() {
		protected double evaluate(double d) {
			return Math.cos(d);
		}
	};
	public static final Function COSH = new OneArg() {
		protected double evaluate(double d) {
			return MathX.cosh(d);
		}
	};
	public static final Function DEGREES = new OneArg() {
		protected double evaluate(double d) {
			return Math.toDegrees(d);
		}
	};
	static final NumberEval DOLLAR_ARG2_DEFAULT = new NumberEval(2.0);
	public static final Function DOLLAR = new Var1or2ArgFunction() {
		public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
			return evaluate(srcRowIndex, srcColumnIndex, arg0, DOLLAR_ARG2_DEFAULT);
		}

		public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0,
				ValueEval arg1) {
			double val;
			double d1;
			try {
				val = singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex);
				d1 = singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex);
			} catch (EvaluationException e) {
				return e.getErrorEval();
			}
			// second arg converts to int by truncating toward zero
			int nPlaces = (int)d1;

			if (nPlaces > 127) {
				return ErrorEval.VALUE_INVALID;
			}


			// TODO - DOLLAR() function impl is NQR
			// result should be StringEval, with leading '$' and thousands separators
			// current junits are asserting incorrect behaviour
			return new NumberEval(val);
		}
	};
	public static final Function EXP = new OneArg() {
		protected double evaluate(double d) {
			return Math.pow(Math.E, d);
		}
	};
	public static final Function FACT = new OneArg() {
		protected double evaluate(double d) {
			return MathX.factorial((int)d);
		}
	};
	public static final Function INT = new OneArg() {
		protected double evaluate(double d) {
			return Math.round(d-0.5);
		}
	};
	public static final Function LN = new OneArg() {
		protected double evaluate(double d) {
			return Math.log(d);
		}
	};
	public static final Function LOG10 = new OneArg() {
		protected double evaluate(double d) {
			return Math.log(d) / LOG_10_TO_BASE_e;
		}
	};
	public static final Function RADIANS = new OneArg() {
		protected double evaluate(double d) {
			return Math.toRadians(d);
		}
	};
	public static final Function SIGN = new OneArg() {
		protected double evaluate(double d) {
			return MathX.sign(d);
		}
	};
	public static final Function SIN = new OneArg() {
		protected double evaluate(double d) {
			return Math.sin(d);
		}
	};
	public static final Function SINH = new OneArg() {
		protected double evaluate(double d) {
			return MathX.sinh(d);
		}
	};
	public static final Function SQRT = new OneArg() {
		protected double evaluate(double d) {
			return Math.sqrt(d);
		}
	};

	public static final Function TAN = new OneArg() {
		protected double evaluate(double d) {
			return Math.tan(d);
		}
	};
	public static final Function TANH = new OneArg() {
		protected double evaluate(double d) {
			return MathX.tanh(d);
		}
	};

	/* -------------------------------------------------------------------------- */

	public static final Function ATAN2 = new TwoArg() {
		protected double evaluate(double d0, double d1) throws EvaluationException {
			if (d0 == ZERO && d1 == ZERO) {
				throw new EvaluationException(ErrorEval.DIV_ZERO);
			}
			return Math.atan2(d1, d0);
		}
	};
	public static final Function CEILING = new TwoArg() {
		protected double evaluate(double d0, double d1) {
			return MathX.ceiling(d0, d1);
		}
	};
	public static final Function COMBIN = new TwoArg() {
		protected double evaluate(double d0, double d1) throws EvaluationException {
			if (d0 > Integer.MAX_VALUE || d1 > Integer.MAX_VALUE) {
				throw new EvaluationException(ErrorEval.NUM_ERROR);
			}
			return  MathX.nChooseK((int) d0, (int) d1);
		}
	};
	public static final Function FLOOR = new TwoArg() {
		protected double evaluate(double d0, double d1) throws EvaluationException {
			if (d1 == ZERO) {
				if (d0 == ZERO) {
					return ZERO;
				}
				throw new EvaluationException(ErrorEval.DIV_ZERO);
			}
			return MathX.floor(d0, d1);
		}
	};
	public static final Function MOD = new TwoArg() {
		protected double evaluate(double d0, double d1) throws EvaluationException {
			if (d1 == ZERO) {
				throw new EvaluationException(ErrorEval.DIV_ZERO);
			}
			return MathX.mod(d0, d1);
		}
	};
	public static final Function POWER = new TwoArg() {
		protected double evaluate(double d0, double d1) {
			return Math.pow(d0, d1);
		}
	};
	public static final Function ROUND = new TwoArg() {
		protected double evaluate(double d0, double d1) {
			return MathX.round(d0, (int)d1);
		}
	};
	public static final Function ROUNDDOWN = new TwoArg() {
		protected double evaluate(double d0, double d1) {
			return MathX.roundDown(d0, (int)d1);
		}
	};
	public static final Function ROUNDUP = new TwoArg() {
		protected double evaluate(double d0, double d1) {
			return MathX.roundUp(d0, (int)d1);
		}
	};
	static final NumberEval TRUNC_ARG2_DEFAULT = new NumberEval(0);
	public static final Function TRUNC = new Var1or2ArgFunction() {

		public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
			return evaluate(srcRowIndex, srcColumnIndex, arg0, TRUNC_ARG2_DEFAULT);
		}

		public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
			double result;
			try {
				double d0 = singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex);
				double d1 = singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex);
				double multi = Math.pow(10d,d1);
				if(d0 < 0) result = -Math.floor(-d0 * multi) / multi;
                else result = Math.floor(d0 * multi) / multi;
				checkValue(result);
			}catch (EvaluationException e) {
				return e.getErrorEval();
			}
			return new NumberEval(result);
		}
	};

	/* -------------------------------------------------------------------------- */

	private static final class Log extends Var1or2ArgFunction {
		public Log() {
			// no instance fields
		}
		public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
			double result;
			try {
				double d0 = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex);
				result = Math.log(d0) / LOG_10_TO_BASE_e;
				NumericFunction.checkValue(result);
			} catch (EvaluationException e) {
				return e.getErrorEval();
			}
			return new NumberEval(result);
		}
		public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0,
				ValueEval arg1) {
			double result;
			try {
				double d0 = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex);
				double d1 = NumericFunction.singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex);
				double logE = Math.log(d0);
				double base = d1;
				if (Double.compare(base, Math.E) == 0) {
					result = logE;
				} else {
					result = logE / Math.log(base);
				}
				NumericFunction.checkValue(result);
			} catch (EvaluationException e) {
				return e.getErrorEval();
			}
			return new NumberEval(result);
		}
	}

	public static final Function LOG = new Log();

	static final NumberEval PI_EVAL = new NumberEval(Math.PI);
	public static final Function PI = new Fixed0ArgFunction() {
		public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) {
			return PI_EVAL;
		}
	};
	public static final Function RAND = new Fixed0ArgFunction() {
		public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) {
			return new NumberEval(Math.random());
		}
	};
    public static final Function POISSON = new Fixed3ArgFunction() {

        private final static double DEFAULT_RETURN_RESULT =1;
        
        /**
         * This checks is x = 0 and the mean = 0.
         * Excel currently returns the value 1 where as the
         * maths common implementation will error.
         * @param x  The number.
         * @param mean The mean.
         * @return If a default value should be returned.
         */
        private boolean isDefaultResult(double x, double mean) {

            if ( x == 0 && mean == 0 ) {
                return true;
            }
            return false;
        }

        private boolean checkArgument(double aDouble) throws EvaluationException {

            NumericFunction.checkValue(aDouble);

            // make sure that the number is positive
            if (aDouble < 0) {
                throw new EvaluationException(ErrorEval.NUM_ERROR);
            }
            
            return true;
        }

        private double probability(int k, double lambda) {
            return Math.pow(lambda, k) * Math.exp(-lambda) / factorial(k);
        }

        private double cumulativeProbability(int x, double lambda) {
            double result = 0;
            for(int k = 0; k <= x; k++){
                result += probability(k, lambda);
            }
            return result;
        }

        /** All long-representable factorials */
        private final long[] FACTORIALS = new long[] {
                           1l,                  1l,                   2l,
                           6l,                 24l,                 120l,
                         720l,               5040l,               40320l,
                      362880l,            3628800l,            39916800l,
                   479001600l,         6227020800l,         87178291200l,
               1307674368000l,     20922789888000l,     355687428096000l,
            6402373705728000l, 121645100408832000l, 2432902008176640000l };


        public long factorial(final int n) {
            if (n < 0 || n > 20) {
                throw new IllegalArgumentException("Valid argument should be in the range [0..20]");
            }
            return FACTORIALS[n];
        }

        public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, ValueEval arg2) {

            // arguments/result for this function
            double mean=0;
            double x=0;
            boolean cumulative = ((BoolEval)arg2).getBooleanValue();
            double result=0;

            try {
				x = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex);
				mean = NumericFunction.singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex);

                // check for default result : excel implementation for 0,0
                // is different to Math Common.
                if (isDefaultResult(x,mean)) {
                    return new NumberEval(DEFAULT_RETURN_RESULT); 
                }
                // check the arguments : as per excel function def
                checkArgument(x);
                checkArgument(mean);

                // truncate x : as per excel function def
                if ( cumulative ) {
                    result = cumulativeProbability((int)x, mean);
                } else {
                    result = probability((int)x, mean);
                }

                // check the result
                NumericFunction.checkValue(result);

			} catch (EvaluationException e) {
				return e.getErrorEval();
			}
            
            return new NumberEval(result);

        }
    };
}
