#ifndef __MAILBOX_H
#define __MAILBOX_H

#ifndef __STRINGS_H
#include <strings.h>
#endif

// TMessage flags
#define MSG_READ (0x01)

// @doc EXTERNAL

// @class TMessage | Classe per il passaggio dei messaggi base tra applicazioni
//                   e linea di comando
//
// @base public | TObject
class TMessage : public TObject

// @author:(INTERNAL) Villa
  

{
  // @cfriend TMailbox
  friend class TMailbox;  
  
  // @access:(INTERNAL) Private Member

  // @cmember:(INTERNAL) Applicazione che lancia il messaggio
  TString _from;
  // @cmember:(INTERNAL) Applicazione che deve ricevere il messaggio
  TString _to;
  // @cmember:(INTERNAL) Oggetto del messaggio
  TString _subject;
  // @cmember:(INTERNAL) Testo del messaggio
  TString _text;
  // @cmember:(INTERNAL) Flag di controllo del messaggio
  byte _flags;
  // #cmember Numero (non si sa cosa faccia)
  //  int _number;  

  // @access Protected Member
protected:
  // @cmember Indica che il messaggio e' stato letto
  void setread()
  { _flags |= MSG_READ; }
  // @cmember Controlla se il messaggio e' stato letto (TRUE se e' stato letto)
  bool isread()
  { return _flags & MSG_READ; }
  // #cmember Setta il numero. Se viene passato -1 ritorna il valore attuale
  //  int number(int n = -1)
  //  { return (n == -1 ? _number : (_number = n)); }

  // @access Public Member
public:
  // @cmember Ritorna il nome dell'applicazione che lancia il messaggio
  const TString& from() const
  { return _from; }
  // @cmember Ritorna il nome dell'applicazione che deve ricevere il messaggio
  const TString& to() const
  { return _to; }
  // @cmember Ritorna l'oggetto del messaggio
  const TString& subject() const
  { return _subject; }
  // @cmember Ritorna il testo del messaggio
  const TString& body() const
  { return _text; }

  // @cmember Assegna il nome dell'applicazione che lancia il messaggio
  const TString& from(const char* f)
  { return _from = f; }
  // @cmember Assegna il nome dell'applicazione che deve ricevere il messaggio
  const TString& to(const char* t)
  { return _to = t; }
  // @cmember Assegna l'oggetto del messaggio
  const TString& subject(const char* s)
  { return _subject = s; }
  // @cmember Assegna il testo del messaggio
  const TString& body(const char* b)
  { return _text = b; }
  
  // @cmember Manda il messaggio
  void send();

  // @cmember Costruttore
  TMessage(const char* to, const char* sub, const char* text, const char* from = NULL);
  virtual ~TMessage() { }
};

// @class TMailbox | Classe per controllare i messaggi ricevuti da una applicazione
//
// @base public | TObject
class TMailbox : public TObject

// @author:(INTERNAL) Villa

// @access:(INTERNAL) Private Member
{

  // @cmember:(INTERNAL) Nome del file che contiene i messaggi
  TFilename _path;
  // @cmember:(INTERNAL) Array di messaggi ricevuti
  TArray _msgs;
  // @cmember:(INTERNAL) Numero dell'ultimo messaggio letto
  int _lastread;
  // @cmember:(INTERNAL) Numero di messaggi in attesa di lettura
  int n_new;
  // @cmember:(INTERNAL) Posizione nel file dell'ultimo messaggio letto
  long _lastpos;
  // @cmember:(INTERNAL) Indice dei messaggi letti e non letti
  int _cnt;

  // @access Protected Member
protected:

  // @cmember Legge un nuovo messaggio dalla mailbox. Crea messaggi, mette i
  //          messaggi nell'array in ordine cronologico
  void reread();
  // @cmember Ritorna il prossimo messaggio letto (NULL se non e' stato letto)
  TMessage* next_read();
  // @cmember Ritorna il prossimo messaggio non letto
  TMessage* next_unread();

  // @access Public Member
public:

  // @cmember Ritorna il numero di messaggi in attesa
  int check()
  { reread(); return n_new; }
  // @cmember Reinizializza la fase di lettura
  void restart()
  { _cnt = 0;}
  // @cmember Ritorna in numero di messaggi, letti e da leggere, presenti nella mailbox
  int items()
  { return _msgs.items(); }
  // @cmember Ritorna il prossimo messaggio
  TMessage* next(bool read = FALSE);
  // @cmember Ritorna il prossimo messaggio con lo stesso oggetto
  TMessage* next_s(const char* s, bool read = FALSE);
  // @cmember Ritorna il prossimo messaggio con lo stesso mandante
  TMessage* next_f(char* f, bool read = FALSE);
  // @cmember Manda un messaggio
  void send(TMessage& m);
  // @cmember Trasforma gli argomenti della command line in messaggi mail (NON IMPLEMENTATA)
  void sendcmd(int argc, char* argv[],char* to);
  // @cmember Trasforma una mailbox in parametri per la command line per la
  //          chaimata di applicazioni non compilanti (NON IMPLEMENTATA)
  char*  readcmd(char* to = NULL);
  // @cmember Ritorna l'<p n>-esimo messaggio
  TMessage* get(int n)
  { return (TMessage*)_msgs.objptr(n); }

  // @cmember Costruttore
  TMailbox::TMailbox(const char* appname = NULL);
  // @cmember Distruttore
  virtual ~TMailbox();
};

// @todo Da implementare in futuro
//
// instead of using commandline args directly, user posts
// messages to application, then calls it without arguments
// If the application is called by the user with command_line
// arguments, sendcmd parses them and translates to messages
// according to the following rules: 
//       
//    from is "cmdline"
//    
//    subject comes from arguments of type -opt=value
//    (opt becomes subject and value becomes body)
//
//    args like -opt="val, val, val" create
//    one message for each val, with the same subject=opt
//
//    -opt arg creates subject=opt and empty body
//
//    one-word arguments create a message with "null" subject
// 
// A mailbox should be member of applicat and sendcmd should be
// called automatically upon startup 
// Non compliant applications (which do not use mailbox) can be 
// called consistently by sending messages, 
// appending TMailbox::readcmd(appname) to
// their name and doing an exec()

#endif