#ifndef __PREFIX_H
#define __PREFIX_H

#ifndef __EXTCTYPE_H
#include <extctype.h>
#endif

#ifndef __RECTYPES_H
#include <rectypes.h>
#endif

#ifndef __ASSOC_H
#include <assoc.h>
#endif

class TFile_info;
class TRecord_info;
class TTrec;

typedef int TIsam_handle;

class TFile_manager : public TObject
{
  TArray _fileinfo;
  TArray _recinfo;   
  int _open_files, _max_open_files;

protected:
  TFile_info& fileinfo(TIsam_handle handle) const;
  TRecord_info& recinfo(int logicnum) const;

  bool close_oldest();

public:
  TIsam_handle open(int& logicnum, TFilename& name, bool excl, bool idx);
  int close(TIsam_handle& name);

  void lock_record(TIsam_handle num, TRecnotype rec);
  void unlock_record(TIsam_handle num, TRecnotype rec);

  const TFilename& get_filename(TIsam_handle num) const;
  const FileDes& get_filedes(TIsam_handle num) const;
  const RecDes& get_recdes(int logicnum) const;
  TIsam_handle get_handle(TFilename& name);
  const RecDes& update_recdes(int logicnum);
  TDirtype get_dirtype(int logicnum);
  bool add_recdes(int logicnum, TTrec& rec, TToken_string& keys);

  TCodeb_handle get_handle(TIsam_handle name, int key);
  int get_reclen(int logicnum);

  void notify_change(TIsam_handle name);
  long last_change(TIsam_handle name) const;

  int close_closeable();
  void close_all();
  void open_all();

  TFile_manager();
  virtual ~TFile_manager() { }
};

// @doc EXTERNAL

// @class TFirm | Classe contenente le informazioni sulla ditta correntemente in uso
//
// @base public | TObject     
class TFirm : public TObject
{ 
  TAssoc_array _rec;

protected:  
  const TString& get(const char* attr) const;
  long get_long(const char* attr) const;
  
public:
  bool read(long code);
  TFirm& operator=(long code) { read(code); return *this; }
  
  long codice() const;
  const TString& codice_valuta() const;
  
  virtual bool ok() const { return codice() > 0L; }

  TFirm(long code = -1L);
  virtual ~TFirm() { }
};

// @doc EXTERNAL

// @class TPrefix | Classe contenente le informazioni sulla ditta correntemente in uso
//
// @base public | TObject     
class TPrefix : public TObject

// @author:(INTERNAL) Alex
{
  // @access:(INTERNAL) Private Member
  
  // @cmember:(INTERNAL) Contenuto del file "prefix.txt"
  TString _prefix; 

  // @cmember:(INTERNAL) Livello degli archivi
  unsigned int _filelevel, _stdlevel;
  // @cmember:(INTERNAL) Numero di files esitenti
  int _items;

  TFile_manager _manager;

  TFirm* _firm;
  
  
// @access Private Member
private:        
  int closeall(bool changestudy, TBit_array& excl, TBit_array& toclose) const;
  void openall(bool changestudy, TBit_array& excl, int oldmax, TBit_array& toopen) const;
  
  // @access Protected Member
protected:        
  // @cmember Verifica l'effettiva esistenza della directory <p s> sotto 
  //          la directory dati 
  bool test(const char* s) const ;
  
  // @access Public Member          
public:  
  // @cmember Setta la ditta corrente
  void set(const char* name = NULL, bool force = FALSE, TFilelock mode = _manulock);
  // @cmember Controlla l'esistenza di un codice ditta
  bool exist(long codditta) const;
  // @cmember Controlla l'esistenza di un codice ditta e che non sia in uso
  bool test(long codditta) const;
  // @cmember Ritorna il codice della ditta corrente
  long get_codditta() const ;
  // @cmember Setta il codice della ditta corrente
  bool set_codditta(long codditta, bool force = FALSE);
  // @cmember Ritorna lo studio corrente
  const char* get_studio() const;
  // @cmember Setta lo studio corrente
  bool set_studio(const char* study, long firm = 0);
  // @cmember Ritorna il contenuto della variabile <p _prefix>
  const char* name() const 
  { return _prefix;}
  // @cmember Ritorna il livello degli archivi
  unsigned int filelevel() const 
  {return _filelevel;} 

  // @cmember Ritorna il livello standard degli archivi
  unsigned int get_stdlevel() const { return _stdlevel; } 
  void set_stdlevel(unsigned int sl) { _stdlevel = sl; } 
  
  // @cmember Ritorna il numero di archivi
  int items() const 
  { return _items; }
  // @cmember Ritorna la descrizione del file passato
  const char* description(const char* cod) const;
  // @cmember Ritorna la descrizione del file passato
  const char* description(int cod) const;
  // @cmember Controlla che la ditta attiva sia una ditta (e non es. dati comuni)
  bool is_firm() const 
  { return _prefix.len() == 6 && (_prefix[5] == 'A' || _prefix[5] == 'a'); }
  // @cmember Controlla che siano attivi i dati comuni (e non una ditta)
  bool is_com() const  
  { return !is_firm();}
  // @cmember Crea gli archivi dii una nuova ditta
  bool build_firm_data(long codditta, bool flagcom = FALSE);
  // @cmember Riapre tutti gli archivi della ditta attiva
  void reopen() const ;

  TIsam_handle open_isamfile(int& logicnum, TFilename& name, bool excl = FALSE, bool idx = TRUE)
  { return _manager.open(logicnum, name, excl, idx); }

  int close_isamfile(TIsam_handle& name)
  { return _manager.close(name); }

  void lock_record(TIsam_handle num, TRecnotype rec);
  void unlock_record(TIsam_handle num, TRecnotype rec);

  int close_closeable_isamfiles()
  { return _manager.close_closeable(); }

  TDirtype get_dirtype(TIsam_handle name)
  { return _manager.get_dirtype(name); }

  int get_handle(TIsam_handle name, int key = 0)
  { return _manager.get_handle(name, key); }

  TIsam_handle get_handle(TFilename& name)
  { return _manager.get_handle(name); }

  const RecDes& get_recdes(int logicnum) const
  { return _manager.get_recdes(logicnum); }

  bool add_recdes(int logicnum, TTrec& rec, TToken_string& keys)
  { return _manager.add_recdes(logicnum, rec, keys); }

  const RecDes& update_recdes(int logicnum)
  { return _manager.update_recdes(logicnum); }

  int get_reclen(int logicnum)
  { return _manager.get_reclen(logicnum); }

  const FileDes& get_filedes(TIsam_handle name) const
  { return _manager.get_filedes(name); }
 
  const TFilename& get_filename(TIsam_handle name) const
  { return _manager.get_filename(name); }

  void notify_change(TIsam_handle name)
  { _manager.notify_change(name); }

  long last_change(TIsam_handle name) const
  { return _manager.last_change(name); }

  const TFirm& firm();

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


const char* firm2dir(long codditta);
int safely_close_closeable_isamfiles();

TPrefix& prefix_init(); 
bool prefix_valid();
TPrefix& prefix();
void prefix_destroy();

#endif // __PREFIX_H