#include <WFX/kernel/Kernel.h>

using namespace WFX;
using namespace WFX::lang;
using namespace WFX::kernel;

Kernel::Kernel() {
    LOG("Kernel::create");
}

Kernel::~Kernel() {
    LOG("Kernel::destroy");
}

int Kernel::exec() {
    //the game loop
    LOG("Kernel::exec()");
    while (RunningTasks.size()) {
        std::list<Task* >::iterator it, myit;
        for (it=RunningTasks.begin();it!=RunningTasks.end();) {
            Task* t = (*it);
            it++;
            if (!t->Killable) t->update();
        }
        //remove dead Tasks
        for (it=RunningTasks.begin();it!=RunningTasks.end();) {
            Task* t = (*it);
            myit = it;
            it++;
            if (t->Killable) {
                t->stop();
                RunningTasks.remove(t);
                //does not take responsibility for deleting Tasks
//                delete t;
                t = NULL;
            }
        }
    }
    LOG("Kernel::exec -> done");
    return 0;
}

bool Kernel::addTask(Task* t) {
    if (!t->start()) return false;
    insertTask(t);
    return true;
}

void Kernel::removeTask(Task* t) {
    if (std::find(RunningTasks.begin(),RunningTasks.end(),t) != RunningTasks.end()) {
        t->Killable = true;
    }
}

void Kernel::removeAllTasks() {
    std::list<Task*>::iterator it;
    for (it=RunningTasks.begin();it!=RunningTasks.end();it++) {
        (*it)->Killable = true;
    }
}

void Kernel::pauseTask(Task* t) {
    if (std::find(RunningTasks.begin(),RunningTasks.end(),t) != RunningTasks.end()) {
        t->pause();
        RunningTasks.remove(t);
        PausedTasks.push_back(t);
    }
}

void Kernel::resumeTask(Task* t) {
    if (std::find(PausedTasks.begin(),PausedTasks.end(),t) != PausedTasks.end()) {
        t->resume();
        PausedTasks.remove(t);
        insertTask(t); 
    }
}

void Kernel::insertTask(Task* t) {
    //insert task into task list - ordered by priority
    std::list<Task* >::iterator it;
    for (it=RunningTasks.begin();it!=RunningTasks.end();it++) {
        Task* cmp = (*it);
        if (cmp->Priority > t->Priority) {
            break;
        }
    }
    RunningTasks.insert(it,t);
}


