// Dijkstra paso a paso: cómo queda d tras cada entrada, y la verdad del árbitro al lado.
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>

#include "shortest_paths.h"

int main() {
    Graph graph(6);
    add_arc(graph, 0, 1, 4);
    add_arc(graph, 0, 2, 1);
    add_arc(graph, 2, 1, 2);
    add_arc(graph, 2, 3, 7);
    add_arc(graph, 1, 3, 3);
    add_arc(graph, 3, 4, 0);
    add_arc(graph, 4, 2, 5);

    std::vector<long long> truth = relax_until_stable(graph, 0);
    DijkstraResult result = dijkstra(graph, 0);
    std::vector<long long> d(graph.size(), UNREACHABLE);
    d[0] = 0;
    std::size_t next_change = 0;
    std::cout << "sale    qué pasa      d[0] d[1] d[2] d[3] d[4] d[5]  verdad\n";
    for (std::size_t i = 0; i < result.pops.size(); i++) {
        const Pop& pop = result.pops[i];
        while (next_change < result.changes.size() && result.changes[next_change].pop == i) {
            const Change& change = result.changes[next_change];
            d[static_cast<std::size_t>(change.node)] = change.value;
            next_change++;
        }
        std::string entry = "(" + std::to_string(pop.distance) + "," + std::to_string(pop.node) + ")";
        std::cout << std::left << std::setw(8) << entry
                  << (pop.stale ? std::string("vieja       ") : "fija al " + std::to_string(pop.node) + "   ") << std::right;
        for (long long value : d) {
            std::cout << std::setw(5) << (value == UNREACHABLE ? std::string("inf") : std::to_string(value));
        }
        if (!pop.stale) {
            std::cout << std::setw(6) << truth[static_cast<std::size_t>(pop.node)];
        }
        std::cout << '\n';
    }
}
