#include "segment.h"

char VERSION[] = "Ford-Fulkerson algorithm with breadth-first search and beginning of "
                 "Boykof / Kolmogorov optimization, re-using previous search data\n"
                 "(V0: cut all the subtree below orphans)";

arc* get_arc(graph* G, size_t from, size_t to)
{
    UNUSED(G);
    UNUSED(from);
    UNUSED(to);
    return NULL;
}

// Pred is the spanning tree computed during the search
// Seen is the bitmap with all visited nodes
int find_path(graph* G, size_t Pred[], char Seen[], queue* todo)
{
    enqueue(todo, G->source);

    // ...
    // ...
    UNUSED(Pred);
    UNUSED(Seen);
    return 0;
}

int find_bottleneck(graph* G, const size_t Pred[])
{
    UNUSED(G);
    UNUSED(Pred);
    return 0;
}

void augment_flow(graph* G, size_t Pred[], int flow, stack* orphan)
{
    UNUSED(G);
    UNUSED(Pred);
    UNUSED(flow);
    UNUSED(orphan);
}


void update_Pred(graph* G, size_t Pred[], queue* todo, char Seen[], stack* orphan)
{
    size_t s;
    while (pop_stack(orphan, &s)) {

        for (arc* a = G->Adj[s]; a->target != NULL_NODE; a++) {
            size_t v = a->target;
            // neighboors outside the Pred forest are ignored as the find_path
            // function hasn't found them yet.
            if (Pred[v] == NULL_NODE && !Seen[v]) {
                continue;
            }

            // ...
        }

        // no more path from source to s in Pred: we'll need to find it again
        remove_from_queue(todo, s);
        Seen[s] = 0;
    }
}


int maxflow(graph* G, char Seen[])
{
    // allocate and initialize the Pred array
    size_t* Pred = malloc(G->nb_nodes * sizeof(size_t));
    for (size_t k = 0; k < G->nb_nodes; k++) {
        Pred[k] = NULL_NODE;
    }

    // allocation and initialize the todo queue
    queue* todo = new_queue();
    enqueue(todo, G->source);

    // allocate and initialize the list of orphans, ie nodes that
    // become disconnected when adding an augmenting path to the
    // flow
    stack* orphan = new_stack();

    int path_counter = 0;
    int flow_counter = 0;
    // while there are augmenting path, use them to increase the global flow
    // (Ford-Fulkerson algorithm)
    while (find_path(G, Pred, Seen, todo)) {
        path_counter += 1;
        if (VERBOSITY == 3) {
            LOG(3, ".");
        }
        // find weight of augmenting path
        int flow = find_bottleneck(G, Pred);
        flow_counter += flow;
        LOG(4, ">>>> augmenting path #%i of weight %i\n", path_counter, flow);

        // update flow with augmenting path
        augment_flow(G, Pred, flow, orphan);
        LOG(4, "     current flow is %i\n", flow_counter);

        // update Pred by updating orphans' parents
        update_Pred(G, Pred, todo, Seen, orphan);
    }
    if (VERBOSITY == 3) {
        LOG(3, "\n");
    }

    LOG(2, ">> %i augmenting path were found\n", path_counter);

    // deallocate dynamic datastructures
    free(Pred);
    free_queue(todo);
    free_stack(orphan);

    return flow_counter;
}

int main_test(graph* G, size_t argc, char* argv[])
{
    UNUSED(G);
    UNUSED(argc);
    UNUSED(argv);
    return 0;
}
// vim: textwidth=120 foldmethod=indent
