#ifndef morpheo_behavioural_Component_h
#define morpheo_behavioural_Component_h

/*
 * $Id: Component.h 82 2008-05-01 16:48:45Z 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 ;
    } 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 
						       );

  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);

  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    : 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);
  };

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

#endif
