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

namespace U.Graph
{
    class PathInsertion
    {
        internal static void add(Graph graph, List<List<int>> lstNodeIndices)
        {
            if (lstNodeIndices.Count == 0) { return; }

            int N = graph.getNbNodes();
            int A = graph.getNbArcs();
            int P = graph.getNbPaths();
            int[,] I = graph.getIncidenceMatrix();
            int pathIndex;
            
            // Nodes
            //List<List<int>> emanating = new List<List<int>>();
            //List<List<int>> incoming = new List<List<int>>();
            //List<List<int>> all = new List<List<int>>();
            //for (int n = 0; n < N; n++) { emanating.Add(new List<int>()); incoming.Add(new List<int>()); all.Add(new List<int>()); }
            
            // Arcs
            List<List<int>> allA = new List<List<int>>();
            for (int a = 0; a < A; a++) { allA.Add(new List<int>()); }

            Path[] newPaths = new Path[lstNodeIndices.Count];
            for (int k = 0; k < lstNodeIndices.Count; k++)
            {
                pathIndex = P + k;
                int[] nodeIndices = UArray.toArray(lstNodeIndices[k]);
                /*p*/newPaths[k] = new Path(graph, nodeIndices, 0, 0);
                //*n*/emanating[nodeIndices[0]].Add(pathIndex);
                //*n*/incoming[nodeIndices[nodeIndices.Length - 1]].Add(pathIndex);
                //*n*/foreach (int n in nodeIndices) { all[n].Add(pathIndex); }
                /*a*/for (int n = 0; n < nodeIndices.Length - 1; n++)
                {
                    int a = I[nodeIndices[n], nodeIndices[n + 1]];
                    allA[a].Add(pathIndex);
                }
            }


            // Path
            Path[] paths = graph.getPaths();
            Array.Resize(ref paths, paths.Length + newPaths.Length);
            for (int p = 0; p < newPaths.Length; p++) { paths[P + p] = newPaths[p]; }
            graph.setPaths(paths);

            // Node
            /*for (int n = 0; n < N; n++)
            {
                Node node = graph.getNode(n);
                if (emanating[n].Count > 0)
                {
                    int[] emanatingPathIndices = node.getEmanatingPathIndices();
                    int prevNb = emanatingPathIndices.Length;
                    Array.Resize(ref emanatingPathIndices, emanatingPathIndices.Length + emanating[n].Count);
                    for (int i = 0; i < emanating[n].Count; i++) { emanatingPathIndices[prevNb + i] = emanating[n][i]; }
                    node.setEmanatingPathIndices(emanatingPathIndices);
                }
                if (incoming[n].Count > 0)
                {
                    int[] incomingPathIndices = node.getIncomingPathIndices();
                    int prevNb = incomingPathIndices.Length;
                    Array.Resize(ref incomingPathIndices, incomingPathIndices.Length + incoming[n].Count);
                    for (int i = 0; i < incoming[n].Count; i++) { incomingPathIndices[prevNb + i] = incoming[n][i]; }
                    node.setIncomingPathIndices(incomingPathIndices);
                }
                if (all[n].Count > 0)
                {
                    int[] pathIndices = node.getPathIndices();
                    int prevNb = pathIndices.Length;
                    Array.Resize(ref pathIndices, pathIndices.Length + all[n].Count);
                    for (int i = 0; i < all[n].Count; i++) { pathIndices[prevNb + i] = all[n][i]; }
                    node.setPathIndices(pathIndices);
                }
            }//*/

            // Arc
            /*
            for (int a = 0; a < A; a++)
            {
                Arc arc = graph.getArc(a);
                if (allA[a].Count > 0)
                {
                    int[] pathIndices = arc.getPathIndices();
                    int prevNb = pathIndices.Length;
                    Array.Resize(ref pathIndices, pathIndices.Length + allA[a].Count);
                    for (int i = 0; i < allA[a].Count; i++) { pathIndices[prevNb + i] = allA[a][i]; }
                    arc.setPathIndices(pathIndices);
                }
            }
            //*/
            //emanating.Clear(); emanating = null;
            //incoming.Clear(); incoming = null;
            //all.Clear(); all = null;
            allA.Clear(); allA = null;
        }




        

    }
}
