#include <relation.h>
#include <relapp.h>
#include <tree.h>
#include <mask.h>

#include "ablib09.h"
#include "analisi.h"
#include "relvoci.h"
#include "relana.h"
#include "saldi.h"
#include "movdett.h"
#include "voci.h"
#include "caradd.h"
#include "colldich.h"

#define MAX_ID_REL 999999999
#define MAX_ID_MOVDETT 999999
#define NODO_AGGIUNTO "A"
#define NODO_MODIFICATO "M"
#define NODO_RIMOSSO "R"
#define IMMESSO 'I'
#define TRASFERITO 'T'

#define TIPO_ANALISI "A"
#define TIPO_VOCE    "V"
#define ID_NULLO 0
#define ID_NULLO_STR "0"

typedef real TNumeric_id;


class TAlbero_movdett : public TBidirectional_tree
{
  TToken_string _codtab;
  TLocalisamfile *_movdett;
protected:
  virtual void node2id(const TObject * node,TString & id) const;
public:
  virtual bool has_son() const;
  virtual bool has_rbrother() const;
  virtual bool has_father() const;
  virtual bool has_lbrother() const;
  virtual bool goto_root();
  virtual bool goto_firstson();
  virtual bool goto_father();
  virtual bool goto_rbrother();
  virtual bool goto_lbrother();
  virtual bool goto_node(TString & id)
    {return(_movdett->readat(atol(id))==NOERR); }
  virtual TObject * curr_node() const;
  bool goto_id(const TNumeric_id &id);
  TRectype & curr() {return (TRectype &)*curr_node();}
  
  TAlbero_movdett( const char * tabcode);
  virtual ~TAlbero_movdett();
};
  
  
//Classe per gestire l'albero di relana
class TAlbero_relana : public TBidirectional_tree
{
  TString _codtab;
  TLocalisamfile *_relana;
  TNumeric_id _last_id;
protected:
  virtual void node2id(const TObject * node,TString & id) const;
public:
  void zero_id() {_last_id = 0;}
  virtual bool has_son() const;
  virtual bool has_rbrother() const;
  virtual bool has_father() const;
  virtual bool has_lbrother() const;
  virtual bool goto_root();
  virtual bool goto_firstson();
  virtual bool goto_father();
  virtual bool goto_rbrother();
  virtual bool goto_lbrother();
  virtual bool goto_node(TString & id)
    {return(_relana->readat(atol(id))==NOERR); }
  virtual TObject * curr_node() const;
  bool goto_id(const TNumeric_id &id);
  TRectype & curr() {return (TRectype &)*curr_node();}
  bool lock();
  void unlock();
  TNumeric_id &new_id(real id);
  
  TAlbero_relana( const char * tabcode);
  virtual ~TAlbero_relana();
};

//Classe per gestire la struttura di una tabella di analisi
// basandosi sull'albero di relvoci
class TAlbero_relvoci : public TTree
{
  TString _codtab;
  TLocalisamfile *_relvoci;
protected:
  virtual void node2id(const TObject* node, TString& id) const;
public:
  virtual bool goto_root();
  virtual bool has_son() const;
  virtual bool goto_firstson();
  virtual bool has_rbrother() const;
  virtual bool goto_rbrother();
  virtual TObject * curr_node() const;
  virtual bool goto_node(const TString &id)
    {return (_relvoci->readat(atol(id))==NOERR);}
  bool has_lbrother() const;
  bool goto_lbrother();
  TRectype & curr() {return (TRectype &)*curr_node();}
  bool lock();
  void unlock();
  const TString & codtab()
    {return _codtab;}
  
  TAlbero_relvoci(const char * tabcode);
  virtual ~TAlbero_relvoci() ;
};

// Struttura da albero basata su un file temporaneo cached
class TAlbero_locale : public TBidirectional_tree
{ 
  TLocalisamfile *_f;   // da rimuovere !!
  protected:
    TAssoc_array _status_node;
    TRWrecord_cache * _local_cache;
    TNumeric_id _last_insert_id;
    TRectype *_currnode;

    virtual const char * get_headkey() const {return NULL;}
    virtual const char * id_fieldname() const {return NULL;}
  public:
    // debug
    void write_cache() { _local_cache->flush(); }
    void clear_cache()
    {
      _local_cache->clear();
      _last_insert_id = 0;
    }
    
    virtual bool insert_node(TRectype &node, const TNumeric_id id_prec, const TNumeric_id id_padre, TNumeric_id id, const char trasf_immes = TRASFERITO) {return FALSE;}
    virtual bool delete_node(const TNumeric_id &id) {return FALSE;}
    virtual bool delete_tree() { return FALSE;}
    virtual void zero() {;}
    virtual bool make_root(TBaseisamfile & saldi) {return FALSE;}
    virtual void link_succ_zero(const TNumeric_id currid) {;}
    virtual void link_son_zero(const TNumeric_id currid) {;}
    virtual TObject * curr_node() const {return _currnode;}
    TRectype & current() const {return (TRectype &)*curr_node();}
    TRWrecord_cache & current_cache() const {return *_local_cache;}

    
    // ***** gestione interfaccia Database/copia locale
    virtual TRectype extract_dirtynode(TString &id, TString& status) { TRectype rec(*_currnode); return rec;}
    int dirty_nodes() { return _status_node.items();}
    void set_status_node(const TString &id, const char *status);
    TString* get_status_node(const TString &id) 
      {return (TString*)_status_node.objptr(id);}
      

    virtual void goto_node(const TNumeric_id id) {;}
    virtual void goto_node(TRectype &node) {*_currnode = node;}
    virtual bool goto_node(const TString & id) {TNumeric_id nid(id); goto_node(nid); return TRUE;}

    virtual void node2id(const TObject* node, TString& id) const  {;}
    virtual bool goto_firstson() {return FALSE;}
    virtual bool goto_rbrother() {return FALSE;}
    virtual bool goto_root() {return FALSE;}

/*    virtual const char * idfather_fieldname() const {return NULL;}
    virtual const char * idson_fieldname() const {return NULL;}
    virtual const char * idsucc_fieldname() const {return NULL;}
    virtual const char * idprec_fieldname() const {return NULL;}
    virtual void put_headkey(TRectype &) {;}
    
    virtual bool remove_subtree(const TNumeric_id lastnode_id) { return TRUE;}
    virtual TNumeric_id &new_id(TNumeric_id) { real i; return i;}
    virtual bool has_father() const {return TRUE;}
    virtual bool goto_father() {return TRUE;}
    virtual bool has_rbrother() const {return TRUE;}
    virtual bool has_lbrother() const {return TRUE;}    
    virtual bool goto_lbrother() {return TRUE;}
    virtual bool goto_son_first_level() {return TRUE;}
        virtual void curr_id(TString& id) const 
    { 
      node2id(curr_node(), id);
    }

*/

    TAlbero_locale(int filenum);
    virtual ~TAlbero_locale();
};

class TAlbero_locale_link : public TAlbero_locale
{
  
//  TLocalisamfile *_c;
//    TRWrecord_cache * _local_cache_carad;
  protected:

    virtual const char * idfather_fieldname() const pure ;
    virtual const char * idson_fieldname() const pure;
    virtual const char * idsucc_fieldname() const pure;
    virtual const char * idprec_fieldname() const pure;
    virtual const char * id_fieldname() const pure;
    virtual const char * get_headkey() const pure;
    virtual void put_headkey(TRectype &) pure;
    virtual void node2id(const TObject* node, TString& id) const 
    {
      const TRectype *rec = (const TRectype *)node;
      id = rec->get_real(id_fieldname()).string();
    }
    
    virtual bool remove_subtree(const TNumeric_id lastnode_id);
    virtual TNumeric_id &new_id(TNumeric_id);

  public:
    virtual bool insert_node(TRectype &node, const TNumeric_id id_prec, const TNumeric_id id_padre, TNumeric_id id, const char trasf_immes = TRASFERITO);
    virtual bool delete_node(const TNumeric_id &id);
    virtual bool delete_tree();
    virtual void zero();
    
    virtual void goto_node(const TNumeric_id id);
    virtual void goto_node(TRectype &node) {*_currnode = node;}
    virtual bool goto_node(const TString & id) {TNumeric_id nid(id); goto_node(nid); return TRUE;}

    virtual bool make_root(TBaseisamfile & saldi) pure;
    virtual bool get_description(TString& desc) const pure; 
    
    virtual bool has_son() const;
    virtual bool goto_firstson();
    virtual bool has_father() const;
    virtual bool goto_father();
    virtual bool has_rbrother() const;
    virtual bool goto_rbrother();
    virtual bool has_lbrother() const;
    virtual bool goto_lbrother();

    virtual bool goto_son_first_level();
//    virtual bool has_root() const {return FALSE;}
    virtual bool goto_root();
    virtual void link_succ_zero(const TNumeric_id currid);
    virtual void link_son_zero(const TNumeric_id currid);
    virtual TRectype extract_dirtynode(TString &id, TString& status);
    
    TAlbero_locale_link(int filenum);
    virtual ~TAlbero_locale_link() {;}
};

class TAlbero_locale_relvoci: public TAlbero_locale
{   
  protected:
//        virtual bool remove_subtree(const TNumeric_id lastnode_id);
  
  public:
    virtual bool insert_node(TRectype &node, const TNumeric_id id_prec, const TNumeric_id id_padre, TNumeric_id id, const char trasf_immes = TRASFERITO);
    virtual bool delete_node(const TNumeric_id &id);

    virtual bool goto_node(const TString &key);

/**********************/
    virtual bool delete_tree() { return FALSE;}
    virtual void zero() {;}
    virtual bool make_root(TBaseisamfile & saldi) {return FALSE;}
    virtual bool has_rbrother() const;
    virtual bool goto_rbrother();
    virtual bool has_lbrother() const;
    virtual bool goto_lbrother();
    virtual TRectype extract_dirtynode(TString &id, TString& status);
    TNumeric_id new_id();


//    virtual bool delete_tree();

//    virtual bool has_son() const;
//    virtual bool goto_firstson();
//    virtual bool has_father() const;
//    virtual bool goto_father();

//    virtual bool goto_son_first_level();

    TAlbero_locale_relvoci();
    virtual ~TAlbero_locale_relvoci() {;}
};

// Copia locale dell'albero di una tabella analisi
class TLocal_relana3 : public TAlbero_locale_link
{ 
  protected:
    virtual const char * idfather_fieldname() const {return ABRA_IDPADRE;}
    virtual const char * idson_fieldname() const {return ABRA_IDFIGLIO;}
    virtual const char * idsucc_fieldname() const {return ABRA_IDSUCC;}
    virtual const char * idprec_fieldname() const {return ABRA_IDPREC;}
    virtual const char * id_fieldname() const {return ABRA_ID;}
    virtual const char * get_headkey() const {return " ";}
    virtual void put_headkey(TRectype & node) {node.put(ABRA_CODAN,get_headkey());}
  public:
    virtual bool make_root(TBaseisamfile & saldi);
    virtual bool get_description(TString& desc) const; 
  
    TLocal_relana3();
    virtual ~TLocal_relana3();
};

// Copia locale dell'albero dei dettagli di un saldo
class TLocal_balance3 : public TAlbero_locale_link
{ 
  protected:
    virtual const char * idfather_fieldname() const {return ABMD_IDPADRE;}
    virtual const char * idson_fieldname() const {return ABMD_IDFIGLIO;}
    virtual const char * idsucc_fieldname() const {return ABMD_IDSUCC;}
    virtual const char * idprec_fieldname() const {return ABMD_IDPREC;}
    virtual const char * id_fieldname() const {return ABMD_ID;}
    virtual const char * get_headkey() const {return " | | | | ";}
    virtual void put_headkey(TRectype & node) ;
  public:
    virtual bool make_root(TBaseisamfile & saldi); 
    virtual bool get_description(TString& desc) const;  

    TLocal_balance3();
    virtual ~TLocal_balance3();
};

class TAlbero_AB: public TRectype
{
  protected:
    TAlbero_locale *_inter_tree;
    virtual int commit_body() const;
    virtual int read_body(bool lockstruct) {return 0;}  //DA FARE
    virtual void put_headkey(TRectype &rec) const {;} //DA FARE
    
    TRectype * _newrec; //buffer per l'inserimento dodo per nodo
 
  public:
    TAlbero_AB(int filenum);
    virtual ~TAlbero_AB();
    
    virtual int read(TBaseisamfile& analisi, word isop=_isequal, word lockop=_nolock);
    virtual int readat(TBaseisamfile& f, TRecnotype nrec, word lockop = _nolock);
    virtual int write(TBaseisamfile& analisi) const;
    virtual int rewrite(TBaseisamfile& analisi) const;
    virtual int remove(TBaseisamfile& f) const;
    virtual bool remove_node(const TNumeric_id &id) {return FALSE;}
    virtual bool insert_new_node() {return FALSE;}
    virtual void zero();
    TAlbero_locale * user_tree()
      {return _inter_tree;}
};




class TRecord : public TObject
{    
  TLocalisamfile *_r;   // da rimuovere !!
  protected:                         
    TAssoc_array _status_node_record;
    TRWrecord_cache * _local_cache_record;
    TRectype *_currrec;
    
  public:
    // debug
    void write_cache() { _local_cache_record->flush(); }
    TRectype & current_rec() const {return *_currrec;}
    TRWrecord_cache & current_cache_record() const {return *_local_cache_record;}
    virtual TRectype extract_dirtynode(TString &id, TString& status);
    
    int dirty_nodes() { return _status_node_record.items();}
    void set_status_node(const TString &id, const char *status);
    TString* get_status_node(const TString &id) 
      {return (TString*)_status_node_record.objptr(id);}
    TRecord(int filenum);
    virtual ~TRecord();
};

class TRecord_caradd : public TRecord
{
  public:
    TRecord_caradd();
    virtual ~TRecord_caradd() {;}
};

class TRecord_colldich : public TRecord
{
  public:
    TRecord_colldich();
    virtual ~TRecord_colldich() {;}
};

class TAnalisi_bil: public TAlbero_AB
{
    class TArray_fratelli: public TAssoc_array
    {
      public:
        void setkey(const char *tipocod, const char *codvc, TToken_string &key) const;
        bool find1stkey(const char *tipocod, const char *codvc, TToken_string &key);
        void mark_used(const char *key);
        bool used(TObject *o);
    };
    TArray_fratelli _nodifratelli;
    TLocalisamfile *_analisi;
    TLocalisamfile *_voci;
    TAlbero_relvoci *_relaz;
    TAlbero_relana *_ana;
    TAlbero_locale *_inter_tree_relvoci;
    
    TRecord *_record_caradd;
    TRecord *_record_colldich;
    TNumeric_id _last_id_caradd;
    TNumeric_id _last_id_colldich;
    void last_id_caradd();
    void last_id_colldich();
  protected:
    void naviga_relazioni(const TNumeric_id & id_relana,const TNumeric_id & prec,const TNumeric_id & padre );
    TRectype * sincronizza_relana(const TNumeric_id &begin_relana,TNumeric_id &id_relana);
    bool lock_struttura();
    bool unlock_struttura();
    bool lock_tabella();
    bool unlock_tabella();
    virtual int read_body(bool lockstruct);
    virtual int commit_body() const;
    virtual void put_headkey(TRectype &rec) const;
    void prova_inserimento();

  public:
    TNumeric_id new_id_caradd() 
    {
      _last_id_caradd = _last_id_caradd +1;
      return _last_id_caradd;
    }

    TNumeric_id new_id_colldich() 
    {
      _last_id_colldich = _last_id_colldich +1;
      return _last_id_colldich;
    }

    virtual bool remove_node(const TNumeric_id &id);
    virtual bool insert_new_node(TToken_string &codice);
    virtual void modify_node(TToken_string &codice);
    TAnalisi_bil();
    virtual ~TAnalisi_bil() ;
    TAlbero_locale * user_tree_voc()
      {return _inter_tree_relvoci;}
    
    TRecord *user_caradd()
      {return _record_caradd;}
      
    TRecord *user_colldich()
      {return _record_colldich;}

    const TString &type() {return get(ABAN_TIPOAN);}
    void set_type(const char * tipo) {put(ABAN_TIPOAN,tipo);}
    
};
    
class TABsaldo: public TAlbero_AB
{
    TLocalisamfile *_saldi;
    TAlbero_movdett *_mov;
    TLocalisamfile *_movdett;

  protected:
    virtual int read_body(bool lockstruct);
    virtual void put_headkey(TRectype &rec) const;
    void naviga_movdett();
    void prova_inserimento();

  public:
    virtual bool remove_node(const TNumeric_id &id) {return FALSE;} //da fare
    TABsaldo();
    virtual ~ TABsaldo();
};