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 GraphInitialization
    {
        private static int N;
        private static int A;
        private static int P;

        private static List<string> nodeLabels;
        private static List<string> arcLabels;

        private static List<List<int>> nodeInArcIndices;
        private static List<List<int>> nodeOutArcIndices;
        //private static List<List<int>> nodePathIndices;
        //private static List<List<int>> nodeEmanatingPathIndices;
        //private static List<List<int>> nodeIncomingPathIndices;

        private static List<int> arcFromIndices;
        private static List<int> arcToIndices;
        //private static List<List<int>> arcPathIndices;

        private static List<List<int>> pathArcIndices;
        //private static List<List<int>> pathNodeIndices;

        internal static void initialize(Graph graph)
        {
            initializeLists(graph);

            for (int i = 0; i < N; i++)
            {
                Node node = graph.getNode(i);
                //node.setIndex(i);
            }

            for (int a = 0; a < A; a++)
            {
                Arc arc = graph.getArc(a);
                int fromIndex = nodeLabels.IndexOf(arc.getFromLabel());
                int toIndex = nodeLabels.IndexOf(arc.getToLabel());
                nodeOutArcIndices[fromIndex].Add(a);
                nodeInArcIndices[toIndex].Add(a);
                arcFromIndices[a] = fromIndex;
                arcToIndices[a] = toIndex;
            }
            for (int p = 0; p < P; p++)
            {
                /*
                Path path = graph.getPath(p);
                for (int v = 0; v < path.getNodeLabels().Length - 1; v++)
                {
                    string arcLabel = Str.combine(path.getNodeLabels()[v], path.getNodeLabels()[v + 1], Str.Delimiter.Dash);
                    int a = arcLabels.IndexOf(arcLabel);
                    //arcPathIndices[a].Add(p);
                    pathArcIndices[p].Add(a);
                }//*/
            }
            for (int p = 0; p < P; p++)
            {
                int firstArcIndex = pathArcIndices[p][0];
                int lastArcIndex = pathArcIndices[p][pathArcIndices[p].Count - 1];
                int firstNodeIndex = arcFromIndices[firstArcIndex];
                int lastNodeIndex = arcToIndices[lastArcIndex];
                //nodeEmanatingPathIndices[firstNodeIndex].Add(p);
                //nodeIncomingPathIndices[lastNodeIndex].Add(p);

                //pathNodeIndices[p].Add(arcFromIndices[pathArcIndices[p][0]]);
                //nodePathIndices[arcFromIndices[pathArcIndices[p][0]]].Add(p);
                for (int e = 0; e < pathArcIndices[p].Count; e++)
                {
                    //pathNodeIndices[p].Add(arcToIndices[pathArcIndices[e][0]]);
                    //nodePathIndices[arcToIndices[pathArcIndices[e][0]]].Add(p);
                    //pathNodeIndices[p].Add(arcToIndices[pathArcIndices[p][e]]);
                    //nodePathIndices[arcToIndices[pathArcIndices[p][e]]].Add(p);
                }
            }
            for (int n = 0; n < N; n++)
            {
                graph.getNode(n).setOutArcIndices(UArray.toArray(nodeOutArcIndices[n]));
                graph.getNode(n).setInArcIndices(UArray.toArray(nodeInArcIndices[n]));
                //graph.getNode(n).setPathIndices(UArray.toArray(nodePathIndices[n]));
                //graph.getNode(n).setEmanatingPathIndices(UArray.toArray(nodeEmanatingPathIndices[n]));
                //graph.getNode(n).setIncomingPathIndices(UArray.toArray(nodeIncomingPathIndices[n]));
            }
            for (int a = 0; a < A; a++)
            {
                graph.getArc(a).setFromIndex(arcFromIndices[a]);
                graph.getArc(a).setToIndex(arcToIndices[a]);
                //graph.getArc(a).setPathIndices(UArray.toArray(arcPathIndices[a]));
            }
            for (int p = 0; p < P; p++)
            {
                graph.getPath(p).setArcIndices(UArray.toArray(pathArcIndices[p]));
                //graph.getPath(p).setNodeIndices(UArray.toArray(pathNodeIndices[p]));
            }
            clearLists();

            // Incidence Matrix
            int[,] incidenceMatrix = UArray.sameValues<int>(-1, N, N);
            for (int a = 0; a < A; a++) { int i = graph.getArc(a).getFromIndex(); int j = graph.getArc(a).getToIndex(); incidenceMatrix[i, j] = a; }
            graph.setIncidenceMatrix(incidenceMatrix);
        }



        private static void initializeLists(Graph graph)
        {
            nodeLabels = new List<string>(); foreach (Node node in graph.getNodes()) { nodeLabels.Add(node.getLabel()); }
            arcLabels = new List<string>(); foreach (Arc arc in graph.getArcs()) { arcLabels.Add(arc.getLabel()); }

            N = graph.getNodes().Length;
            A = graph.getArcs().Length;
            P = graph.getPaths().Length;

            nodeOutArcIndices = new List<List<int>>();
            nodeInArcIndices = new List<List<int>>();
            //nodePathIndices = new List<List<int>>();
            //nodeEmanatingPathIndices = new List<List<int>>();
            //nodeIncomingPathIndices = new List<List<int>>();
            for (int i = 0; i < N; i++)
            {
                nodeOutArcIndices.Add(new List<int>());
                nodeInArcIndices.Add(new List<int>());
                //nodePathIndices.Add(new List<int>());
                //nodeEmanatingPathIndices.Add(new List<int>());
                //nodeIncomingPathIndices.Add(new List<int>());
            }

            arcFromIndices = UList.sameValues(-1, A);
            arcToIndices = UList.sameValues(-1, A);
            //arcPathIndices = new List<List<int>>();
            for (int i = 0; i < A; i++)
            {
                //arcPathIndices.Add(new List<int>());
            }

            pathArcIndices = new List<List<int>>();
            //pathNodeIndices = new List<List<int>>();
            for (int i = 0; i < P; i++)
            {
                pathArcIndices.Add(new List<int>());
                //pathNodeIndices.Add(new List<int>());
            }
        }
        private static void clearLists()
        {
            nodeLabels.Clear(); nodeLabels = null;
            arcLabels.Clear(); arcLabels = null;

            nodeInArcIndices.Clear(); nodeInArcIndices = null;
            nodeOutArcIndices.Clear(); nodeOutArcIndices = null;
            //nodePathIndices.Clear(); nodePathIndices = null;
            //nodeEmanatingPathIndices.Clear(); nodeEmanatingPathIndices = null;
            //nodeIncomingPathIndices.Clear(); nodeIncomingPathIndices = null;

            arcFromIndices.Clear(); arcFromIndices = null;
            arcToIndices.Clear(); arcToIndices = null;
            //arcPathIndices.Clear(); arcPathIndices = null;

            pathArcIndices.Clear(); pathArcIndices = null;
            //pathNodeIndices.Clear(); pathNodeIndices = null;
        }


    }
}
