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

namespace DiscreteChoiceModel
{
    public class Deterministic : ChoiceModel
    {
        public static string abbr = "Det";

        private bool maximizeUtility;

        // CONSTRUCTORS
        public Deterministic(bool maximizeUtility) : base(ChoiceModel.Type.Deterministic)
        {
            this.maximizeUtility = maximizeUtility;
        }


        // OVERRIDE
        public override double[] calcProbabilities(double[] utilityFunctionParameters)
        {
            if (maximizeUtility) { return calcProbsUtility(utilityFunctionParameters); }
            else { return calcProbsDisutility(utilityFunctionParameters); }
        }


        // TOSTRING
        public override string ToString()
        {
            string maxString = "min"; if (maximizeUtility) { maxString = "max"; }
            return StrFunc.getFuncString(abbr, new List<string>() { maxString }, CMStr.PAR, CMStr.DEL);
        }
        // CLONE
        public override ChoiceModel Clone() { return new Deterministic(this.maximizeUtility); }


        // Private
        private double[] calcProbsUtility(double[] V)
        {
            double[] P = UArray.sameValues(0.0, V.Length);
            double max = double.MinValue;
            List<int> maxIndices = new List<int>();
            for (int k = 0; k < V.Length; k++)
            {
                if (V[k] > max)
                {
                    max = V[k];
                    maxIndices = new List<int>() { k };
                }
                else if (V[k] == max)
                {
                    maxIndices.Add(k);
                }
            }
            for (int i = 0; i < maxIndices.Count; i++)
            {
                P[maxIndices[i]] = 1.0 / maxIndices.Count;
            }
            maxIndices.Clear(); maxIndices = null;
            return P;
        }
        private double[] calcProbsDisutility(double[] V)
        {
            double[] P = UArray.sameValues(0.0, V.Length);
            double min = double.MaxValue;
            List<int> minIndices = new List<int>();
            for (int k = 0; k < V.Length; k++)
            {
                if (V[k] < min)
                {
                    min = V[k];
                    minIndices = new List<int>() { k };
                }
                else if (V[k] == min)
                {
                    minIndices.Add(k);
                }
            }
            for (int i = 0; i < minIndices.Count; i++)
            {
                P[minIndices[i]] = 1.0 / minIndices.Count;
            }
            minIndices.Clear(); minIndices = null;
            return P;
        }
    }
}
