#ifndef morpheo_behavioural_configuration_Instance_h
#define morpheo_behavioural_configuration_Instance_h

/*
 * $Id: Instance.h 88 2008-12-10 18:31:39Z rosiere $
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Configuration/include/Parameter_affectation.h"
#include "Behavioural/Configuration/include/Link_affectation.h"
#include "Behavioural/Configuration/include/Generator.h"
#include "Behavioural/Configuration/include/Parameters.h"
#include "Behavioural/Custom/include/Custom.h"

#include <map>
#include <vector>
#include <cstdarg>

namespace morpheo {
namespace behavioural {
namespace configuration {

  class Instance_component;

  typedef std::map<std::string, Parameter_affectation *> list_parameters_t;
  typedef std::map<std::string, Link_affectation *>      list_link_t;
  typedef std::map<std::string, list_link_t>             list_links_t;
  typedef std::map<std::string, Instance_component *>    list_instances_t;
  typedef std::map<std::string, list_instances_t>        list_components_t;

  class Instance_component
  {
  public   : const std::string _name;
  public   : const std::string _id;
  public   : list_parameters_t * _list_parameters;
//public   : list_links_t      * _list_links;
  public   : list_components_t * _list_components;
   
  public   :  Instance_component (std::string name,
                                  std::string id):
    _name (name),
    _id   (id)
    {
      _list_parameters = new list_parameters_t;
//    _list_links      = new list_links_t     ;
      _list_components = new list_components_t;
    }
    
  public   : ~Instance_component (void)
    {
      for (list_parameters_t::iterator it = _list_parameters->begin();
           it != _list_parameters->end();
           ++it)
        delete it->second;
      delete _list_parameters;
      
//       for (list_links_t::iterator it1 = _list_links->begin();
//            it1 != _list_links->end();
//            ++it1)
//         for (list_link_t::iterator it2 = it1->second.begin();
//              it2 != it1->second.end();
//              ++it2)
//           delete it2->second;
//       delete _list_links;

      for (list_components_t::iterator it1 = _list_components->begin();
           it1 != _list_components->end();
           ++it1)
        for (list_instances_t::iterator it2 = it1->second.begin();
             it2 != it1->second.end();
             ++it2)
          delete it2->second;
      delete _list_components;
    }

#undef  FUNCTION
#define FUNCTION "Instance_component::toXML"
  public   : XML                  toXML                (void)
    {
      log_begin(Configuration,FUNCTION);

      XML xml (_name);
      
      xml.balise_open_begin(_name);
      xml.  attribut("id" ,_id);
      xml.balise_open_end();
      
      for (list_parameters_t::iterator it = _list_parameters->begin();
           it != _list_parameters->end();
           ++it)
        xml.insert_XML(it->second->toXML(),1);

//       for (list_links_t::iterator it1 = _list_links->begin();
//            it1 != _list_links->end();
//            ++it1)
//         for (list_link_t::iterator it2 = it1->second.begin();
//              it2 != it1->second.end();
//              ++it2)
//           xml.insert_XML(it2->second->toXML(),1);

      for (list_components_t::iterator it1 = _list_components->begin();
           it1 != _list_components->end();
           ++it1)
        for (list_instances_t::iterator it2 = it1->second.begin();
             it2 != it1->second.end();
             ++it2)
          xml.insert_XML(it2->second->toXML(),1);

      xml.balise_close();

      log_end(Configuration,FUNCTION);
      return xml;
    }

#undef  FUNCTION
#define FUNCTION "Instance_component::print"
  private  : std::string          print                (uint32_t depth)
    {
      log_begin(Configuration,FUNCTION);
      
      std::string _return = (toXML()).get_body(depth);
      
      log_end(Configuration,FUNCTION);
      return _return;
    };
    
#undef  FUNCTION
#define FUNCTION "Instance_component::operator<<"
  public   : friend std::ostream& operator<<           (std::ostream& output,
                                                        morpheo::behavioural::configuration::Instance_component & x)
    {
      log_begin(Configuration,FUNCTION);
      output << x.print(0);
      log_end(Configuration,FUNCTION);
      return output;
    };
  };


  class Instance
  {
    // -----[ fields ]----------------------------------------------------
  private  : std::string _name;
  private  : std::string _filename;
//private  : list_parameters_t * _array;

  public   : list_parameters_t * _list_parameters;
  public   : list_links_t      * _list_links;
  public   : list_components_t * _list_components;

  private  : Generator  * _generator;
  public   : Parameters * _param;

    // -----[ methods ]---------------------------------------------------
  public   :                          Instance    (std::string filename,
                                                   Generator * generator,
                                                   behavioural::custom::custom_information_t (*get_custom_information) (void));
  public   :                         ~Instance    ();
                                    
  public   : std::string              getName     (void);
  private  : std::string              getParam    (const char * name, ...);
  private  : std::vector<std::string> getLink     (const char * name, ...);
  private  : std::vector<std::string> link2array  (std::string  str);

    // Test : parameter, link, component
  public   : void                     test        (std::string type,
                                                   std::string value);
  public   : void                     test        (std::string type,
                                                   std::string father_name,
                                                   bool        father_is_src,
                                                   bool        father_is_dest);
  private  : void                     test        (std::string link,
                                                   std::vector<std::string> & vect,
                                                   uint32_t nb_elt);
  private  : void                     test_use    (void);
  private  : void                     test_use    (std::string name,
                                                   list_parameters_t * list_parameters,
                                                   list_components_t * list_components,
                                                   std::vector<std::string> & list_not_use);

  private  : void                     fromInternalStructure(void);
                                    
  private  : void                     fromXMLLight(XML_t * xml,
                                                   attribute_t         id,
                                                   list_parameters_t * list_parameters,
                                                   list_links_t      * list_links,
                                                   list_components_t * list_component);
                                    
  private  : void                     fromFile    (std::string filename);
                                    
  public   : void                     toFile      (std::string dirname=".");
  private  : XML                      toXML       (void);
  private  : std::string              print       (uint32_t depth);
  public   : friend std::ostream&     operator<<  (std::ostream& output,
                                                   morpheo::behavioural::configuration::Instance & x);

  };

}; // end namespace configuration
}; // end namespace behavioural
}; // end namespace morpheo              

#endif
