#ifndef morpheo_behavioural_Component_h
#define morpheo_behavioural_Component_h

/*
 * $Id: Component.h 115 2009-04-20 21:29:17Z rosiere $
 *
 * [ Description ]
 * 
 */

#include <stdint.h>
#include <iostream>
#include <list>
#include <map>
#ifdef VHDL
#include "Behavioural/include/Vhdl.h"
#endif
//#include "Behavioural/include/Description.h"
#include "Behavioural/include/Entity.h"
#include "Common/include/ToString.h"
#include "Common/include/Debug.h"
#include "Behavioural/include/Usage.h"

namespace morpheo              {
namespace behavioural          {

  /*
#ifdef DEBUG
# define PORT_MAP(x,a,b,c,d)						\
  do									\
    {									\
      try								\
	{								\
	  x->port_map(a,b,c,d);						\
	}								\
      catch (morpheo::ErrorMorpheo & error)				\
	{								\
	  throw (ErrorMorpheo ("In file "+toString(__FILE__)+", at line "+toString(__LINE__)+"\n"+error.what ())); \
	}								\
    }									\
  while (0)
#else
*/
# define PORT_MAP(x,a,b,c,d)						\
  do									\
    {									\
      x->port_map(a,b,c,d);						\
    }									\
  while (0)
// #endif

#define COMPONENT_MAP(x,a,b,c,d)					\
  do									\
    {									\
      PORT_MAP(x,a,b,c,d);						\
      PORT_MAP(x,c,d,a,b);						\
    }									\
  while (0)
  

  typedef uint8_t Tinstance_t;

#define INSTANCE_NONE         0x0
#define INSTANCE_LIBRARY      0x1
#define INSTANCE_COMPONENT    0x2
#define INSTANCE_POSITION     0x4
#define INSTANCE_ALL          0x7

  class Component
  {
    typedef struct
    {
    public : Component * _component;
    public : Entity    * _entity   ;
    public : Tinstance_t _instance ;
    public : std::string _architecture;
    } Tcomponent_t;    
  
    // -----[ fields ]----------------------------------------------------
  private   : const Tusage_t             _usage;
  private   : Entity                   * _entity        ;
  private   : std::list<Tcomponent_t*> * _list_component;

    // -----[ methods ]---------------------------------------------------
  public    :                       Component         (Tusage_t usage);
  public    :                       Component         (const Component & component);
  public    :                       ~Component        ();

  public    : std::string           get_name          (void);

  public    : Entity *              set_entity        (std::string        name   
						       ,std::string        type  
#ifdef POSITION
						       ,schema_t      schema
#endif
						       );
  private   : std::string           get_entity        (void);

  public    : void                  set_component     (Component * component
#ifdef POSITION
						       ,uint32_t   pos_x  
						       ,uint32_t   pos_y  
						       ,uint32_t   size_x 
						       ,uint32_t   size_y 
#endif
						       ,Tinstance_t instance=INSTANCE_ALL 
                                                       ,std::string architecture=""
						       );

  private   : std::string           get_component     (void);

  private   : Entity *              find_entity       (std::string name);
//private   : Interface *           find_interface    (std::string   name  , 
//						       Entity * entity);

#ifdef VHDL
  public    : void                  vhdl_instance     (Vhdl * & vhdl);
#endif


  private   : Signal *              signal_internal   (Entity * entity_productor,
						       Signal * signal_productor,
                                                       Entity * entity_consumer,
						       Signal * signal_consumer);

  public    : void                  port_map          (std::string component_src ,
						       std::string port_src      ,
						       std::string component_dest,
						       std::string port_dest    );

  public    : bool                  test_map          (bool recursive=true);
  private   : bool                  test_map          (uint32_t depth, bool recursive);

  public    : void *                get_sc_signal     (std::string component,
						       std::string port     );
//   public    : void                  set_sc_signal     (std::string component,
// 						       std::string port     ,
//                                                        void *      sc_signal);

//   public    : bool                  test_equi         (bool recursive=true);
//   private   : bool                  test_equi         (uint32_t depth, bool recursive);

#ifdef POSITION
  public    : void                  interface_map     (std::string component_src ,
						       std::string port_dest,
						       std::string component_dest,
						       std::string port_dest     );

  public    : XML                   toXML             (void);

  public    : void                  generate_file     (void);
#endif    
  public    : friend std::ostream&  operator<<        (std::ostream& output_stream,
						       morpheo::behavioural::Component & x);


#undef  FUNCTION
#define FUNCTION "Component::set_sc_signal"
  public    : template <typename T>
  void set_sc_signal (std::string component,
                      std::string port     ,
                      void *      sc_signal)
    {
      log_begin(Behavioural,FUNCTION);
      
      std::string name_entity = _entity->get_name();
      
      Entity * entity = find_entity(component);
      
      if (entity == NULL)
        throw (ERRORMORPHEO (FUNCTION,"In component \""+name_entity+"\", the component \""+component+"\" is unknow.\n"));
      
      Signal * signal = entity->find_signal (port);
      
      if (signal == NULL)
        throw (ERRORMORPHEO (FUNCTION,"In component \""+name_entity+"\", the component \""+component+"\" have not the signal \""+port+"\".\n"));
      
      signal->alloc<T>(sc_signal);
      
      log_end(Behavioural,FUNCTION);
    };
  };

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

#endif
