/**
 ********************************************************************************
 * Copyright (c) 2020 Robert Bosch GmbH and others.
 *
 * This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License 2.0
 * which is available at https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Robert Bosch GmbH - initial API and implementation
 ********************************************************************************
 */

package org.eclipse.app4mc.amalthea.model.util;

import org.apache.commons.math3.distribution.WeibullDistribution;
import org.apache.commons.math3.special.Gamma;

/**
 * @author mlh2sh
 *
 */
public class WeibullUtil {

	private static final String NO_VALID_WEIBULL_DISTRIBUTION_FOUND = "invalid argument: there is no valid weibull distribution for the used parameter";

	// Suppress default constructor
	private WeibullUtil() {
		throw new IllegalStateException("Utility class");
	}

	public static class Parameters {
		public double given_lowerBound = 0.0;
		public double given_upperBound = 0.0;
		public double requested_mean = 0.0;
		public double requested_pRemainPromille = 0.0;

		public double shape = 1.0;
		public double scale = 1.0;

		public String error = null;

		@Override
		public String toString() {
			String output = "WeibullParam"
					+ "\n  shape = " + shape
					+ "\n  scale = " + scale
					+ "\n  lowerBound      = " + given_lowerBound
					+ "\n  upperBound      = " + given_upperBound
					+ "\n  mean            = " + requested_mean
					+ "\n  pRemainPromille = " + requested_pRemainPromille;
			if (error != null) {
				output = output + "\n  *** error *** : " + error;
			}
			return output;
		}

		public String qualityReport() {
			// check with Apache Commons Math
			final WeibullDistribution mathFunction = new WeibullDistribution(null, shape, scale);
			double cdfAvg = mathFunction.cumulativeProbability(requested_mean - given_lowerBound);
			double cdfMax = mathFunction.cumulativeProbability(given_upperBound - given_lowerBound);
			double remPromilleC = (1.0 - cdfMax) * 1000.0;
			double averageC = WeibullUtil.computeAverage(shape, scale, given_lowerBound, given_upperBound);
			double medianC = WeibullUtil.computeMedian(shape, scale, given_lowerBound, given_upperBound);
			return "Weibull Parameter Quality"
				+ "\nInput: [" + given_lowerBound + ", " + requested_mean + ", " + given_upperBound + "], " + requested_pRemainPromille
				+ "\nEstimated parameters: shape = " + shape + "\tscale = " + scale
				+ "\n computed average: " + averageC
				+ "\n computed median: " + medianC
				+ "\n computed pRemainPromille: " + remPromilleC
				+ "\n computed cdf(lower interval) = " + cdfAvg
				+ "\n computed cdf(upper interval) = " + (cdfMax - cdfAvg);
		}
	}

	/**
	 * See Crénin, François, Truncated Weibull Distribution Functions and Moments (October 30, 2015).
	 * Available at SSRN: https://ssrn.com/abstract=2690255 or http://dx.doi.org/10.2139/ssrn.2690255
	 *
	 * @param shape
	 * @param scale
	 * @param location
	 * @param upperBound
	 * @return
	 */
	public static double computeAverage(double shape, double scale, double location, Double upperBound) {
		if (shape <= 0.0 || scale <= 0.0) return Double.NaN;

		if (upperBound == null || upperBound.isNaN() || upperBound.isInfinite()) {
			// Standard Weibull distribution
			return location + scale * Gamma.gamma(1 + 1 / shape);

		} else if (location < upperBound) {
			// Right truncated Weibull distribution
			final double range = upperBound - location;
			final double power = Math.pow(range / scale, shape);
			double factor1 = scale / (1 - Math.exp(-1.0 * power));
			double factor2 = lowerIncompleteGammaFunction(1 + 1 / shape, power);
			return location + factor1 * factor2;
		}

		return Double.NaN;
	}

	/**
	 * See https://en.wikipedia.org/wiki/Incomplete_gamma_function
	 *
	 * @param s
	 * @param x
	 * @return
	 */
	private static double lowerIncompleteGammaFunction(double s, double x) {
		return Gamma.regularizedGammaP(s, x) * Gamma.gamma(s);
	}

	public static double computeMedian(double shape, double scale, double location, Double upperBound) {
		double pRemainPromille;
		if (upperBound == null || upperBound.isNaN() || upperBound.isInfinite()) {
			pRemainPromille = 0.0;
		} else {
			pRemainPromille = computePRemainPromille(shape, scale, location, upperBound);
		}

		return computeMedianWithPRemainPromille(shape, scale, location, pRemainPromille);
	}

	public static double computeMedianWithPRemainPromille(double shape, double scale, double location, double pRemainPromille) {
		if (shape <= 0.0 || scale <= 0.0 || pRemainPromille < 0 || pRemainPromille >= 1000) return Double.NaN;

		double x = scale * Math.pow(-1.0 * Math.log(0.5 + pRemainPromille / 2000.0), 1 / shape);
		return location + x;
	}

	public static double computePRemainPromille(double shape, double scale, double location, double upperBound) {
		if (shape <= 0.0 || scale <= 0.0) return Double.NaN;

		if (location < upperBound) {
			// Compute CDF at upper bound; pRemainPromille = (1 - CDF) * 1000
			final double range = upperBound - location;
			final double power = Math.pow(range / scale, shape);
			return Math.exp(-1.0 * power) * 1000.0;
		}

		return Double.NaN;
	}

	public static double computeUpperBound(double shape, double scale, double location, double pRemainPromille) {
		if (shape <= 0.0 || scale <= 0.0) return Double.NaN;

		double pRemain = pRemainPromille / 1000.0;
		if (pRemain > 0 && pRemain < 1) {
			// Compute CDF at upper bound; pRemain = (1 - CDF)
			return location + Math.pow(-1.0 * Math.log(pRemain), 1.0 / shape) * scale;
		}

		return Double.NaN;
	}

	/**
	 * This is a simple attempt to get a better parameter estimation for big pRemainPromille values.
	 *
	 * As an alternative to the regular estimation another estimation based on the median value is calculated.
	 * The better result is selected according to the relative error of both requested values.
	 *
	 * Better solutions are welcome !
	 *
	 * @param lowerBound
	 * @param average
	 * @param upperBound
	 * @param pRemainPromille
	 * @return
	 */
	public static Parameters findParameters(double lowerBound, double average, double upperBound, double pRemainPromille) {
		Parameters p1 = findParametersForAverage(lowerBound, average, upperBound, pRemainPromille);
		Parameters p2 = findParametersForMedian(lowerBound, average, upperBound, pRemainPromille);

		if (p2.error != null) return p1;

		// compute resulting values for estimated parameters

		double p1_average = computeAverage(p1.shape, p1.scale, lowerBound, upperBound);
		double p1_pRemainPromille = computePRemainPromille(p1.shape, p1.scale, lowerBound, upperBound);
		double p2_average = computeAverage(p2.shape, p2.scale, lowerBound, upperBound);
		double p2_pRemainPromille = computePRemainPromille(p2.shape, p2.scale, lowerBound, upperBound);

		// find the better one

		double error1 = Math.abs(1.0 - p1_average / average) + Math.abs(1.0 - p1_pRemainPromille / pRemainPromille);
		double error2 = Math.abs(1.0 - p2_average / average) + Math.abs(1.0 - p2_pRemainPromille / pRemainPromille);
		if (error2 < error1) return p2;

		return p1;
	}

	/**
	 * The approximation from the given parameters boil down to the following problem (latex formulas):
	 * <p>
	 * CDF_{weibull}(upperBound) = 1 - pRemainPromille/1000
	 * <p>
	 * Using the Weibull CDF (1) and the Expectation Value (average) (2)
	 * we can derive a formula for the scale dependent on shape and known values from (2)
	 * <p>
	 * (1) CDF_{weibull}(x) = 1 - e^{- (\frac{x}{scale})^{shape}}
	 * <p>
	 * (2) avg = scale \cdot \Gamma(1 + \frac{1}{shape})
	 * <p>
	 * (3) scale = \frac{avg}{\Gamma(1 + (1 / shape))}
	 * <p>
	 * with (1), (3) and pRemain = pRemainPromille/1000 follows
	 * <p>
	 * (4) pRemain = e^{-(\frac{upper limit}{E_{avg}} \cdot \Gamma(1 + \frac{1}{shape}))^{shape}}
	 * <p>
	 * from this we form a zero finding problem
	 * <p>
	 * (5) 0 = e^{-(\frac{upper limit}{E_{avg}}\cdot \Gamma(1 + \frac{1}{shape}))^{shape}} - pRemain
	 * <p>
	 * The work "Robust Scheduling of Real-Time Applications on Efficient Embedded Multicore Systems"
	 * (https://mediatum.ub.tum.de/download/1063381/1063381.pdf) proposes an algorithm from (4) which
	 * is basically the bisection method.
	 */
	public static Parameters findParametersForAverage(double lowerBound, double average, double upperBound, double pRemainPromille) {
		Parameters result = new Parameters();
		result.shape = 1;
		result.scale = 1;
		result.requested_pRemainPromille = pRemainPromille;

		result.given_lowerBound = lowerBound;
		result.requested_mean = average;
		result.given_upperBound = upperBound;

		// shifted values for standard 2 parameter Weibull distribution
		double avg = average - lowerBound;
		double max = upperBound - lowerBound;
		double pRemain = pRemainPromille / 1000;

		if ((max / avg) > 10000) {
			result.error = "finding: upper bound and mean have no valid value for parameter";
			return result;
		}

		if (pRemain > 1) {
			result.error = "invalid_argument: pRemainPromille needs to be smaller than 1";
			return result;
		}

		/* find zero interval */
		double right = 0.2;
		double left = 0.1;
		double right_f = paramZeroFunctionforAverage(right, avg, max, pRemain);
		double left_f = paramZeroFunctionforAverage(left, avg, max, pRemain);
		while ((right_f > 0 || left_f < 0) && right < 1000 && (pRemain + right_f) > 0) {
			left = right;
			right = right + Math.max((0.1 * right), 0.1);
			right_f = paramZeroFunctionforAverage(right, avg, max, pRemain);
			left_f = paramZeroFunctionforAverage(left, avg, max, pRemain);
		}
		if (right_f > 0 && left_f < 0) {
			result.error = NO_VALID_WEIBULL_DISTRIBUTION_FOUND;
			return result;
		}

		// if we found the exact solution on one of the interval borders, return it
		if (left_f == 0) {
			right = left;
			right_f = left_f;
		}

		if (right_f == 0) {
			result.shape = right;
			result.scale = computeScaleForAverage(result.shape, avg);
			return result;
		}

		while (true) {
			double half = left + (right - left) / 2;
			double half_f = paramZeroFunctionforAverage(half, avg, max, pRemain);
			// found solution
			if (half_f == 0.0 || left == right || half == right || half == left) {
				result.shape = half;
				result.scale = computeScaleForAverage(result.shape, avg);
				return result;
			} else {
				if (Math.signum(1.0) == Math.signum(half_f)) {
					left = half;
				} else {
					right = half;
				}
			}
			if (!Double.isFinite(left) || !Double.isFinite(right) || !Double.isFinite(half_f)) {
				result.error = NO_VALID_WEIBULL_DISTRIBUTION_FOUND;
				return result;
			}
		}
	}

	private static double paramZeroFunctionforAverage(double shape, double avg, double max, double pRemain) {
		return 1 / Math.exp(Math.pow((max / avg) * Gamma.gamma(1 + 1 / shape), shape)) - pRemain;
	}

	private static double computeScaleForAverage(double shape, double avg) {
		return avg / (Gamma.gamma(1 + (1 / shape)));
	}

	public static Parameters findParametersForMedian(double lowerBound, double median, double upperBound, double pRemainPromille) {
		Parameters result = new Parameters();
		result.shape = 1;
		result.scale = 1;
		result.requested_pRemainPromille = pRemainPromille;

		result.given_lowerBound = lowerBound;
		result.requested_mean = median;
		result.given_upperBound = upperBound;

		// shifted values for standard 2 parameter Weibull distribution
		double med = median - lowerBound;
		double max = upperBound - lowerBound;
		double pRemain = pRemainPromille / 1000;

		if ((max / med) > 10000) {
			result.error = "finding: upper bound and mean have no valid value for parameter";
			return result;
		}

		if (pRemain > 1) {
			result.error = "invalid_argument: pRemainPromille needs to be smaller than 1";
			return result;
		}

		/* find zero interval */
		double right = 0.2;
		double left = 0.1;
		double right_f = paramZeroFunctionForMedian(right, med, max, pRemain);
		double left_f = paramZeroFunctionForMedian(left, med, max, pRemain);
		while ((right_f > 0 || left_f < 0) && right < 1000 && (pRemain + right_f) > 0) {
			left = right;
			right = right + Math.max((0.1 * right), 0.1);
			right_f = paramZeroFunctionForMedian(right, med, max, pRemain);
			left_f = paramZeroFunctionForMedian(left, med, max, pRemain);
		}
		if (right_f > 0 && left_f < 0) {
			result.error = NO_VALID_WEIBULL_DISTRIBUTION_FOUND;
			return result;
		}

		// if we found the exact solution on one of the interval borders, return it
		if (left_f == 0) {
			right = left;
			right_f = left_f;
		}

		if (right_f == 0) {
			result.shape = right;
			result.scale = computeScaleForMedian(result.shape, med, pRemain);
			return result;
		}

		while (true) {
			double half = left + (right - left) / 2;
			double half_f = paramZeroFunctionForMedian(half, med, max, pRemain);
			// found solution
			if (half_f == 0.0 || left == right || half == right || half == left) {
				result.shape = half;
				result.scale = computeScaleForMedian(result.shape, med, pRemain);
				return result;
			} else {
				if (Math.signum(1.0) == Math.signum(half_f)) {
					left = half;
				} else {
					right = half;
				}
			}
			if (!Double.isFinite(left) || !Double.isFinite(right) || !Double.isFinite(half_f)) {
				result.error = NO_VALID_WEIBULL_DISTRIBUTION_FOUND;
				return result;
			}
		}
	}

	private static double paramZeroFunctionForMedian(double shape, double median, double max, double pRemain) {
		double factor1 = max / median;
		double factor2 = Math.pow(-1.0 * Math.log(0.5 + pRemain / 2.0), 1 / shape);
		return 1.0 / Math.exp(Math.pow(factor1 * factor2, shape)) - pRemain;
	}

	private static double computeScaleForMedian(double shape, double median, double pRemain) {
		return median / Math.pow(-1.0 * Math.log(0.5 + pRemain / 2.0), 1 / shape);
	}

}
