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

namespace Algorithms.Nw
{
    class PathAndCost
    {
        internal List<int> nodeIndices;
        internal double cost;

        // Constructors
        internal PathAndCost(List<int> nodeIndices, double cost)
        {
            this.nodeIndices = nodeIndices;
            this.cost = cost;
        }
        internal PathAndCost(PathAndCost rootPath, PathAndCost spurPath, Graph graph)
        {
            this.nodeIndices = new List<int>();
            this.nodeIndices.AddRange(rootPath.nodeIndices.GetRange(0, rootPath.nodeIndices.Count - 1));
            this.nodeIndices.AddRange(spurPath.nodeIndices);
            this.cost = rootPath.cost + spurPath.cost;
        }

        // Methods
        internal PathAndCost getRootPath(int nbNodes, Graph graph)
        {
            List<int> nodes = this.nodeIndices.GetRange(0, nbNodes);
            double c = 0.0;
            for (int i = 0; i < nodes.Count - 1; i++) { c += graph.getArc(nodes[i], nodes[i + 1]).getCost(); }
            return new PathAndCost(nodes, c);
        }
        internal List<int> getRootPathzzz(int nbNodes)
        {
            List<int> path = new List<int>();
            for (int i = 0; i < nbNodes; i++)
            {
                path.Add(nodeIndices[i]);
            }
            return path;
        }
        internal bool sameRootPath(PathAndCost rootPath)
        {
            for (int i = 0; i < rootPath.nodeIndices.Count; i++) { if (this.nodeIndices[i] != rootPath.nodeIndices[i]) { return false; } }
            return true;
        }
        public override bool Equals(object pathAndCost)
        {
            PathAndCost pac = (PathAndCost)pathAndCost;
            if (this.cost != pac.cost) { return false; }
            if (this.nodeIndices.Count != pac.nodeIndices.Count) { return false; }
            for (int i = 0; i < this.nodeIndices.Count; i++) { if (this.nodeIndices[i] != pac.nodeIndices[i]) { return false; } }
            return true;
        }

        internal static PathAndCost getShortestPath(Graph graph, SubGraph subGraph, ShortestPathAlgorithm spa, int s, int t)
        {
            spa.run(graph, subGraph, s, t, false);
            List<int> nodeIndices = spa.getShortestPathAsNodeIndices(s, t);
            if (nodeIndices == null) { return null; }
            return new PathAndCost(nodeIndices, spa.d[t]);
        }
    }
}
