using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using U.ListOperations;
using U.StringOperations;

namespace DiscreteChoiceModel
{
    // p(k) = CT(k).Pow{C(k) - xi, beta} / SUM{l, CT(l).Pow{C(l) - xi, beta}}
    public class Weibit : ChoiceModel
    {
        public static string abbr = "Weibit";

        private double xi;
        private double beta;
        private double[] correctionTerms;//path-size
        
        private bool useCorrectionTerms;


        // CONSTRUCTORS
        public Weibit(double xi, double beta): base(ChoiceModel.Type.Weibit)
        {
            this.xi = xi;
            this.beta = beta;
            this.useCorrectionTerms = false;
        }
        public Weibit(double xi, double beta, double[] correctionTerms): base(ChoiceModel.Type.Weibit)
        {
            this.xi = xi;
            this.beta = beta;
            this.useCorrectionTerms = true;
            this.correctionTerms = correctionTerms;
        }



        // OVERRIDE
        public override double[] calcProbabilities(double[] C)
        {
            double[] P = new double[C.Length];
            double denominator = 0.0;
            if (useCorrectionTerms)
            {
                for (int k = 0; k < C.Length; k++)
                {
                    P[k] = correctionTerms[k] * Math.Pow(C[k] - xi, -beta);
                    denominator += P[k];
                }
            }
            else
            {
                for (int k = 0; k < C.Length; k++)
                {
                    P[k] = Math.Pow(C[k] - xi, -beta);
                    denominator += P[k];
                }
            }
            for (int k = 0; k < C.Length; k++)
            {
                P[k] = P[k] / denominator;
            }
            return P;
        }


        // SETTERS
        public void setCorrectionTerms(double[] correctionTerms) { this.correctionTerms = correctionTerms; }
        public void setUseCorrectionTerms(bool useCorrectionTerms) { this.useCorrectionTerms = true; }

        // GETTERS
        public double[] getCorrectionTerms() { return this.correctionTerms; }


        // TOSTRING
        public override string ToString()
        {
            List<string> args = new List<string>() { xi.ToString(), beta.ToString() };
            if (this.correctionTerms != null) { args.Add(Str.inParenthesis(Str.combine(correctionTerms, Str.Delimiter.Semicolon), Str.ParenthesisTypes.Square)); }
            return StrFunc.getFuncString(abbr, args, CMStr.PAR, CMStr.DEL);
        }

        // CLONE
        public override ChoiceModel Clone() { return new Weibit(this.xi, this.beta, UArray.clone(this.correctionTerms)); }

    }
}
