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

namespace U.SUE.Helpers
{
    class GraphString
    {
        // from sue file
        internal static List<string> getArgsFromSueFile(string filepath)
        {
            string strSue = SueFile.getAllTextFromFile(filepath); if (strSue == null) { return null; } else if (strSue == String.Empty) { return null; }
            return Str.split(strSue, Str.Delimiter.Colon);
        }


        internal static int[] getArrInt(string str, Str.Delimiter delimiter)
        {
            str = Str.left(Str.right(str, str.Length - 1), str.Length - 2);
            return UArray.toArray(Str.toInt(Str.split(str, delimiter)));
        }
        internal static string[] getArrString(string str, Str.Delimiter delimiter)
        {
            str = Str.left(Str.right(str, str.Length - 1), str.Length - 2);
            return UArray.toArray(Str.split(str, delimiter));
        }


        // arg0
        internal static Node[] getNodes(string str)
        {
            List<string> lst = Str.split(str, Str.Delimiter.NewLine);
            lst.RemoveAt(0);
            Node[] arr = new Node[lst.Count];
            for (int i = 0; i < lst.Count; i++) { arr[i] = new Node(Str.split(lst[i], Str.Delimiter.Tab)); }
            return arr;
        }

        // arg1
        internal static Link[] getLinks(string str)
        {
            List<string> lst = Str.split(str, Str.Delimiter.NewLine);
            lst.RemoveAt(0);
            Link[] arr = new Link[lst.Count];
            for (int i = 0; i < lst.Count; i++) { arr[i] = new Link(Str.split(lst[i], Str.Delimiter.Tab)); }
            return arr;
        }

        // arg2
        internal static Path[] getPaths(string str)
        {
            List<string> lst = Str.split(str, Str.Delimiter.NewLine);
            lst.RemoveAt(0);
            Path[] arr = new Path[lst.Count];
            for (int i = 0; i < lst.Count; i++) { arr[i] = new Path(Str.split(lst[i], Str.Delimiter.Tab)); }
            return arr;
        }

        // arg3
        internal static OdPair[] getOdPairs(string str)
        {
            List<string> lst = Str.split(str, Str.Delimiter.NewLine);
            lst.RemoveAt(0);
            OdPair[] arr = new OdPair[lst.Count];
            for (int i = 0; i < lst.Count; i++) { arr[i] = new OdPair(Str.split(lst[i], Str.Delimiter.Tab)); }
            return arr;
        }



        // Back to String
        internal static string toString(Graph graph)
        {
            List<string> args = toArgs(graph);
            return /*args[0] + ":" + Environment.NewLine +//*/ args[0] + ":" + Environment.NewLine + args[1] + ":" + Environment.NewLine + args[2] + ":" + Environment.NewLine + args[3] + ":";
        }
        internal static List<string> toArgs(Graph graph)
        {
            int N = graph.getNbNodes();
            int A = graph.getNbArcs();
            int P = graph.getNbPaths();
            int O = graph.getNbOdPairs();
            List<string> args = new List<string>();

            /*
            string incidence = "incidence" + Environment.NewLine;
            string line = graph.getIncidenceMatrix()[0, 0].ToString();
            for (int j = 1; j < N; j++) { line = line + "," + graph.getIncidenceMatrix()[0, j].ToString(); }
            incidence = incidence + line;
            for (int i = 1; i < N; i++)
            {
                line = graph.getIncidenceMatrix()[i, 0].ToString();
                for (int j = 1; j < N; j++) { line = line + "," + graph.getIncidenceMatrix()[i, j].ToString(); }
                incidence = incidence + ";" + line;
            }//*/

            List<string> lst;
            
            string nodes = "nodes" + Environment.NewLine;
            if (graph.getNbNodes() > 0)
            {
                Node node = graph.getNode(0);
                lst = new List<string>()
                {
                    node.getLabel(),
                    Str.inParenthesis(Str.combine(UList.toList(node.getOutArcIndices()), Str.Delimiter.Semicolon), Str.ParenthesisTypes.Square),
                    Str.inParenthesis(Str.combine(UList.toList(node.getInArcIndices()), Str.Delimiter.Semicolon), Str.ParenthesisTypes.Square),
                    //Str.inParenthesis(Str.combine(UList.toList(node.getPathIndices()), Str.Delimiter.Semicolon), Str.ParenthesisTypes.Square),
                    //Str.inParenthesis(Str.combine(UList.toList(node.getEmanatingPathIndices()), Str.Delimiter.Semicolon), Str.ParenthesisTypes.Square),
                    //Str.inParenthesis(Str.combine(UList.toList(node.getIncomingPathIndices()), Str.Delimiter.Semicolon), Str.ParenthesisTypes.Square)
                };
                nodes = nodes + Str.combine(lst, Str.Delimiter.Tab);
                for (int i = 1; i < N; i++)
                {
                    node = graph.getNode(i);
                    lst = new List<string>()
                    {
                        node.getLabel(),
                        Str.inParenthesis(Str.combine(UList.toList(node.getOutArcIndices()), Str.Delimiter.Semicolon), Str.ParenthesisTypes.Square),
                        Str.inParenthesis(Str.combine(UList.toList(node.getInArcIndices()), Str.Delimiter.Semicolon), Str.ParenthesisTypes.Square),
                        //Str.inParenthesis(Str.combine(UList.toList(node.getPathIndices()), Str.Delimiter.Semicolon), Str.ParenthesisTypes.Square),
                        //Str.inParenthesis(Str.combine(UList.toList(node.getEmanatingPathIndices()), Str.Delimiter.Semicolon), Str.ParenthesisTypes.Square),
                        //Str.inParenthesis(Str.combine(UList.toList(node.getIncomingPathIndices()), Str.Delimiter.Semicolon), Str.ParenthesisTypes.Square)
                    };
                    nodes = nodes + Environment.NewLine + Str.combine(lst, Str.Delimiter.Tab);
                }
            }
            

            string arcs = "arcs" + Environment.NewLine;
            if (graph.getNbArcs() > 0)
            {
                Link link = graph.getLink(0);
                lst = new List<string>()
            {
                link.getFromLabel(),
                link.getToLabel(),
                link.getFromIndex().ToString(),
                link.getToIndex().ToString(),
                //Str.inParenthesis(Str.combine(UList.toList(link.getPathIndices()), Str.Delimiter.Semicolon), Str.ParenthesisTypes.Square),
                link.getFlow().ToString(),
                link.getCost().ToString(),
                link.getLinkCost().getFreeFlowTravelTime().ToString(),
                link.getLinkCost().getB().ToString(),
                link.getLinkCost().getCapacity().ToString(),
                link.getLinkCost().getPower().ToString(),
                link.getLinkCost().getToll().ToString(),
                link.getLinkCost().getTollFactor().ToString(),
                link.getLinkCost().getLength().ToString(),
                link.getLinkCost().getDistanceFactor().ToString(),
                link.getLinkCost().getExponentialCoefficient().ToString(),
                link.getCostAdd().ToString(),
                link.getCostMul().ToString()
            };
                arcs = arcs + Str.combine(lst, Str.Delimiter.Tab);
                for (int i = 1; i < A; i++)
                {
                    link = graph.getLink(i);
                    lst = new List<string>()
                    {
                        link.getFromLabel(),
                        link.getToLabel(),
                        link.getFromIndex().ToString(),
                        link.getToIndex().ToString(),
                        //Str.inParenthesis(Str.combine(UList.toList(link.getPathIndices()), Str.Delimiter.Semicolon), Str.ParenthesisTypes.Square),
                        link.getFlow().ToString(),
                        link.getCost().ToString(),
                        link.getLinkCost().getFreeFlowTravelTime().ToString(),
                        link.getLinkCost().getB().ToString(),
                        link.getLinkCost().getCapacity().ToString(),
                        link.getLinkCost().getPower().ToString(),
                        link.getLinkCost().getToll().ToString(),
                        link.getLinkCost().getTollFactor().ToString(),
                        link.getLinkCost().getLength().ToString(),
                        link.getLinkCost().getDistanceFactor().ToString(),
                        link.getLinkCost().getExponentialCoefficient().ToString(),
                        link.getCostAdd().ToString(),
                        link.getCostMul().ToString()
                    };
                    arcs = arcs + Environment.NewLine + Str.combine(lst, Str.Delimiter.Tab);
                }
            }


            string paths = "paths" + Environment.NewLine;
            if (graph.getNbPaths() > 0)
            {
                Path path = graph.getPath(0);
                lst = new List<string>()
            {
                //Str.inParenthesis(Str.combine(UList.toList(path.getNodeLabels()), Str.Delimiter.Semicolon), Str.ParenthesisTypes.Square),
                //Str.inParenthesis(Str.combine(UList.toList(path.getNodeIndices()), Str.Delimiter.Semicolon), Str.ParenthesisTypes.Square),
                Str.inParenthesis(Str.combine(UList.toList(path.getArcIndices()), Str.Delimiter.Semicolon), Str.ParenthesisTypes.Square),
                path.getFlow().ToString(),
                path.getCost().ToString(),
                path.getOdPairIndex().ToString(),
                path.getProb().ToString()
            };
                paths = paths + Str.combine(lst, Str.Delimiter.Tab);
                for (int i = 1; i < P; i++)
                {
                    path = graph.getPath(i);
                    lst = new List<string>()
                    {
                        //Str.inParenthesis(Str.combine(UList.toList(path.getNodeLabels()), Str.Delimiter.Semicolon), Str.ParenthesisTypes.Square),
                        //Str.inParenthesis(Str.combine(UList.toList(path.getNodeIndices()), Str.Delimiter.Semicolon), Str.ParenthesisTypes.Square),
                        Str.inParenthesis(Str.combine(UList.toList(path.getArcIndices()), Str.Delimiter.Semicolon), Str.ParenthesisTypes.Square),
                        path.getFlow().ToString(),
                        path.getCost().ToString(),
                        path.getOdPairIndex().ToString(),
                        path.getProb().ToString()
                    };
                    paths = paths + Environment.NewLine + Str.combine(lst, Str.Delimiter.Tab);
                }
            }
            

            string odpairs = "odpairs" + Environment.NewLine;
            if (graph.getNbOdPairs() > 0)
            {
                OdPair od = graph.getOdPair(0);
                lst = new List<string>()
                {
                    od.getOriLabel(),
                    od.getDesLabel(),
                    od.getOriIndex().ToString(),
                    od.getDesIndex().ToString(),
                    od.getDemand().ToString(),
                    "null",
                    Str.inParenthesis(Str.combine(UList.toList(od.getPathIndices()), Str.Delimiter.Semicolon), Str.ParenthesisTypes.Square)
                };
                if (od.getChoiceModel() != null) { lst[5] = od.getChoiceModel().ToString(); }
                odpairs = odpairs + Str.combine(lst, Str.Delimiter.Tab);
                for (int i = 1; i < O; i++)
                {
                    od = graph.getOdPair(i);
                    lst = new List<string>()
                    {
                        od.getOriLabel(),
                        od.getDesLabel(),
                        od.getOriIndex().ToString(),
                        od.getDesIndex().ToString(),
                        od.getDemand().ToString(),
                        "null",
                        Str.inParenthesis(Str.combine(UList.toList(od.getPathIndices()), Str.Delimiter.Semicolon), Str.ParenthesisTypes.Square)
                    };
                    if (od.getChoiceModel() != null) { lst[5] = od.getChoiceModel().ToString(); }
                    odpairs = odpairs + Environment.NewLine + Str.combine(lst, Str.Delimiter.Tab);
                }
            }
            return new List<string>() { /*incidence,//*/ nodes, arcs, paths, odpairs };
        }

        internal static string msaToString(MSA msa)
        {
            string str = "MSA" + Environment.NewLine;
            str = str + Str.combine(new List<string>() 
            { 
                msa.getStepSize().ToString(), 
                msa.getMaxNbIterations().ToString(), 
                msa.getRmseThreshold().ToString(), 
                msa.getNbIterations().ToString(), 
                msa.getSolutionMiliseconds().ToString() 
            }, Str.Delimiter.Tab);
            if (msa.getLinkFlows().Count == 0) { return str + ":"; }
            string strF = Str.combine(msa.getLinkFlows()[0], Str.Delimiter.Comma);
            for (int i = 1; i < msa.getLinkFlows().Count; i++) { strF = strF + ";" + Str.combine(msa.getLinkFlows()[i], Str.Delimiter.Comma); }
            string strRmse = Str.combine(msa.getRmse(), Str.Delimiter.Semicolon);
            return str + Environment.NewLine + strF + Environment.NewLine + strRmse + ":";
        }

    }
}
