/*
 ** This file is part of the ViTE project.
 **
 ** This software is governed by the CeCILL-A license under French law
 ** and abiding by the rules of distribution of free software. You can
 ** use, modify and/or redistribute the software under the terms of the
 ** CeCILL-A license as circulated by CEA, CNRS and INRIA at the following
 ** URL: "http://www.cecill.info".
 **
 ** As a counterpart to the access to the source code and rights to copy,
 ** modify and redistribute granted by the license, users are provided
 ** only with a limited warranty and the software's author, the holder of
 ** the economic rights, and the successive licensors have only limited
 ** liability.
 **
 ** In this respect, the user's attention is drawn to the risks associated
 ** with loading, using, modifying and/or developing or reproducing the
 ** software by the user in light of its specific status of free software,
 ** that may mean that it is complicated to manipulate, and that also
 ** therefore means that it is reserved for developers and experienced
 ** professionals having in-depth computer knowledge. Users are therefore
 ** encouraged to load and test the software's suitability as regards
 ** their requirements in conditions enabling the security of their
 ** systems and/or data to be ensured and, more generally, to use and
 ** operate it in the same conditions as regards security.
 **
 ** The fact that you are presently reading this means that you have had
 ** knowledge of the CeCILL-A license and that you accept its terms.
 **
 **
 ** ViTE developers are (for version 0.* to 1.0):
 **
 **        - COULOMB Kevin
 **        - FAVERGE Mathieu
 **        - JAZEIX Johnny
 **        - LAGRASSE Olivier
 **        - MARCOUEILLE Jule
 **        - NOISETTE Pascal
 **        - REDONDY Arthur
 **        - VUCHENER Clément
 **
 */
#include <iostream>
#include <string>
#include <map>
#include <list>
#include <vector>
#include <sstream>
#include <stack>
#include <algorithm>

/* -- */
#include "interface/Interface.hpp"
/* -- */
#include "common/Message.hpp"
#include "common/Session.hpp"
#include "common/Palette.hpp"
/* -- */
#include "trace/values/Values.hpp"
#include "trace/tree/Interval.hpp"
#include "trace/tree/Node.hpp"
#include "trace/tree/BinaryTree.hpp"
#include "trace/EntityValue.hpp"
#include "trace/EntityTypes.hpp"
#include "trace/Entitys.hpp"
#include "trace/Trace.hpp"
/* -- */
#include "common/common.hpp"
#include "common/Info.hpp" /* Dirty, should be remove */
#include "common/Message.hpp"
/* -- */
#include "trace/tree/Interval.hpp"
/* -- */

#include <QtXml>


#if defined(USE_ITC) && defined(BOOST_SERIALIZE)
#include <fstream>
#include <boost/serialization/base_object.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/utility.hpp>
#include <boost/serialization/list.hpp>
#include <boost/serialization/assume_abstract.hpp>
#include "boost/serialization/map.hpp"


#include "trace/Serializer.hpp"

#include "trace/Serializer_values.hpp"
#include "trace/Serializer_types.hpp"
#include "trace/Serializer_structs.hpp"
#include "trace/Serializer_container.hpp"

#include "trace/SerializerDispatcher.hpp"
#endif
using namespace std;


Trace::Trace(): _max_date(0.0) {
    _selected_container = NULL;
    _filter = 0;
    _interval_constrained = NULL;
    _depth = 0;
}

template <class T>
void MyDelete(T *ptr){
    delete ptr;
};


Trace::~Trace()
{
    //delete _palette;

    if(_interval_constrained != NULL) {
        delete _interval_constrained;
        _interval_constrained = NULL;
    }

    // Delete containers
    for_each(_root_containers.begin(),
             _root_containers.end(),
             MyDelete<Container>);
    _root_containers.clear();
    _root_containers.resize(0);
    // while (!_root_containers.empty()){
    //     delete _root_containers.front();
    //     _root_containers.pop_front();
    // }

    // Delete container types
    while (!_root_container_types.empty()){
        delete _root_container_types.front();
        _root_container_types.pop_front();
    }

    //     Delete state types
    for(std::map<Name, StateType* >::iterator it=_state_types.begin(); it !=_state_types.end(); it++)
        delete (*it).second;


    // Delete event types
    for(std::map<Name, EventType* >::iterator it=_event_types.begin(); it !=_event_types.end(); it++)
        delete (*it).second;


    // Delete link types
    for(std::map<Name, LinkType* >::iterator it=_link_types.begin(); it !=_link_types.end(); it++)
        delete  (*it).second;


    // Delete variable types
    for(std::map<Name, VariableType* >::iterator it=_variable_types.begin(); it !=_variable_types.end(); it++)
        delete  (*it).second;
    _state_types.clear();
    _event_types.clear();
    _link_types.clear();
    _variable_types.clear();

}

static void delete_opt(map<string, Value *> &opt) {
    for (map<string, Value *>::iterator i = opt.begin();
         i != opt.end();
         i++) {
        delete (*i).second;
    }
}

void Trace::define_container_type(Name &name, ContainerType *parent, map<string, Value *> &opt) {
    ContainerType *type = new ContainerType(name, parent);
    if (parent)
        parent->add_child(type);
    else
        _root_container_types.push_back(type);
#if defined(USE_ITC) && defined(BOOST_SERIALIZE)
    Serializer<ContainerType>::Instance().setUid(type);
#endif
    // Delete unused extra fields
    delete_opt(opt);
}

Container* Trace::create_container(Date &time,
                                   Name &name,
                                   ContainerType *type,
                                   Container *parent,
                                   map<string, Value *> &opt)
{
    if (!type) {
        vite_error("Trace::get_container : Type undefined");
        return NULL;
    }

    Container *cont = new Container(name, time, type, parent, opt);
    if (parent){
        parent->add_child(cont);
    } else {
        _root_containers.push_back(cont);
    }

    /* Update the trace depth */
    if (cont->get_depth() > _depth) {
        _depth = cont->get_depth();
        Info::Trace::depth = _depth; /* Dirty method. Should be remove */
    }

    if (time > _max_date)
        _max_date = time;

#if defined(USE_ITC) && defined(BOOST_SERIALIZE)
    Serializer<Container>::Instance().setUid(cont);
#endif

    return cont;
    // Delete unused extra fields
    //delete_opt(opt);
}

void Trace::destroy_container(Date &time,
                              Container *cont,
                              ContainerType *type,
                              map<string, Value *> &opt)
{
    if (cont && type)
        cont->destroy(time);

    if (time > _max_date)
        _max_date = time;

    // Delete unused extra fields
    delete_opt(opt);
}

void Trace::define_event_type(Name &name, ContainerType *container_type, map<string, Value *> &opt) {
    EventType* et=new EventType(name, container_type, opt);
    _event_types.insert ( pair<Name , EventType*>(name,et));

#if defined(USE_ITC) && defined(BOOST_SERIALIZE)
    Serializer<EntityType>::Instance().setUid(et);
#endif
    //_event_types.push_back(new EventType(name, container_type, opt));
}

void Trace::define_state_type(Name &name, ContainerType *container_type, map<string, Value *> &opt) {
    StateType* st=new StateType(name, container_type, opt);
    _state_types.insert ( pair<Name , StateType*>(name,st));

#if defined(USE_ITC) && defined(BOOST_SERIALIZE)
    Serializer<EntityType>::Instance().setUid(st);
#endif
    // _state_types.push_back(new StateType(name, container_type, opt));
}

void Trace::define_variable_type(Name &name, ContainerType *container_type, map<string, Value *> &opt) {
    if (container_type){
        VariableType* vt=new VariableType(name, container_type, opt);
        _variable_types.insert ( pair<Name , VariableType*>(name,vt));

#if defined(USE_ITC) && defined(BOOST_SERIALIZE)
        Serializer<EntityType>::Instance().setUid(vt);
#endif
    }
    //_variable_types.push_back(new VariableType(name, container_type, opt));
}

void Trace::define_link_type(Name &name,
                             ContainerType *ancestor,
                             ContainerType *source,
                             ContainerType *destination,
                             map<string, Value *> &opt)
{
    // TODO: make a clean error message if source or destination is undefined
    if (source && destination){
        LinkType * lt= new LinkType(name, ancestor, source, destination, opt);
        _link_types.insert ( pair<Name , LinkType*>(name,lt));
#if defined(USE_ITC) && defined(BOOST_SERIALIZE)
        Serializer<EntityType>::Instance().setUid(lt);
#endif
        //_link_types.push_back(new LinkType(name, ancestor, source, destination, opt));
    }
}

void Trace::define_entity_value(Name &name, EntityType *entity_type, map<string, Value *> &opt) {
    if (entity_type) {
        //don't alter the trace, reloading initial colors won't be possible after that.
        // The palettes are applied ine DrawTrace or DrawTree after that
        /*if(Session::_palette) {
         Color *c = Session::_palette->get_color(name.to_string());
         if(c != NULL) { // We set the palette color first
         if(opt.find("Color") != opt.end()) {
         delete opt["Color"];
         }
         opt["Color"] = new Color(*c);

         }
         }*/

        entity_type->add_value(new EntityValue(name, entity_type, opt));
    }
}

void Trace::set_state(Date &time, StateType *type, Container *container, EntityValue *value, map<string, Value *> &opt) {
    if (container && type)
        container->set_state(time, type, value, opt);

    if (time > _max_date)
        _max_date = time;
}

void Trace::push_state(Date &time, StateType *type, Container *container, EntityValue *value, map<string, Value *> &opt) {
    if (container && type)
        container->push_state(time, type, value, opt);

    if (time > _max_date)
        _max_date = time;
}

void Trace::pop_state(Date &time, StateType *type, Container *container, map<string, Value *> &opt) {
    if (container && type)
        container->pop_state(time);

    if (time > _max_date)
        _max_date = time;

    // Delete unused extra fields
    delete_opt(opt);
}

void Trace::reset_state(Date &time, StateType *type, Container *container, map<string, Value *> &opt) {
    if (container && type)
        container->reset_state(time);

    if (time > _max_date)
        _max_date = time;

    // Delete unused extra fields
    delete_opt(opt);
}

void Trace::new_event(Date &time, EventType *type, Container *container, EntityValue *value, map<string, Value *> &opt) {
    if (container && type)
        container->new_event(time, type, value, opt);

    if (time > _max_date)
        _max_date = time;
}

void Trace::set_variable(Date &time, VariableType *type, Container *container, Double value, map<string, Value *> &opt) {
    if (container && type)
        container->set_variable(time, type, value);

    if (time > _max_date)
        _max_date = time;

    // Delete unused extra fields
    delete_opt(opt);
}

void Trace::add_variable(Date &time, VariableType *type, Container *container, Double value, map<string, Value *> &opt) {
    if (container && type)
        container->add_variable(time, type, value);

    if (time > _max_date)
        _max_date = time;

    // Delete unused extra fields
    delete_opt(opt);
}

void Trace::sub_variable(Date &time, VariableType *type, Container *container, Double value, map<string, Value *> &opt) {
    if (container && type)
        container->sub_variable(time, type, value);

    if (time > _max_date)
        _max_date = time;

    // Delete unused extra fields
    delete_opt(opt);
}

void Trace::start_link(Date &time, LinkType *type, Container *ancestor, Container *source, EntityValue *value, String key, map<string, Value *> &opt) {
    if (ancestor && type && source)
        ancestor->start_link(time, type, source, value, key, opt);

    if (time > _max_date)
        _max_date = time;
}

void Trace::end_link(Date &time, LinkType *type, Container *ancestor, Container *destination, EntityValue * /*value*/, String key, map<string, Value *> &opt) {
    if (ancestor && type && destination)
        ancestor->end_link(time, destination, key, opt);

    if (time > _max_date)
        _max_date = time;
}


void Trace::finish() {
    stack<Container *> containers;

    const Container::Vector* root_containers =&_view_root_containers;
    if(root_containers->empty())root_containers=&_root_containers;

    Container::VectorIt        i   = root_containers->begin();
    Container::VectorIt const &end = root_containers->end();

    for (; i != end; i++)
        containers.push(*i);

    while (!containers.empty()) {
        Container * c = containers.top();
        containers.pop();
        c->finish(_max_date);

        {
            const Container::Vector* children =c->get_view_children();
            if (children->empty())children=c->get_children();

            Container::VectorIt        it     = children->begin();
            Container::VectorIt const &it_end = children->end();

            for (; it != it_end; it++)
                containers.push(*it);
        }
    }

}

#if defined(USE_ITC) && defined(BOOST_SERIALIZE)

void Trace::updateTrace(Interval* interval){
    if(Info::Splitter::load_splitted==true){
        if(Info::Splitter::preview==false){
            loadTraceInside(interval);
            finish();
        }else{
            loadPreview();

        }
    }

}

void Trace::loadTraceInside(Interval* interval){
    SerializerDispatcher::Instance().init();
    stack<Container *> containers;
    const Container::Vector* root_containers =&_view_root_containers;
    if(root_containers->empty())root_containers=&_root_containers;

    Container::VectorIt        i   = root_containers->begin();
    Container::VectorIt const &end = root_containers->end();

    for (; i != end; i++)
        containers.push(*i);

    while (!containers.empty()) {
        Container * c = containers.top();
        c->loadItcInside(interval);
        containers.pop();
        {
            const Container::Vector* children =c->get_view_children();
            if (children->empty())children=c->get_children();

            Container::VectorIt        it     = children->begin();
            Container::VectorIt const &it_end = children->end();

            for (; it != it_end; it++)
                containers.push(*it);
        }
    }

    //wait for loading to finish
    SerializerDispatcher::Instance().kill_all_threads();
}

void Trace::loadPreview (){
    stack<Container *> containers;
    const Container::Vector* root_containers =&_view_root_containers;
    if(root_containers->empty())root_containers=&_root_containers;

    Container::VectorIt        i   = root_containers->begin();
    Container::VectorIt const &end = root_containers->end();

    for (; i != end; i++)
        containers.push(*i);

    while (!containers.empty()) {
        Container * c = containers.top();
        c->loadPreview();
        containers.pop();
        {
            const Container::Vector* children =c->get_view_children();
            if (children->empty())children=c->get_children();

            Container::VectorIt        it     = children->begin();
            Container::VectorIt const &it_end = children->end();

            for (; it != it_end; it++)
                containers.push(*it);
        }
    }

}


void Trace::dump(std::string path, std::string filename) {



    //dump intervalOfContainer for each container
    stack<Container *> containers;
    Container::VectorIt        i   = _root_containers.begin();
    Container::VectorIt const &end = _root_containers.end();

    for (; i != end; i++)
        containers.push(*i);

    while (!containers.empty()) {
        Container * c = containers.top();
        c->dump(path, filename, _max_date);
        containers.pop();
        {
            std::list<Container *>::const_iterator        it     = c->get_children()->begin();
            std::list<Container *>::const_iterator it_end = c->get_children()->end();

            for (; it != it_end; it++){
                containers.push(*it);
            }
        }

    }
    //dump containers

    std::string file;
    file += path + "/" + filename + "/" + filename +".vite";
    //  i   = _root_containers.begin();
    std::ofstream ofs(file.c_str(),std::ios::out);
    boost::archive::text_oarchive oa(ofs);




    oa.register_type(static_cast<StateType *>(NULL));
    oa.register_type(static_cast<EventType *>(NULL));
    oa.register_type(static_cast<VariableType *>(NULL));
    oa.register_type(static_cast<LinkType *>(NULL));
    oa.register_type(static_cast<ContainerType *>(NULL));
    oa.register_type(static_cast<Container *>(NULL));
    oa.register_type(static_cast<Color *>(NULL));
    oa.register_type(static_cast<Date *>(NULL));
    oa.register_type(static_cast<Double *>(NULL));
    oa.register_type(static_cast<Hex *>(NULL));
    oa.register_type(static_cast<Integer *>(NULL));
    oa.register_type(static_cast<Name *>(NULL));
    oa.register_type(static_cast<String *>(NULL));
    oa << _root_container_types;
    oa << _root_containers;
    oa <<  _state_types;
    oa <<  _event_types;
    oa <<  _link_types;
    oa <<  _variable_types;
    oa <<  _max_date;


    //we finished to dump all the trace, we can now cleanly kill the serialization threads
    SerializerDispatcher::Instance().kill_all_threads();



}
#endif

const Container::Vector *Trace::get_root_containers() const {
    return &_root_containers;
}

void Trace::set_root_containers(Container::Vector& conts) {
    _root_containers=conts;


    /* Update the trace depth, a bit dirty, but we need to fetch the maximum */

    stack<Container *> containers;

    const Container::Vector* root_containers =&_root_containers;

    Container::VectorIt        i   = root_containers->begin();
    Container::VectorIt const &end = root_containers->end();

    for (; i != end; i++)
        containers.push(*i);

    while (!containers.empty()) {
        Container * c = containers.top();
        containers.pop();
        if (c->get_depth() > _depth){
            _depth=c->get_depth();
            Info::Trace::depth=_depth; /* Dirty method. Should be remove */
        }

        {
            const Container::Vector* children =c->get_children();

            Container::VectorIt        it     = children->begin();
            Container::VectorIt const &it_end = children->end();

            for (; it != it_end; it++)
                containers.push(*it);
        }
    }



}

void Trace::set_state_types (std::map<Name, StateType* >& conts) {
    _state_types=conts;
}
void Trace::set_event_types (std::map<Name, EventType* >& conts) {
    _event_types=conts;
}
void Trace::set_link_types (std::map<Name, LinkType* >& conts) {
    _link_types=conts;
}
void Trace::set_variable_types (std::map<Name, VariableType* >& conts) {
    _variable_types=conts;
}

void Trace::set_container_types (std::list<ContainerType*>& conts) {
    _root_container_types=conts;
}

void Trace::set_max_date(Date d){
    _max_date=d;
}

const Container::Vector *Trace::get_view_root_containers() const {
    return &_view_root_containers;
}

void Trace::set_view_root_containers(Container::Vector& conts) {
    _view_root_containers=conts;
}

void Trace::get_all_containers(Container::Vector &list_to_fill) const {
    Container::VectorIt        it  = _root_containers.begin();
    Container::VectorIt const &end = _root_containers.end();

    for (; it != end; it ++) {
        list_to_fill.push_back(*it);
        // Recursivity to add the children names
        add_containers(list_to_fill, *it);
    }

}

void Trace::add_containers(Container::Vector &containers, const Container *parent) const {
    const Container::Vector           *children  = parent->get_children();
    Container::VectorIt        it  = children->begin();
    Container::VectorIt const &end = children->end();

    for (; it != end; it ++) {
        // We create the node and we do the recursivity
        containers.push_back(*it);
        add_containers(containers , *it);
    }
}

const map<Name, StateType* > *Trace::get_state_types() const {
    return &_state_types;
}

const map<Name, EventType* > *Trace::get_event_types() const {
    return &_event_types;
}

const map<Name, LinkType* > *Trace::get_link_types() const {
    return &_link_types;
}

template<class T>
static T *search_tree(string name, T *el) { // Before : String name
    if (el->get_name() == name)
        return el;
    else {
        T *r;
        typename list<T *>::const_iterator it_end = el->get_children()->end();
        for (typename list<T *>::const_iterator it = el->get_children()->begin();
             it != it_end;
             ++ it) {
            r = search_tree<T>(name, *it);
            if (r)
                return r;
        }
    }
    return 0;
}

template<class T>
static T *search_treeV(string name, T *el) { // Before : String name
    if (el->get_name() == name)
        return el;
    else {
        T *r;
        typename vector<T *>::const_iterator it_end = el->get_children()->end();
        for (typename vector<T *>::const_iterator it = el->get_children()->begin();
             it != it_end;
             ++ it) {
            r = search_treeV<T>(name, *it);
            if (r)
                return r;
        }
    }
    return 0;
}

ContainerType *Trace::search_container_type(String name) const {
    ContainerType *r;

    const string &std_name = name.to_string();
    if (std_name == "0")
        return 0;

    const list<ContainerType *>::const_iterator &it_end = _root_container_types.end();
    for (list<ContainerType *>::const_iterator it = _root_container_types.begin();
         it != it_end;
         ++ it) {
        r = search_tree<ContainerType>(std_name, *it);
        if (r)
            return r;
    }

    return 0;
}

Container *Trace::search_container(String name) const {
    Container *r;

    const string &std_name = name.to_string();
    if (std_name == "0")
        return 0;

    Container::VectorIt        it  = _root_containers.begin();
    Container::VectorIt const &end = _root_containers.end();
    for( ; it != end; ++ it) {
        r = search_tree<Container>(std_name, *it);
        if (r)
            return r;
    }

    return 0;
}

EventType *Trace::search_event_type(String name) const {
    std::map<Name, EventType* >::const_iterator it = _event_types.find(Name(name));
    if (it !=  _event_types.end() ) {
        return  (((*it).second));
    }

    return 0;
}

StateType *Trace::search_state_type(String name) const {
    std::map<Name, StateType* >::const_iterator it = _state_types.find(Name(name));
    if (it !=  _state_types.end() ) return (((*it).second));
    return 0;
}

VariableType *Trace::search_variable_type(String name) const {
    std::map<Name, VariableType* >::const_iterator it = _variable_types.find(Name(name));
    if (it !=  _variable_types.end() ) return (((*it).second));
    return 0;
}

LinkType *Trace::search_link_type(String name) const {
    std::map<Name, LinkType* >::const_iterator it = _link_types.find(Name(name));
    if (it !=  _link_types.end() ) return (((*it).second));
    return 0;
}

EntityType *Trace::search_entity_type(String name) const {
    //Search the State Type
    std::map<Name, StateType*>::const_iterator it = _state_types.find(Name(name));

    if (it !=  _state_types.end() ) return  (((*it).second));
    //Search the Link Type
    std::map<Name, LinkType*>::const_iterator it2 = _link_types.find(Name(name));

    if (it2 !=  _link_types.end() ) return (((*it2).second));
    //Search the Entity Type
    std::map<Name, EventType*>::const_iterator it3 = _event_types.find(Name(name));

    if (it3 !=  _event_types.end() ) return  (((*it3).second));

    return 0;
}

EntityValue *Trace::search_entity_value(String name, EntityType *entity_type) const {
    if(!entity_type){
        return NULL;
    }

    map<Name, EntityValue* >::const_iterator it = entity_type->get_values()->find(Name(name));
    if (it !=  entity_type->get_values()->end() ) {
        return ( (*it).second);
    }
    Name alias_name(name);
    //alias_name.set_name(name.to_string());
    EntityValue *value = new EntityValue(alias_name, entity_type, map<string, Value*>());
    entity_type->add_value(value);
    return value;
}

Date Trace::get_max_date(){
    return _max_date;
}

int Trace::get_depth(){
    return _depth;
}


void Trace::set_selected_container(vector<const Container *> * c) {
    _selected_container = c;
}

void Trace::set_interval_constrained(Interval * i) {
    if(_interval_constrained != NULL) {
        delete _interval_constrained;
    }
    _interval_constrained = i;
}

vector<const Container *> *Trace::get_selected_container() {
    return _selected_container;
}

Interval *Trace::get_interval_constrained() {
    return _interval_constrained;
}

void Trace::set_filter(double f) {
    _filter = f;
}

double Trace::get_filter() {
    return _filter;
}

void Trace::get_all_variables(map<string, Variable *> &map_to_fill) {
    Container::Vector all_containers;
    get_all_containers(all_containers);

    Container::VectorIt const &end = all_containers.end();
    Container::VectorIt        it  = all_containers.begin();
    for ( ; it != end ; it ++) {
        const map<VariableType *, Variable *> *variables = (*it)->get_variables();
        // We store each variable
        for(map<VariableType *, Variable *>::const_iterator var_it = variables->begin() ;
            var_it != variables->end() ;
            var_it ++) {
            string name = (*it)->get_name().to_string() + " " + (*var_it).first->get_name().to_string();
            map_to_fill[name] = (*var_it).second;
        }
    }
}

void Trace::get_states_colors(map<string, Color * > &nc_map, Container *parent) {
    Container::Vector containers;
    // We look for each container
    if(parent)
        add_containers(containers, parent);
    else // We add all
        get_all_containers(containers);

    for(Container::VectorIt it = containers.begin();
        it != containers.end(); ++ it) {
        BinaryTree<StateChange> *states;
        states = (*it)->get_states();
        if(states && states->get_root()) {
            get_state_names_colors_list(nc_map, states->get_root());
        }
    }
}

void Trace::get_events_colors(map<string, Color * > &nc_map) {
    map<Name, EventType *>::const_iterator it;

    for(it  = _event_types.begin();
        it != _event_types.end() ; ++ it)
    {
        Color *color = NULL;
        if( (it->second->get_extra_fields() != NULL) &&
            (it->second->get_extra_fields()->find(string("Color")) != it->second->get_extra_fields()->end()) )
        {
            color = (Color *)( it->second->get_extra_fields()->find(string("Color"))->second );
        }
        else {
            color = new Color();
        }

        nc_map[ it->first.get_name() ] = color;
    }
}

void Trace::get_links_colors(map<string, Color * > &nc_map) {
    map<Name, LinkType *>::const_iterator it;

    for(it  = _link_types.begin();
        it != _link_types.end() ; ++ it)
    {
        Color *color = NULL;
        if( (it->second->get_extra_fields() != NULL) &&
            (it->second->get_extra_fields()->find(string("Color")) != it->second->get_extra_fields()->end()) )
        {
            color = (Color *)( it->second->get_extra_fields()->find(string("Color"))->second );
        }
        else {
            color = new Color();
        }

        nc_map[ it->first.get_name() ] = color;
    }
}

void Trace::get_colors(const string type, map<string, Color * > &nc_map) {
    if (type == "palette")
        get_states_colors( nc_map );
    else if (type == "event_types")
        get_events_colors( nc_map );
    else if (type == "link_types")
        get_links_colors( nc_map );
}

/* Fill name_map with the names of the state contained in sub-tree node */
void get_state_names_colors_list(map<string, Color *> &name_map, Node<StateChange> *node) {
    if (!node)
        return;

    /* handle the node */
    const State *left_st = node->get_element()->get_left_state();
    if (left_st) {
        const EntityValue *value = left_st->get_value();
        const string name = value->get_name().to_string();
        Color *color = NULL;
        if(value->get_extra_fields()!=NULL && (value->get_extra_fields()->find(string("Color")) != value->get_extra_fields()->end())) {
            color = (Color *)value->get_extra_fields()->find(string("Color"))->second;
        }

        name_map[name] = color;
    }

    const State *right_st = node->get_element()->get_right_state();
    if (right_st) {
        const EntityValue *value = right_st->get_value();
        const string name = value->get_name().to_string();

        Color *color = NULL;
        if(value->get_extra_fields()!=NULL && (value->get_extra_fields()->find(string("Color")) != value->get_extra_fields()->end())) {
            color = (Color *)value->get_extra_fields()->find(string("Color"))->second;
        }

        name_map[name] = color;
    }

    /* handle its left child */
    get_state_names_colors_list(name_map, node->get_left_child());

    /* handle its right child */
    get_state_names_colors_list(name_map, node->get_right_child());
}

bool  Trace::load_config_from_xml(QString filename){
    QDomDocument doc( "Subset" );
    QFile file( filename);
    if( !file.open( QIODevice::ReadOnly ) ){
        *Message::get_instance() << "File opening fail"<< Message::ende;
        return false ;
    }

    if( !doc.setContent( &file ) )
    {
        file.close();
        *Message::get_instance() << "File is not a valid xml file" << Message::ende;
        return false;
    }
    file.close();


    QDomElement root = doc.documentElement();
    if( root.tagName() != "nodes" ) {
        *Message::get_instance() << "File is not a valid xml file" << Message::ende;
        return false;
    }



    //go through all the top elements of the trace to construct a representation
    QDomNode n = root.firstChild();
    _view_root_containers.clear();
    while( !n.isNull() )
    {
        QDomElement e = n.toElement();
        if( !e.isNull() )
        {
            if( e.tagName() == "rootNode" )
            {
                string n(e.attribute( "name", "" ).toStdString());
                Container::VectorIt it = _root_containers.begin();
                for (;
                     it != _root_containers.end();
                     it ++) {
                    if((*it)->get_name().to_string()==n){//we found the root container corresponding
                        //QTreeWidgetItem *current_node = new QTreeWidgetItem((QTreeWidgetItem *)0, QStringList(QString::fromStdString(n)));
                        //current_node->setFlags(flg);
                        //current_node->setData(0,Qt::UserRole,qVariantFromValue(*it));//store the pointer to the container in the Data field
                        // current_node->setCheckState(0,Qt::Checked);
                        //items.append(current_node);
                        _view_root_containers.push_back(*it);
                        // Recursivity to add the children names
                        load_names_rec((*it), e);
                        break;
                    }

                }

                if(it==_root_containers.end())*Message::get_instance() <<"Root node was not found, check if it exists. Continuing ..." << Message::ende;

            }else
                *Message::get_instance() << "wrong node was found when parsing for rootNode, check xml construction. Continuing ..." << Message::ende;

        }

        n = n.nextSibling();
    }


    // _nodes_displayed->insertTopLevelItems(0, items);

    // _nodes_displayed->expandAll();
    return true;
}

void Trace::load_names_rec(Container *current_container, QDomElement& element) {

    //we need to loop on both the xml childs and the container's child to make them correspond
    const Container::Vector *children = current_container->get_children();
    current_container->clear_view_children();
    QDomNode n = element.firstChild();
    while( !n.isNull() )
    {
        QDomElement e = n.toElement();
        if( !e.isNull() )
        {
            if( e.tagName() == "Node" )
            {
                string n(e.attribute( "name", "" ).toStdString());
                Container::VectorIt it = children->begin();
                for (;
                     it != children->end();
                     it ++) {
                    // We create the node and we do the recursivity


                    if( (*it)->get_name().to_string()==n){
                        //we found the good Container
                        // QTreeWidgetItem *node = new QTreeWidgetItem(current_node, QStringList(QString::fromStdString(n)));

                        //node->setFlags(flg);
                        // node->setData(0,Qt::UserRole, qVariantFromValue(*it));//store the pointer to the container in the Data field
                        // node->setCheckState(0,Qt::Checked);
                        //printf("we found a sub element %s\n", n.c_str());
                        current_container->add_view_child((*it));
                        load_names_rec((*it), e);
                        break;
                    }
                }
                if(it==children->end())
                    *Message::get_instance() << "node "<< n << " was not found, check if it exists. Continuing ..." << Message::ende;

            }else
                *Message::get_instance() <<"wrong node was found when parsing for Node, check xml construction. Continuing ..." << Message::ende;

        }

        n = n.nextSibling();
    }

}



std::map<long int,double> Trace::update_text_variable_values(double date){
    std::map<long int,double> values;

    stack<Container *> containers;

    const Container::Vector* root_containers =&_view_root_containers;
    if(root_containers->empty())root_containers=&_root_containers;

    Container::VectorIt        i   = root_containers->begin();
    Container::VectorIt const &end = root_containers->end();
    const Variable* var;
    for (; i != end; i++)
        containers.push(*i);

    while (!containers.empty()) {
        Container * c = containers.top();
        containers.pop();
        if (c->get_variable_number() > 0){
            const std::map<VariableType *, Variable *>* variable_map = c->get_variables();

            for (std::map<VariableType *, Variable *>::const_iterator i = variable_map->begin();
                 i != variable_map->end();
                 i++) {

                var = (*i).second;

                values [(long int)var]= var->get_value_at(date);
                //draw_object->draw_text_value((long int)var,var->get_value_at(date), position);
            }


        }

        {
            const Container::Vector* children =c->get_view_children();
            if (children->empty())children=c->get_children();

            Container::VectorIt        it     = children->begin();
            Container::VectorIt const &it_end = children->end();

            for (; it != it_end; it++)
                containers.push(*it);
        }
    }
    return values;
}
