#include "Tour.h"




void Tour::updateCostAndDemand(const Instance& instance)
{
    demand = 0;
    costs = 0;

    if (nodes.size() > 0) {
        costs += instance.distanceMatrix[0][nodes[0]];
        demand += instance.demand[nodes[0]];

        // Add the cost of traveling between customers in the tour
        for (int j = 0; j < nodes.size() - 1; ++j) {
            costs += instance.distanceMatrix[nodes[j]][nodes[j + 1]];
            demand += instance.demand[nodes[j + 1]];
        }

        costs += instance.distanceMatrix[nodes.back()][0];
    }

}


void Tour::stringRemoval(std::vector<int>& removed_cust, Tour& newTour, int lt, int c_star) {
    auto it = std::find(nodes.begin(), nodes.end(), c_star);
    int ctStarIdx = std::distance(nodes.begin(), it);

    // Define min and max index ranges for removal
    // Start at 1 since node 0 is the depot
    int minIdx = std::max(0, ctStarIdx - lt);
    int maxIdx = std::min(ctStarIdx, (int)nodes.size() - lt);


    int start = getRandomNumber(minIdx, maxIdx);

    // Extract the removed customers
    removed_cust.assign(nodes.begin() + start, nodes.begin() + start + lt);

    // Create a ruined tour by excluding removed customers
    newTour.nodes = std::vector<int>();
    std::copy_if(nodes.begin(), nodes.end(), std::back_inserter(newTour.nodes),
        [&](int cust) { return std::find(removed_cust.begin(), removed_cust.end(), cust) == removed_cust.end(); });

}


void Tour::splitStringRemoval(std::vector<int>& removed_cust, Tour& newTour, int lt, int c_star, float alpha) {
    auto it = std::find(nodes.begin(), nodes.end(), c_star);
    int ctStarIdx = std::distance(nodes.begin(), it);

    int m_max = nodes.size() - lt;

    int m = 1;

    while (getRandomFraction() > alpha && m < m_max) {
        m += 1;
    }


    int lt_m = lt + m;

    // Define min and max index ranges for removal
    int minIdx = std::max(0, ctStarIdx - lt_m);
    int maxIdx = std::min(ctStarIdx, (int)nodes.size() - lt_m);


    int start = getRandomNumber(minIdx, maxIdx);

    int preserve_start = (int)(start + lt / 2.0); //getRandomNumber(start + 1, start + lt - 1);

    // Extract the removed customers
    removed_cust.assign(nodes.begin() + start, nodes.begin() + preserve_start);
    removed_cust.insert(removed_cust.end(), nodes.begin() + preserve_start + m, nodes.begin() + start + lt_m);

    // Create a ruined tour by excluding removed customers
    newTour.nodes = std::vector<int>();
    std::copy_if(nodes.begin(), nodes.end(), std::back_inserter(newTour.nodes),
        [&](int cust) { return std::find(removed_cust.begin(), removed_cust.end(), cust) == removed_cust.end(); });

}


