// El ejemplo de los apuntes: cuatro ciudades, k = 1. Los arcos del grafo de estados están
// escritos a mano y Dijkstra corre sobre ellos sin saber qué es un peaje.
#include <iostream>
#include <string>
#include <vector>

#include "shortest_paths.h"
#include "toll_mistakes.h"

namespace {

// El estado (ciudad, peajes usados) se guarda como ciudad * 2 + peajes, con k = 1.
int state(int city, int used) { return city * 2 + used; }

std::string label(int id) {
    return "(" + std::to_string(id / 2) + "," + std::to_string(id % 2) + ")";
}

}  // namespace

int main() {
    Graph layers(8);
    // Carretera 0-2 sin peaje, largo 2: una copia en cada capa, en los dos sentidos.
    for (int used = 0; used <= 1; used++) {
        add_arc(layers, state(0, used), state(2, used), 2);
        add_arc(layers, state(2, used), state(0, used), 2);
        // Carretera 2-1 sin peaje, largo 3.
        add_arc(layers, state(2, used), state(1, used), 3);
        add_arc(layers, state(1, used), state(2, used), 3);
    }
    // Carreteras 0-1 y 1-3 con peaje, largo 1: suben de la capa 0 a la capa 1.
    add_arc(layers, state(0, 0), state(1, 1), 1);
    add_arc(layers, state(1, 0), state(0, 1), 1);
    add_arc(layers, state(1, 0), state(3, 1), 1);
    add_arc(layers, state(3, 0), state(1, 1), 1);

    DijkstraResult result = dijkstra(layers, state(0, 0));
    std::cout << "estado  distancia\n";
    for (const Pop& pop : result.pops) {
        if (!pop.stale) std::cout << label(pop.node) << "    " << pop.distance << '\n';
    }
    std::cout << "a (3,0): ";
    if (result.distance[static_cast<std::size_t>(state(3, 0))] == UNREACHABLE) std::cout << "no se llega\n";
    std::cout << "a (3,1): " << result.distance[static_cast<std::size_t>(state(3, 1))] << " por";
    for (int id : path_to(result.parent, state(0, 0), state(3, 1))) std::cout << ' ' << label(id);
    std::cout << '\n';

    const std::vector<Road> roads = {{0, 2, 2, false}, {2, 1, 3, false}, {0, 1, 1, true}, {1, 3, 1, true}};
    std::cout << "contador global: " << with_global_counter(4, roads, 0, 3, 1) << '\n';
    std::cout << "una distancia por ciudad: " << with_one_distance_per_city(4, roads, 0, 3, 1) << '\n';
}
