#ifndef TELEPATIPKG_H_DEF
#define TELEPATIPKG_H_DEF

#include <OPENR/ODataFormats.h>
#include <OPENR/OSyslog.h>

/** @file*/
/**namespace standard.*/
using namespace std;

/** Tipo di package.  Da 0 a 9 sono messaggi di servizio riconosciuti
    da Telepati, i restanti sono utilizzabili come messaggi
    personabilizzabili */
enum pkg_type {
  DUMMY=0, /**< messaggio DummyPkg*/
  INFO=1, /**< messaggio AiboInfoPkg*/
  HI=2, /**< messaggio HiPkg*/
  HIREPLY=3, /**< messaggio HiReplyPkg*/
  BYE=4, /**< messaggio ByePkg*/
  ACK=5, /**< messaggio AckPkg*/
  DUMMYLED=6, /**< messaggio DummyLedPkg*/
  COUNTER=7,  /**< messaggio di informazione sul numero di messaggi gestiti da Telepati*/
  LEADER=8, /**< messaggio di info sul leader del gruppo*/
  LEADERREPLY=9, /**< messaggio di risposta al messaggio leader*/
  COMMAND=10, /**< messaggio di comando*/
  TIMEINFO=11, /**< messaggio di informazioni sull'orologio dell'Aibo*/
  OTHHEADREADY=12, /**< other sono pronti a ricevere comandi per la testa*/
  OTHLEGSREADY=13, /**< other sono pronti a ricevere comandi per le zampe*/
  BREAKTHELINE=14 /**< Rompete le Righe, goal raggiunto*/
};


/**Classe virtuale per l'implementazione dei vari tipi di messaggi scambiati.
Struttura del pacchetto:
@code
      byte         byte        short          byte          short           byte...
   [pkg_type] [aibo_dest] [size_of_packet] [need_ack]  [serial_number]  [pkg_data... ]
@endcode
   @arg @c pkg_type= tipo di messaggio
   @arg @c aibo_dest= l'indice dell'aibo di destinazione
   @arg @c size_of_packet= dimensione del pacchetto compreso l'header
   @arg @c need_ack= 0 se non ha bisogno di ack, >0 se ne ha bisogno
   @arg @c serial_number= numero seriale del pachetto necessario all'Ack (16bit)
   @arg @c pkg_data= dati da spedire

   Dimensione dell'HEADER standard: 6byte.
*/
class TelepatiPkg {
 public:
  /** Costruttore di default.*/
  TelepatiPkg();  
  /** Construisce un oggetto a partire dall'array di byte (message)
      rappresentante un altro oggetto. Utilizzato per ricostruire la
      struttura del paccheto ricevuto dal Telepati. @param ptr i dati
      @see getMsg(), createPkg(const byte* ptr)*/
  TelepatiPkg(byte* ptr); 

  /** Distruttore di default*/
  virtual ~TelepatiPkg() { 
    delete [] message;
  };  
  
  /** Imposta il valore dell'aibo di destinazione. @param a a aibo di
      destinazione del pacchetto*/
   virtual inline void setAibo(int a) { aibo=a; return;};  
  /** Ritorna l'indice dell'Aibo di destinazione. @return int aibo di
      destinazione*/
  virtual inline int getAibo() {return aibo;};  
  /** Ritorna il tipo di pacchetto. @return pkg_type tipo di
      pacchetto*/
  virtual inline pkg_type getType() { return type;};  
  /** Ritorna la dimensione dell'array di byte. ATTENZIONE: Il valore
      restituito dalla funzione e' significativo solo se chiamato dopo
      il cotruttore TelepatiPkg(byte* ptr) oppure dopo il metodo
      getMsg(). @return size_t dimensione dell'array di byte*/
  virtual inline size_t getSize() { return size; };  
  /** Richiesta di conferma del package. @return true se il package ha
      bisogno di un ack di conferma; false altrimenti*/
  virtual inline bool needConfirm() { return needAck; };  
  /** Ritorna il numero seriale del package. @return short seriale del
      pacchetto*/
  virtual inline unsigned short getSerial() { return serialNum; };  

  /** Restituisce un array rappresentante l'oggetto. L'array
      restituito viene utilizzato per spedire l'oggetto sia via rete
      sia per lo scambio di messaggi tra oggetti OPENR. Da
      implementare.  @return byte[] array di byte che rappresenta
      l'oggetto @see TelepatiPkg(const byte* ptr), createPkg(const
      byte* ptr)*/
  virtual byte* getMsg() = 0;  

  /** Crea un clone dell'oggetto su cui viene chimato. Utile per
      creare copie di un oggetto a partire da un oggetto, viene
      utilizzato per il broadcasting e per altre funzioni interne di
      Telepati. @return oggetto clonato*/
  virtual TelepatiPkg* clone() = 0;
  
  /** crea l'header standard del pacchetto. @param pkgDataSize
      dimensione di pkg data @return byte[] array di byte, di
      dimensione pari a pkgDataSize piu' la dimensione dello standard
      header, con i valori dell'header impostati correttamente*/
  byte* createStdHeader(size_t pkgDataSize); 
  
  /** PATTERN Simple Factory: costruisce un TelepatiPkg. A partire da
      un array di byte ricostrusce l'oggetto corretto richiamando il
      costruttore corretto e lo ritorna. @param ptr array di byte
      rappresentanti l'oggetto @return oggetto di tipo TelepatiPkg*
      corretto, 0 nel caso non riconosca il tipo di package @see
      TelepatiPkg(const byte* ptr), getMsg()*/
  static TelepatiPkg* createPkg(byte* ptr);  

  /** Calcola la dimensione di un Package in base al suo header. Dato
      il message del pacchetto calcola la dimesione del
      package. @return dimensione del package.*/
  static size_t getSizeOfPkg(byte* ptr);

  static const int ADDR_INVALID=254; /**< Indirizzo invalido.*/
  static const int ADDR_BROADCAST=255; /**< Indirizzo per il broadcast.*/
  static const size_t STD_HEADER_SIZE = 7;    /**< Dimensione dell'Header Standard*/

 protected:
  /** indice dell'aibo di destinazione*/
  int aibo;  
  /** tipo di messaggio*/
  pkg_type type;  
  /** dimensione dell'array rappresentante l'oggetto */     
  unsigned short size;  
  /** true: se ha bisogno di ricevere un Ack; false: altrimenti*/    
  bool needAck;  
  /** numero seriale del package*/ 
  unsigned short serialNum;  
  /** Array contenente i dati del message da spedire*/
  byte* message; 
};
#endif

