// El ejemplo de cinco tareas: el orden por plazo y los intercambios de la demostración.
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>

#include "scheduling.h"

namespace {

const std::vector<Job> JOBS = {{3, 5}, {2, 4}, {1, 7}, {4, 9}, {2, 9}};

std::string names(const std::vector<int>& order) {
    std::string text;
    for (int id : order) {
        text += static_cast<char>('A' + id);
    }
    return text;
}

void print_schedule(const std::vector<int>& order) {
    std::cout << "tarea  duración  plazo  fin  retraso\n";
    long long now = 0;
    for (int id : order) {
        const Job& job = JOBS[static_cast<std::size_t>(id)];
        now += job.duration;
        std::cout << "  " << static_cast<char>('A' + id) << std::setw(10) << job.duration << std::setw(7)
                  << job.deadline << std::setw(5) << now << std::setw(9) << now - job.deadline << '\n';
    }
    std::cout << "retraso máximo: " << max_lateness(JOBS, order) << "\n\n";
}

}  // namespace

int main() {
    std::vector<int> by_deadline = order_by_deadline(JOBS);
    print_schedule(by_deadline);
    print_schedule({1, 0, 2, 4, 3});  // D y E, con el mismo plazo, al revés

    std::vector<int> order = {3, 2, 4, 0, 1};
    std::cout << "orden  inversiones  retraso máximo  se cambia\n";
    while (true) {
        std::size_t i = first_adjacent_inversion(JOBS, order);
        std::cout << names(order) << std::setw(10) << count_inversions(JOBS, order) << std::setw(14)
                  << max_lateness(JOBS, order);
        if (i == order.size()) {
            std::cout << "          ninguna\n";
            break;
        }
        std::cout << "          " << static_cast<char>('A' + order[i]) << static_cast<char>('A' + order[i + 1]) << '\n';
        std::swap(order[i], order[i + 1]);
    }

    // Cambiar dos tareas que no son vecinas sí puede empeorar: las del medio se corren.
    const std::vector<Job> far = {{1, 5}, {1, 2}, {5, 4}};
    std::cout << "\nX(1, 5) M(1, 2) Y(5, 4)\n";
    std::cout << "orden XMY: retraso máximo " << max_lateness(far, {0, 1, 2}) << '\n';
    std::cout << "orden YMX: retraso máximo " << max_lateness(far, {2, 1, 0}) << '\n';
}
