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

namespace U.SUE.Algorithms.MSAClasses
{
    class BoundsForMDM
    {
        public static void set(Graph graph)
        {
            int A = graph.getLinks().Length;
            double[] linkMaxFlow = new double[A];
            double[] minCostAdd = new double[A];
            double[] maxCostAdd = new double[A];
            double[] minCostMul = new double[A];
            double[] maxCostMul = new double[A];


            foreach (OdPair od in graph.getOdPairs())
            {
                double demand = od.getDemand();
                foreach (int p in od.getPathIndices())
                {
                    Path path = graph.getPath(p);
                    foreach (int a in path.getArcIndices())
                    {
                        linkMaxFlow[a] += demand;
                    }
                }
            }
            for (int a = 0; a < A; a++)
            {
                Link link = graph.getLink(a);
                minCostAdd[a] = link.getLinkCost().getBPRCost(0.0);
                maxCostAdd[a] = link.getLinkCost().getBPRCost(linkMaxFlow[a]);
                minCostMul[a] = link.getLinkCost().getBPRCostExponential(0.0);
                maxCostMul[a] = link.getLinkCost().getBPRCostExponential(linkMaxFlow[a]);
            }
            foreach (OdPair od in graph.getOdPairs())
            {
                if (od.getChoiceModel() != null)
                {
                    if (od.getChoiceModel().getType() == DiscreteChoiceModel.ChoiceModel.Type.MDM)
                    {
                        MDM mdm = (MDM)od.getChoiceModel();
                        double maxC = double.MinValue;
                        double minC = double.MaxValue;
                        PathCost.Type costType = PathCost.getType(od.getChoiceModel());
                        if (costType == PathCost.Type.ADD)
                        {
                            foreach (int p in od.getPathIndices())
                            {
                                Path path = graph.getPath(p);
                                double pathCostMax = 0.0;
                                double pathCostMin = 0.0;
                                foreach (int a in path.getArcIndices())
                                {
                                    pathCostMax += maxCostAdd[a];
                                    pathCostMin += minCostAdd[a];
                                }
                                maxC = Math.Max(maxC, pathCostMax);
                                minC = Math.Min(minC, pathCostMin);
                            }
                            mdm.setMinMaxV(-maxC, -minC);
                        }
                        else if (costType == PathCost.Type.MUL)
                        {
                            foreach (int p in od.getPathIndices())
                            {
                                Path path = graph.getPath(p);
                                double pathCostMax = 1.0;
                                double pathCostMin = 1.0;
                                foreach (int a in path.getArcIndices())
                                {
                                    pathCostMax *= maxCostMul[a];
                                    pathCostMin *= minCostMul[a];
                                }
                                maxC = Math.Max(maxC, pathCostMax);
                                minC = Math.Min(minC, pathCostMin);
                            }
                            mdm.setMinMaxV(minC, maxC);
                        }
                    }
                }
                
            }

        }


    }
}
