using DiscreteChoiceModel;
using StatisticalDistribution;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace U.SUE.StandardModels
{
    class MDMNorP
    {
        public static void unscaled(Graph graph)
        {
            foreach (OdPair od in graph.getOdPairs())
            {
                Distribution[] mds = new Distribution[od.getPathIndices().Length];
                double sigma = Math.PI / Math.Sqrt(6) / StaSUE.theta;
                double[] ps = od.calcPathSize(graph);
                double psSum = 0.0; foreach (double p in ps) { psSum += p; }
                if (od.getPathIndices().Length == 1) { mds[0] = new NormalDist(0.0, sigma); }
                else
                {
                    for (int k = 0; k < od.getPathIndices().Length; k++)
                    {
                        double mu = -sigma * StandardNormalDist.CdfInv(1.0 - ps[k] / psSum);
                        mds[k] = new NormalDist(mu, sigma);
                    }
                }
                MDM mdm = new MDM(mds, MDM.UtilityFunctionType.Additive, StaSUE.varEpsilon);
                od.setChoiceModel(mdm);
            }
        }


        public static void scaledScalingFactor(Graph graph)
        {
            foreach (OdPair od in graph.getOdPairs())
            {
                double spFftt = od.calcSpFFTT(graph);
                Distribution[] mds = new Distribution[od.getPathIndices().Length];
                double sigma = Math.Sqrt(StaSUE.eta * spFftt) / StaSUE.theta;
                double[] ps = od.calcPathSize(graph);
                double psSum = 0.0; foreach (double p in ps) { psSum += p; }
                if (od.getPathIndices().Length == 1) { mds[0] = new NormalDist(0.0, sigma); }
                else
                {
                    for (int k = 0; k < od.getPathIndices().Length; k++)
                    {
                        double mu = -sigma * StandardNormalDist.CdfInv(1.0 - ps[k] / psSum);
                        mds[k] = new NormalDist(mu, sigma);
                    }
                }
                MDM mdm = new MDM(mds, MDM.UtilityFunctionType.Additive, StaSUE.varEpsilon);
                od.setChoiceModel(mdm);
            }
        }
        public static void scaledScalingFactorPath(Graph graph)
        {
            foreach (OdPair od in graph.getOdPairs())
            {
                Distribution[] mds = new Distribution[od.getPathIndices().Length];
                double[] ps = od.calcPathSize(graph);
                double psSum = 0.0; foreach (double p in ps) { psSum += p; }
                if (od.getPathIndices().Length == 1) { mds[0] = new NormalDist(0.0, StaSUE.nu * graph.getPath(od.getPathIndices()[0]).calcFFTT(graph)); }
                else
                {
                    for (int k = 0; k < od.getPathIndices().Length; k++)
                    {
                        Path path = graph.getPath(od.getPathIndices()[k]);
                        double sigma = Math.Sqrt(StaSUE.eta * path.calcFFTT(graph)) / StaSUE.theta;
                        double mu = -sigma * StandardNormalDist.CdfInv(1.0 - ps[k] / psSum);
                        mds[k] = new NormalDist(mu, sigma);
                    }
                }
                MDM mdm = new MDM(mds, MDM.UtilityFunctionType.Additive, StaSUE.varEpsilon);
                od.setChoiceModel(mdm);
            }
        }


        public static void scaledCoefOfVariation(Graph graph)
        {
            foreach (OdPair od in graph.getOdPairs())
            {
                double spFftt = od.calcSpFFTT(graph);
                double sigma = StaSUE.nu * spFftt;
                Distribution[] mds = new Distribution[od.getPathIndices().Length];
                double[] ps = od.calcPathSize(graph);
                double psSum = 0.0; foreach (double p in ps) { psSum += p; }
                if (od.getPathIndices().Length == 1) { mds[0] = new NormalDist(0.0, sigma); }
                else
                {
                    for (int k = 0; k < od.getPathIndices().Length; k++)
                    {
                        double mu = -sigma * StandardNormalDist.CdfInv(1.0 - ps[k] / psSum);
                        mds[k] = new NormalDist(mu, sigma);
                    }
                }
                MDM mdm = new MDM(mds, MDM.UtilityFunctionType.Additive, StaSUE.varEpsilon);
                od.setChoiceModel(mdm);
            }
        }
        public static void scaledCoefOfVariationPath(Graph graph)
        {
            foreach (OdPair od in graph.getOdPairs())
            {
                Distribution[] mds = new Distribution[od.getPathIndices().Length];
                double[] ps = od.calcPathSize(graph);
                double psSum = 0.0; foreach (double p in ps) { psSum += p; }
                if (od.getPathIndices().Length == 1) { mds[0] = new NormalDist(0.0, StaSUE.nu * graph.getPath(od.getPathIndices()[0]).calcFFTT(graph)); }
                else
                {
                    for (int k = 0; k < od.getPathIndices().Length; k++)
                    {
                        Path path = graph.getPath(od.getPathIndices()[k]);
                        double sigma = StaSUE.nu * path.calcFFTT(graph);
                        double mu = -sigma * StandardNormalDist.CdfInv(1.0 - ps[k] / psSum);
                        mds[k] = new NormalDist(mu, sigma);
                    }
                }
                MDM mdm = new MDM(mds, MDM.UtilityFunctionType.Additive, StaSUE.varEpsilon);
                od.setChoiceModel(mdm);
            }
        }




    }
}
