#include <QTextEdit>
#include <QHBoxLayout>
#include <set>
#include <stack>
#include "plugin/Plugin.hpp"
#include "trace/EntityTypes.hpp"
#include "trace/EntityValue.hpp"
#include "trace/Entitys.hpp"
#include "trace/Container.hpp"
#include "trace/tree/Node.hpp"
#include "trace/tree/BinaryTree.hpp"
#include "trace/Trace.hpp"
#include "TraceInfos.hpp"

using namespace std;

Trace_infos::Trace_infos() {
    QHBoxLayout *horizontalLayout = new QHBoxLayout(this);
    _text_info = new QTextEdit();
    horizontalLayout->addWidget(_text_info);
}

Trace_infos::~Trace_infos() {
}

void Trace_infos::set_container_infos(QString &text) const {
    /* count */
    list <Container *> container_list;
    _trace->get_all_containers(container_list);

    text += "<h2>Containers:</h2>";
    text += QString("count: %1").arg(container_list.size());
}

void Trace_infos::set_states_infos(QString &text) const {

    list <Container *> container_list;
    BinaryTree<StateChange> *states;
    _trace->get_all_containers(container_list);

    set<string> state_list;

    for(list<Container *>::const_iterator it = container_list.begin();
        it != container_list.end();
        ++ it) {
        states = (*it)->get_states();
        if(states && states->get_root()) {
            get_states_name_rec(states->get_root(), state_list);
        }
    }

    text += "<h2>States:</h2>";
    text += QString("count: %1").arg(state_list.size());
}

void Trace_infos::get_states_name_rec(Node<StateChange> *parent, set<string> &state_list) const {

    if(!parent)
        return;
    const StateChange *top_state = parent->get_element();
    const State *left_state = top_state->get_left_state();
    const State *right_state = top_state->get_right_state();
    if(left_state && left_state->get_value()) {
        state_list.insert(left_state->get_value()->get_name());
        //cout << left_state->get_value()->get_name() << endl;
        get_states_name_rec(parent->get_left_child(), state_list);
    }
    if(right_state && right_state->get_value()) {
        state_list.insert(right_state->get_value()->get_name());
        //cout << right_state->get_value()->get_name() << endl;
        get_states_name_rec(parent->get_right_child(), state_list);
    }
}

void Trace_infos::set_events_infos(QString &text) const {
    /* count */
    int count = 0;
    list <Container *> container_list;
    _trace->get_all_containers(container_list);

    for(list<Container *>::const_iterator it = container_list.begin();
        it != container_list.end();
        ++ it) {
        count += (*it)->get_event_number();
    }
    text += "<h2>Events:</h2>";
    text += QString("count: %1").arg(count);
}

void Trace_infos::set_variables_infos(QString &text) const {
    /* count */
    int count = 0;
    list <Container *> container_list;
    _trace->get_all_containers(container_list);

    for(list<Container *>::const_iterator it = container_list.begin();
        it != container_list.end();
        ++ it) {
        count += (*it)->get_variable_number();
    }
    text += "<h2>Variables:</h2>";
    text += QString("count: %1").arg(count);
}

void Trace_infos::set_links_infos(QString &text) const {
    /* count */
    int nb_of_links = 0;

    list <Container *> containers;
    _trace->get_all_containers(containers);

    // Look for the values now
    for(list<Container *>::const_iterator it = containers.begin() ; it != containers.end() ; ++ it) {
        const Link::Vector *links = (*it)->get_links();
        for(Link::VectorIt it = links->begin() ; it != links->end() ; ++ it) {
            nb_of_links ++;
        }
    }

    text += "<h2>Links:</h2>";
    text += QString("count: %1").arg(nb_of_links);
}

void Trace_infos::init() {
    //_text_info->clear();
}

void Trace_infos::clear() {
    _text_info->clear();
}

void Trace_infos::set_arguments(map<string /*argname*/, QVariant */*argValue*/>) {}

string Trace_infos::get_name() {
    return "Trace informations";
}

void Trace_infos::execute() {
    _text_info->clear();
    QString text ("<center><h1> Trace informations </h1></center>");

    set_container_infos(text);

    set_states_infos(text);

    set_events_infos(text);

    set_variables_infos(text);

    set_links_infos(text);

    _text_info->setHtml(text);
}
