#ifndef __VARREC_H
#define __VARREC_H

#ifndef __ISAM_H
#include <isam.h>
#endif

#ifndef __EXPR_H
#include <expr.h>
#endif

class TVariable_rectype;

// @doc EXTERNAL
//
// @type VIRTUAL_GET_FUNCTION | Prototipo funzione di calcolo del valore di un campo virtuale 
//                              da definire quando non sia sufficente una semplice espressione
typedef const char * (*VIRTUAL_GET_FUNCTION)(TVariable_rectype & r);

// @doc EXTERNAL
//
// @class TVariable_field | Oggetto campo virtuale
//
// @base public | TObject
class TVariable_field : public TObject

// @author:(INTERNAL) Sandro

{ 
  TVariable_rectype * _rec;                
  TString _name;
  TExpression * _e;
  TString _value;
  TToken_string * _put_string;
  VIRTUAL_GET_FUNCTION _getfunc;
  bool _destroy_expression;
  bool _in_get;
  
public:
  // @access Public Member
  // @cmember Duplica il campo
  virtual TObject* dup() const;
// @cmember segnala che il campo deve essere ricalcolato
  virtual bool dirty() const { return TRUE;}
// @cmember assegna lo stato di campo da ricalcolare
  virtual void set_dirty(bool on = TRUE) {}
// @cmember assegna lo stato di campo da non ricalcolare
  void set_clean() { set_dirty(FALSE);}
// @cmember assegna il record a cui appartiene il campo
  virtual void set_rec(TVariable_rectype * rec) { _rec = rec;}
  

// @cmember ritorna il nome del campo
  const char * name() const { return _name;}
// @cmember ritorna il valore del campo
  TString & get() const;
// @cmember aggiorna il valore del campo utilizzando <p val> 
  void put(const char * val);
// @cmember aggiorna il valore del campo utilizzando <p val> indipendentemente dal tipo del campo variabile
  void force_value(const char * val) { _value = val; set_clean(); }
// @cmember azzera il valore del campo 
  void zero();
// @cmember il campo non ha formule o funzioni collegate
  bool plain() const 
  { return _e == NULL && _getfunc == NULL;}

// @ cmember Costruttore con una espressione di calcolo  
  TVariable_field(const char * name, const char * expr = "", TTypeexp type = _strexpr);
// @ cmember Costruttore con una funzione
  TVariable_field(const char * name, VIRTUAL_GET_FUNCTION getfunc);
// @ cmember Costruttore con una espressione di calcolo  
  TVariable_field(const char * name, TExpression * expr, TTypeexp type = _strexpr);
// @ cmember Costruttore con un variable_field 
  TVariable_field(const TVariable_field & f);
// @ cmember Distruttore  
  ~TVariable_field();
};
               

// @doc EXTERNAL

// @class TVariable_rectype | Classe per la definizione del  record di file con campi virtuali (variabili)

// @base public | TRectype
class TVariable_rectype : public TRectype

// @author:(INTERNAL) Sandro

{
// @access:(INTERNAL) Private Member
  TAssoc_array        _virtual_fields;  
  TString16           _memo_fld; 
  bool                _memo_fld_to_load;   

protected:
  // @cmember Segnalazione di un campo inesistente
  virtual void unknown_field(const char* name) const;                    
  // @cmember Indica se il record implementa i campi variabili automatici
  virtual bool auto_virtual_fields() const { return TRUE; }
  // @cmember Ritorna il contenuto del campo <p fieldname> (non tipizzata)
  virtual const TString & get_str(const char* fieldname) const ;
  // @cmember Setta il contenuto del campo <p fieldname> (non tipizzata)
  virtual void put_str(const char* fieldname, const char* val);
  //  void put(const char* fieldname, TString& val);

public:
  // @access Public Member
  // @cmember Duplica il tipo di record
  virtual TObject* dup() const;

  // @cmember Setta il record come non vuoto (chiama <mf TRectype::setempty>

  virtual TFieldtypes type(const char* fieldname) const;
  // @cmember Ritorna la lunghezza del campo <p fieldname>
  virtual int length(const char* fieldname) const;
  // @cmember Ritorna numero di decimali del campo <p fieldname>
  virtual int ndec(const char* fieldname) const;
  // @cmember Indica se esiste il campo <p fieldname>
  virtual bool exist(const char* fieldname) const;

  // @cmember Vuota il campo puntato da <p fieldname>
  virtual void zero(const char * fieldname);
  // @cmember Vuota tutto il record usando il carattere <p c>
  virtual void zero(char c = '\0');

  // @cmember Assegnazione tra TVariable_rectype e TRectype
  virtual TRectype & operator =(const TRectype& rec);
  // @cmember Assegnazione tra TVariable_rectype
  virtual TVariable_rectype & operator =(const TVariable_rectype& rec);
  // @cmember Assegnazione tra TRectype const char *
  virtual TRectype & operator =(const char* rec);

                                                                
  void set_memo_fld(const char * fieldname);
  void reset_memo_fld() { set_memo_fld(NULL); }                                                              
  virtual void init_memo(const TRecnotype recno  = RECORD_NON_FISICO);
  virtual void write_memo(isdef * file, const TRecnotype recno);

  virtual void add_field(TVariable_field * f);
  virtual void remove_field(const char * fieldname = NULL);
  
  TVariable_field * first_variable_field() { return (TVariable_field *) _virtual_fields.first_item();}
  TVariable_field * succ_variable_field()  { return (TVariable_field *) _virtual_fields.succ_item();}
  TVariable_field * pred_variable_field()  { return (TVariable_field *) _virtual_fields.pred_item();}
  TVariable_field * last_variable_field()  { return (TVariable_field *) _virtual_fields.last_item();}
//  virtual const char * get_variable_field_names(bool restart = FALSE) ;
  
  // @cmember Costruttore Costruisce un record staccato da un file.
  //          Sarebbe meglio utilizzare una delle altre due
  TVariable_rectype(int logicnum);
  // @cmember Costruttore. Costruisce record e lo associa al file isam <p i>
  TVariable_rectype(const TBaseisamfile* i);
  // @cmember Costruttore. Costruisce il record a partire da <p r>
  TVariable_rectype(const TRectype & r);
  // @cmember Costruttore. Costruisce il record a partire da <p r>
  TVariable_rectype(const TVariable_rectype & r);

  // @cmember Distruttore
  virtual ~TVariable_rectype() {}
};

// @doc EXTERNAL

// @class TAuto_variable_rectype | Classe per la definizione del  record di file con campi virtuali (variabili)

// @base public | TVariable_rectype
class TAuto_variable_rectype : public TVariable_rectype

// @author:(INTERNAL) Sandro
                                                 
                                                 
{      
protected:
  virtual bool auto_virtual_fields() const { return TRUE; }

public:                                                
  // @cmember Costruttore Costruisce un record staccato da un file.
  //          Sarebbe meglio utilizzare una delle altre due
  TAuto_variable_rectype(int logicnum) : TVariable_rectype(logicnum) {}
  // @cmember Costruttore. Costruisce record e lo associa al file isam <p i>
  TAuto_variable_rectype(const TBaseisamfile* i) : TVariable_rectype(i) {}
  // @cmember Costruttore. Costruisce il record a partire da <p r>
  TAuto_variable_rectype(const TRectype & r) : TVariable_rectype(r) {}
  // @cmember Costruttore. Costruisce il record a partire da <p r>
  TAuto_variable_rectype(const TVariable_rectype & r) : TVariable_rectype(r) {}

  // @cmember Distruttore
  virtual ~TAuto_variable_rectype() {}
};

#endif // __VARREC_
