#ifdef STATISTICS
#ifndef morpheo_behavioural_Stat_h
#define morpheo_behavioural_Stat_h

#include "Behavioural/include/Parameters_Statistics.h"
#include "Behavioural/include/Stat_type.h"
#include "Behavioural/include/Stat_binary_tree.h"
#include "Behavioural/include/XML.h"
#include "Common/include/ErrorMorpheo.h"
#include "Common/include/Message.h"

#ifdef SYSTEMC
#include "systemc.h"
#endif

#include <stdint.h>
#include <string>
#include <map>
#include <list>
#include <iostream>

namespace morpheo {
  namespace behavioural {

    typedef double cycle_t;
  
    typedef struct 
    {
      counter_type_t type;
      counter_t *    counter;
      std::string    name;
      std::string    unit;
      std::string    description;
      std::list<counter_t> save_counter;
    } var_t;
  
    typedef struct 
    {
      bool               each_cycle;
      counter_t        * variable;
      Stat_binary_tree * expression;
    } expr_t;

    class Stat
    {
      const std::string              _name_instance;
      const std::string              _name_component;
      const cycle_t                  _nb_cycle_before_begin;
      const cycle_t                  _period;
      const bool                     _save_periodic;
      // Tableau des variables
      std::map<std::string, var_t> * _list_operand;
      // Liste chaîné des expressions
      std::list<expr_t>            * _list_expr;

      counter_t                    * _cycle;

      std::list<Stat *>            * _list_stat;

      bool                           _generate_file;

    public :                     Stat                         (std::string name_instance,
						               std::string name_component,
						               Parameters_Statistics * param);
    public :                     Stat                         (std::string name_instance,
						               std::string name_component,
						               cycle_t nb_cycle_before_begin=0,
						               cycle_t period=0);
    public :                    ~Stat                         (void);

    public  : counter_t *        create_variable              (std::string varname);
    public  : counter_t *        create_counter               (std::string varname,
						               std::string unit,
						               std::string description);
    private : counter_t *        alloc_operand                (counter_type_t type,
						               std::string varname,
						               std::string unit,
						               std::string description);

    public  : void               create_expr                  (std::string varname,
						               std::string expr,
						               bool each_cycle=false);
    public  : void               create_expr_average          (std::string varname,
						               std::string expr_sum,
						               std::string expr_deps,
						               std::string unit,
						               std::string description);

    public  : void               create_expr_average_by_cycle (std::string varname,
							       std::string expr_sum,
							       std::string unit,
							       std::string description);

    public  : void               create_expr_percent          (std::string varname,
						               std::string expr_sum,
						               std::string expr_max,
						               std::string description);

    private : Stat_binary_tree * string2tree                  (std::string expr);

    public  : void               end_cycle                    (void);
    private : void               end_simulation               (void);

    private : void               test_and_save                (bool force_save=false);

    private : void               eval_exprs                   (bool only_each_cycle=true);
    private : void               eval_expr                    (expr_t expr);

    private : bool               is_valid_var                 (std::string expr);

    private : void               generate_file                (void);

    private : bool               have_counter                 (void);

    public  : void               add_stat                     (Stat * stat);

    public  : std::string        print                        (uint32_t depth=0);
    };

  };
};
#endif
#endif
