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

// @doc EXTERNAL

// @class TRelation_application | Classe per la gestione di una apllicazione di manutenzione di uno
//                                o piu' archivi utilizzando una relazione
//
// @base public | TApplication
class TRelation_application : public TApplication

// @author:(INTERNAL) Guido

// @access:(INTERNAL) Private Member
{
  // @cmember:(INTERNAL) Maschera corrente dell'applicazione
  TMask* _mask;
  // @cmember:(INTERNAL) Array di chiavi della maschera
  TKey_array* _maskeys;
  // @cmember:(INTERNAL) Primo record
  TRecnotype _first;
  // @cmember:(INTERNAL) Ultimo record
  TRecnotype _last;
  // @cmember:(INTERNAL) Campo da utilizzare col bottone Ricerca
  int _search_id;
  
  // @cmember:(INTERNAL) Nome del programma chiamante
  TString16 _autoins_caller;
  // @cmember:(INTERNAL) Numero del record nuovo/editato
  long _recins;

  // @cmember:(INTERNAL) Indica se e' stato chiamato col messaggio di link
  bool _lnflag;
  // @cmember:(INTERNAL) Contiene il codice del campo e il valore fisso
  TToken_string _fixed;     
  // @cmember:(INTERNAL) Messaggio da passare all'utente per inidicare che e' stata fatta la rinumerazione
  TString _renum_message;
  
  // @cmember:(INTERNAL) Setta i campi fissati da <md TRelation_application::_fixed>
  bool filter();
  // @cmember:(INTERNAL) Controlla se una chiave e' completa ed esiste su file
  bool test_key(byte k, bool err);
  // @cmember:(INTERNAL) Salva i contenuti della maschera su file
  bool save(bool check_dirty);
  // @cmember:(INTERNAL) Abilita la ricerca sulla maschera
  void enable_query();
  // @cmember:(INTERNAL) UNUSED
  void set_toolbar(bool all);
  
  // @cmember:(INTERNAL) Seleziona il nuovo modo e ritorna il vecchio
  int set_mode(int mode);
  // @cmember:(INTERNAL) Setta i limiti
  void set_limits(byte what = 0x3);
  // @cmember:(INTERNAL) Posiziona l'applicazione in modo richiesta/inserimento (chaima <mf TRelation_application::query_mode>)
  void query_insert_mode()
  { query_mode(TRUE); }
  // @cmember:(INTERNAL) Entra in modo inserimento
  void insert_mode();
  // @cmember:(INTERNAL) Cancella il record corrente
  bool relation_remove();
  // @cmember:(INTERNAL) Ritorna il campo di ricerca della maschera
  TMask_field* get_search_field() const;

  // @cmember:(INTERNAL) Permette di autonumerare un record
  bool autonum(TMask* m, bool rec);
  // @cmember:(INTERNAL) Controlla se il <c TCursor> ha un filtro
  bool has_filtered_cursor() const 
  { return filtered() || force_cursor_usage();}

// @access Protected Member
protected:
  // @cmember Effettua i controlli all'inizio dell'applicazione
  virtual bool create();
  // @cmember Effettua i controlli alla fine dell'applicazione
  virtual bool destroy();
  // @cmember Controlla se e' possibile modificare la ditta corrente durante l'esecuzione dell'applicazione
  virtual bool firm_change_enabled() const;

protected:
  // @cmember Ritorna il descrittore del file principale della relazione
  TLocalisamfile& file() const
  { return get_relation()->lfile(); }
  // @cmember Ritorna il primo record
  TRecnotype first() const 
  { return _first;}
  // @cmember Ritorna l'ultimo record
  TRecnotype last() const 
  { return _last;}
  // @cmember Ritorna il nome del programma chiamante
  const TString& autoins_caller() const 
  { return _autoins_caller;}

  // @cmember Gestisce la barra dei menu' (chiama <mf TRelation_application::main_loop>)
  virtual bool menu(MENU_TAG m);
  // @cmember Ciclo principale
  virtual bool main_loop();

  // @cmember Inizializzazione dei dati dell'utente
  virtual bool user_create() pure;
  // @cmember Distruzione dei dati dell'utente
  virtual bool user_destroy() pure;
  
  // @cmember Fissa i campi non modificabili
  void set_fixed();
  // @cmember Attiva la maschera di ricerca
  bool search_mode();
  // @cmember Entra in modo di ricerca
  void query_mode(bool pre_ins = FALSE);
  // @cmember Entra in modo modifica
  bool modify_mode();
  // @cmember Legge i campi chiave della maschera e setta il cursore relativo
  void setkey();
  // @cmember Ritorna se e' stato chiamato col messaggio di link
  bool lnflag() const 
  { return _lnflag;}
  // @cmember Indica se la futura <mf TRelation_application::get_mask> ritornera' una maschera diversa
  //	      dalla corrente.
  //	      <nl>La richiesta della maschera da utilizzare per ogni fase di lavoro 
  // 	      (ricerca, inserimento, modifica) avviene sempre in due tempi: <mf TRelation_application::changing_mask> e 
  //	      <mf TRelation_application::get_mask>.  Cio' serve per gestire correttamente le applicazioni
  //  	      con mashere multiple.
  virtual bool changing_mask(int mode) pure;
  // @cmember Richiede la maschera da usare
  virtual TMask* get_mask(int mode) pure;

  // @cmember Forza la rigenerazione della lista interna di chiavi ad ogni <mf TRealtion_application::find>
  virtual bool changing_keys() const 
  { return FALSE; }
  
  // @cmember Ritorna la relazione da modificare
  virtual TRelation* get_relation() const pure;
  // @cmember Legge dalla relazione i valori nella maschera <p m>
  virtual int read(TMask& m);
  // @cmember Scrive sulla relazione i valori dalla maschera <p m>
  virtual int write(const TMask& m);
  // @cmember Riscrive sulla relazione i valori dalla maschera <p m>
  virtual int rewrite(const TMask& m);
  // @cmember Cancella il record corrente
  virtual bool remove();
  
  // @cmember Richiede una stringa nella forma CAMPO1<pipe>VALORE1<pipe>CAMPO2<pipe>VALORE2<pipe>...
  //	      <pipe>CAMPOn<pipe>VALOREn contenente le coppie NUMERO_CAMPO_MASCHERA - VALORE_DA_ASSEGNARE
  //          che descrivono il prossimo codice libero da utilizzare per la autonumerazione.
  // 	      <nl>Nel caso di banale numerazione progressiva potrebbe essere implementata come
  // 	      return format("%d<pipe>%s", F_NUM, get_relation()-<gt>items());
  virtual const char* get_next_key()
  { return ""; }
  
  // @cmember Richiede se il record corrente e' protetto (non cancellabile)
  virtual bool protected_record(TRectype&) 
  { return FALSE; }
  
  // @cmember Inizializza la maschera per il modo ricerca
  virtual void init_query_mode(TMask&) 
  { }   
  // @cmember Inizializza la maschera per il modo ricerca ed inserimento (chiama <mf TRelation_application::init_query_mode>)
  virtual void init_query_insert_mode(TMask& m) 
  { init_query_mode(m); }
  // @cmember Inizializza la maschera per il modo inserimento
  virtual void init_insert_mode(TMask&) 
  { }  
  // @cmember Inizializza la maschera per il modo modifica
  virtual void init_modify_mode(TMask&) 
  { }  
  
  // @cmember Simula l'utilizzo di un filtro da un'altra applicazione
  virtual bool force_cursor_usage() const 
  { return FALSE;}
  // @cmember Indica se abilitare/disabilitare la scrittura sul file 
  //	      principale (vedi <mf TRealtion::write_enable>)
  virtual void write_enable(bool on = TRUE) 
  { get_relation()->write_enable(0, on); }
  // @cmember Indica se disabilitare la scrittura sul file principale (vedi <mf TRealtion::write_enable>)
  void write_disable() 
  { write_enable(FALSE); }

  // @cmember Salva il record corrente e si predispone per un nuovo inserimento  
  virtual bool save_and_new() const;
  
  // @cmember Impone il campo da utilizzare col bottone Ricerca
  void set_search_field(short id) 
  { _search_id = id;}  

// @access Public Member  
public:
  // @cmember Ritorna la maschera corrente
  TMask& curr_mask() const 
  { return *_mask; }

  // @cmember Ritorna se sono stati posti dei filtri sul file corrente
  bool filtered() const 
  { return _fixed.not_empty(); }
  // @cmember Cerca un record corrispondete alla chiava <p key> (0 prima chiave completa)
  bool find(byte key = 0);
  // @cmember Costruisce il membro <md TRelation_application::_fixed>
  void set_link(TMask & m, const char * keyexpr);

  // @cmember Costruttore
  TRelation_application();
  // @cmember Distruttore
  virtual ~TRelation_application();
};

#endif