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

namespace StatisticalDistribution
{
    class DStr
    {
        internal const Str.ParenthesisTypes PAR = Str.ParenthesisTypes.Regular;
        internal const Str.Delimiter DEL = Str.Delimiter.Comma;


        private static List<Distribution.Type> lstTypes = new List<Distribution.Type>()
        {
            Distribution.Type.Exponential,
            Distribution.Type.StandardNormal,
            Distribution.Type.Normal,
            Distribution.Type.Uniform,
            Distribution.Type.Gamma,
            Distribution.Type.ChiSquare,
            Distribution.Type.F,
            Distribution.Type.Binomial,
            Distribution.Type.Poisson,
            Distribution.Type.Geometric,
            Distribution.Type.HyperGeometric,
            Distribution.Type.Bernouilli,
            Distribution.Type.Gumbel,
            Distribution.Type.Pareto
        };

        private static List<string> lstTypeStrings = new List<string>()
        {
            ExponentialDist.abbr.ToUpper(),
            StandardNormalDist.abbr.ToUpper(),
            NormalDist.abbr.ToUpper(),
            UniformDist.abbr.ToUpper(),
            GammaDist.abbr.ToUpper(),
            "ChiSq",
            "F",
            "Bin",
            "Poisson",
            "Geom",
            "HG",
            "Bern",
            "Gum",
            "Par"
        };

        private static List<int> lstNbOfArguments = new List<int>()
        {
            2,
            0,
            2,
            2,
            2,
            -1,
            -1,
            -1,
            -1,
            -1,
            -1,
            -1,
            -1,
            -1
        };


        internal static Distribution fromString(string strDistribution)
        {
            StrFunc sf = new StrFunc(strDistribution, DStr.PAR, DStr.DEL);
            int index = lstTypeStrings.IndexOf(sf.getFuncName().ToUpper());
            if (index == -1) { throw new ArgumentException("Invalid distribution string: undefined distribution '" + strDistribution + "'."); }
            int nbArguments = lstNbOfArguments[index];
            if (nbArguments != sf.getNbArgs()) { throw new ArgumentException("Invalid distribution string, wrong number of arguments (required: " + nbArguments.ToString() + "): '" + strDistribution + "'."); }
            List<double> args = sf.getArgsDouble();
            Distribution.Type type = lstTypes[index];
            return getDist(type, args);
        }
        private static Distribution getDist(Distribution.Type type, List<double> args)
        {
            switch (type)
            {
                case Distribution.Type.Exponential: return new ExponentialDist(args[0], args[1]);
                case Distribution.Type.StandardNormal: return new StandardNormalDist();
                case Distribution.Type.Normal: return new NormalDist(args[0], args[1]);
                case Distribution.Type.Uniform: return new UniformDist(args[0], args[1]);
                case Distribution.Type.Gamma: return new GammaDist(args[0], args[1]);
                case Distribution.Type.ChiSquare: throw new NotImplementedException();
                case Distribution.Type.F: throw new NotImplementedException();
                case Distribution.Type.Binomial: throw new NotImplementedException();
                case Distribution.Type.Poisson: throw new NotImplementedException();
                case Distribution.Type.Geometric: throw new NotImplementedException();
                case Distribution.Type.HyperGeometric: throw new NotImplementedException();
                case Distribution.Type.Bernouilli: throw new NotImplementedException();
                case Distribution.Type.Gumbel: throw new NotImplementedException();
                case Distribution.Type.Pareto: throw new NotImplementedException();
                default: throw new NotImplementedException();
            }
        }

    }
}
