using Algorithms.Nw.ShortestPath;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using U.SUE;

namespace Algorithms.Nw
{
    public class LinkElimination : PathGenerationAlgorithm
    {
        private int pathLimit;
        private ShortestPathAlgorithm spa;

        public LinkElimination(int pathLimit, ShortestPathAlgorithm shortestPathAlgorithm, bool keepExistingPaths)
            : base(keepExistingPaths)
        {
            this.pathLimit = pathLimit;
            this.spa = shortestPathAlgorithm;
        }

        public override void generate(Graph graph, bool keepTime, bool performPathAttributeCalculations)
        {
            /*
            if (pathLimit < 1) { return; }
            graph.updateAdditiveEdgeCosts();
            if (keepTime) { base.startTimer(); }
            OdPair[] odArray = graph.getOds().getArray();
            int V = graph.getNbVertices();
            SubGraph subGraph = new SubGraph(V);
            foreach (OdPair od in odArray)
            {
                bool cs = true;
                subGraph.restore();
                List<List<int>> pathsAsVertices = new List<List<int>>();
                if (base.doKeepExistingPaths())
                {
                    pathsAsVertices = graph.getOdPathsList(od, Path.RepresentationType.VertexIndices);
                    foreach (List<int> vertexIds in pathsAsVertices) { subGraph.closePath(vertexIds); }
                }
                int s = od.getOriginIndex();
                int t = od.getDestIndex();
                this.spa.calculate(graph, subGraph, s, t, false);
                List<int> spAsVertices0 = this.spa.getShortestPathAsVertexIndices(s, t);
                if (spAsVertices0 == null) { cs = false; }
                else
                {
                    pathsAsVertices.Add(spAsVertices0);
                    subGraph.closePath(pathsAsVertices[0]);
                }
                while (pathsAsVertices.Count < pathLimit && cs)
                {
                    this.spa.calculate(graph, subGraph, s, t, false);
                    List<int> spAsVertices = this.spa.getShortestPathAsVertexIndices(s, t);
                    if (spAsVertices == null) { cs = false; }
                    else
                    {
                        pathsAsVertices.Add(spAsVertices);
                        subGraph.closePath(pathsAsVertices[pathsAsVertices.Count - 1]);
                    }
                }
                updatePaths(graph, od, pathsAsVertices);
            }
            if (keepTime) { base.stopTimer(); }
            if (performPathAttributeCalculations) { graph.performPathAttributeCalculations(); }//*/
        }


        private void updatePaths(Graph graph, OdPair od, List<List<int>> pathsAsVertices)
        {
            /*
            Path[] pathArray = new Path[pathsAsVertices.Count];
            Vertices vertices = graph.getVertices();
            for (int p = 0; p < pathsAsVertices.Count; p++)
            {
                List<int> vertexIds = pathsAsVertices[p];
                int originIndex = vertexIds[0];
                int destIndex = vertexIds[vertexIds.Count - 1];
                int[] edgeIndices = new int[vertexIds.Count - 1];
                for (int i = 1; i < vertexIds.Count; i++)
                {
                    int ori = vertexIds[i - 1];
                    int des = vertexIds[i];
                    int edgeIndex = graph.getEdge(ori, des).getIndex();
                    edgeIndices[i - 1] = edgeIndex;
                }
                pathArray[p] = new Path(edgeIndices, originIndex, destIndex);
            }
            od.setPaths(new Paths(pathArray));//*/
        }

    }
}
