#ifndef __RELAPP_H
#define __RELAPP_H

#ifndef __APPLICAT_H
#include <applicat.h>
#endif

#ifndef __RELATION_H
#include <relation.h>
#endif

#ifndef __MASK_H
#include <mask.h>
#endif

class TKey_array;

class TRelation_application : public TApplication
{
  TMask * _mask;
  TKey_array* _maskeys;
  TRecnotype _first, _last;
  int    _search_id;
  
  TString16 _autoins_caller;
  long _recins;

  bool _lnflag;
  TToken_string _fixed;
  
  virtual bool create();
  virtual bool destroy();
  
  bool filter();
  bool test_key(byte k, bool err);
  bool save(bool check_dirty);
  void enable_query();
  void set_toolbar(bool all);
  
  int set_mode(int mode);       // Seleziona il nuovo modo e ritorna il vecchio
  void set_limits(byte what = 0x3);
  void query_insert_mode() { query_mode(TRUE); }
  void insert_mode();   // Entra in modo inserimento
  virtual bool main_loop();       // Ciclo principale
  bool relation_remove();                       // Cancella il record corrente
  TMask_field*  get_search_field() const;

  bool autonum(TMask* m, bool rec);
  bool has_filtered_cursor() const { return filtered() || force_cursor_usage();}

protected:
  TLocalisamfile& file() const { return get_relation()->lfile(); } // File principale della relazione
  TRecnotype first() const { return _first;}
  TRecnotype last() const { return _first;}
  TMask& curr_mask() const { return *_mask; }
  const TString& autoins_caller() const { return _autoins_caller;}
  virtual bool menu(MENU_TAG m);

  virtual bool user_create() pure;                // Inizializzazione dati utente
  virtual bool user_destroy() pure;               // Distruzione dati utente
  
  void set_fixed();                             // Fissa i campi non modificabili
  bool search_mode();                           // Attiva la maschera di ricerca
  void query_mode(bool pre_ins = FALSE);        // Entra in modo ricerca
  bool modify_mode();                           // Entra in modo modifica
  void  setkey();
  bool lnflag() const { return _lnflag;}
  // La richiesta della maschera da utilizzare per ogni fase di lavoro (ricerca, inserimento, 
  // modifica avviene sempre in due tempi: changing_mask e get_mask.  Cio' serve per gestire
  // Correttamente le applicazioni con mashere multiple.  La prima funzione serve a sapere se
  // la futura get_mask ritornera' una maschera diversa dalla corrente.
  virtual bool changing_mask(int mode) pure;      
  virtual TMask* get_mask(int mode) pure;           // Richiede la maschera da usare
  
  virtual TRelation* get_relation() const pure;     // Relazione da modificare
  virtual int read(TMask& m);                       // Legge dalla relazione i valori nella maschera
  virtual int write(const TMask& m);                // Scrive sulla relazione i valori dalla maschera
  virtual int rewrite(const TMask& m);              // Riscrive sulla relazione i valori dalla maschera
  virtual bool remove();                            // Cancella il record corrente
  
  // Richiede una stringa nella forma CAMPO1|VALORE1|CAMPO2|VALORE2|...|CAMPOn|VALOREn
  // contenente le coppie NUMERO_CAMPO_MASCHERA - VALORE_DA_ASSEGNARE che descrivono il
  // prossimo codice libero da utilizzare per la autonumerazione.
  // Nel caso di banale numerazione progressiva potrebbe essere implementata come
  // return format("%d|%s", F_NUM, get_relation()->items());
  virtual const char* get_next_key() { return ""; }
  
  // Richiede se il record corrente e' protetto (non cancellabile)
  virtual bool protected_record(TRectype&) { return FALSE; }
  
  virtual void init_query_mode(TMask&) { }   // Inizializza la maschera per il modo ricerca
  virtual void init_query_insert_mode(TMask& m) { init_query_mode(m); }
  virtual void init_insert_mode(TMask&) { }  // Inizializza la maschera per il modo inserimento
  virtual void init_modify_mode(TMask&) { }  // Inizializza la maschera per il modo modifica
  
  virtual bool force_cursor_usage() const { return FALSE;}
  virtual void write_enable(const bool on = TRUE) { get_relation()->write_enable(-1, on); }
  void write_disable() { write_enable(FALSE); }
  
  virtual bool save_and_new() const;
  
  void set_search_field(short id) { _search_id = id;}  // Impone il campo da utilizzare col bottone Ricerca
  
public:
  TRelation_application();
  virtual ~TRelation_application();
  bool filtered() const { return _fixed.not_empty(); }
  bool find(byte key = 0);
  void set_link(TMask & m, const char * keyexpr);
};

#endif