// ba3500.cpp  - Tabella libro unico

#include <applicat.h>
#include <mask.h>
#include <msksheet.h>
#include <relapp.h>
#include <relation.h>
#include <tabutil.h>
#include <urldefid.h>
#include <config.h>      
#include <utility.h>

#include "ba3500.h"
#include "nditte.h"

#define ALIAS 1         

#define TAB_LBU "%LBU"
#define TAB_INL "%INL"
#define TAB_REG "REG"

class Riga_tabinl : public TToken_string
{
public:
  const TString& operator = (const TString& s) 
  {return TToken_string::operator=(s);}
  Riga_tabinl (long,int,long,long,long,const char*,long,long,const char*,bool,bool);
};

Riga_tabinl::Riga_tabinl(long annorg,int meserg,long pilib,long pflib,long coddta,const char* codrg,long piut,long pfut,const char* codvid,bool stamp_bol,bool pag_ann)
: TToken_string(80)
{
  add((long)annorg);  add((long)meserg);  add((long)pilib);   add((long)pflib);  add((long)coddta); 
  add(codrg);   add((long)piut);    add((long)pfut);    add(codvid); add((char)stamp_bol);
  add((char)pag_ann);
}

class TRighe_tabinl : public TArray
{
public:
  void add_riga(long=0l,int=0,long=0l,long=0l,long=0L,const char*p=NULL,long=0L,long=0L,const char*d=NULL,bool=FALSE,bool=FALSE);
  
  TRighe_tabinl() {}
};

void TRighe_tabinl::add_riga(long annorg,int meserg,long pilib,long pflib,long coddta,const char* codrg,long piut,long pfut,const char* codvid,bool stamp_bol,bool pag_ann)
{
  Riga_tabinl* r=new Riga_tabinl(annorg,meserg,pilib,pflib,coddta,codrg,piut,pfut,codvid,stamp_bol,pag_ann);
  add(r); 
}

class TRighe_gia_presenti : public TBit_array
{
public:
  bool IS_IN (long) const;
  void togli (long);
  TRighe_gia_presenti (long size) : TBit_array(size) {}
};

void TRighe_gia_presenti::togli(long numrig)
{
  reset(numrig);
}

bool TRighe_gia_presenti::IS_IN (long numrig) const
{
  if ((*this)[numrig])
    return TRUE;
  else
    return FALSE;
}

class BA3500_application : public TRelation_application
{
  TRelation       * _rel;
  TMask           * _msk;
  TTable          * _tab_lbu;
  TTable          * _tab_inl;
  TTable          * _tab_reg;
  TLocalisamfile  * _nditte;
  TRighe_gia_presenti *_righe_gia_presenti;
  
  int _mode;              // Modo maschera corrente
  TRighe_tabinl        _righe_tabinl;
  
  int    compila_righe_rcaus (TString&, TString&, TString&, TString&);
  void   read_tabinl(TMask&);
  bool   fill_sheet(TMask&);
  
protected:
  virtual bool user_create();
  virtual bool user_destroy();
  
  virtual TRelation*   get_relation() const { return _rel; }
  virtual TMask*       get_mask(int mode);
  virtual bool         changing_mask(int mode) {return FALSE; }
  virtual bool         remove();
  
  //  void init_mask(TMask&);
  virtual void init_query_mode(TMask&);
  //  virtual void init_modify_mode(TMask&);

  //  virtual void init_insert_mode(TMask&);
  virtual int  rewrite(const TMask& m);
  virtual int  write(const TMask& m);
  virtual int  read(TMask& m);
  int          cancella(long items);

public:
  BA3500_application() {}
};

TMask*  BA3500_application::get_mask(int mode)
{
  return _msk;
}

void BA3500_application::read_tabinl(TMask& m)
{
  long    paginilib,pagfinlib,codditta,paginiut,pagfinut;
  int     mesereg,annoreg;
  TString codvidim,codreg;
  bool    stampa_bol = FALSE;
  bool    pagine_ann = FALSE;
  bool    ok = FALSE;
  //  TTable* tab_inl = (TTable*)_rel->lfile(TAB_INL);
  TTable& tab_inl = (TTable&)_rel->lfile(-ALIAS);
  long    numrig;
  int     anno;
  TString codlib;

  anno   = m.get_int(F_ANNO);
  codlib = m.get(F_CODLIB);

  _rel->update();

  _righe_gia_presenti = new TRighe_gia_presenti(tab_inl.items());
  _righe_gia_presenti->reset();

  // int lognum = name2log(TAB_INL); //trasformo il nome della tab in un logicnum

  ok = _rel->is_first_match(-ALIAS);

  while (ok)
  {
    TRecfield num (tab_inl.curr(),"CODTAB",7,12);
    numrig     = long(num);
    annoreg    = tab_inl.get_int("I0");
    mesereg    = tab_inl.get_int ("I1");
    paginilib  = tab_inl.get_long("I2");
    pagfinlib  = tab_inl.get_long("I3");
    codditta   = tab_inl.get_long("I4");
    codreg     = tab_inl.get("S0");
    paginiut   = tab_inl.get_long("I5");
    pagfinut   = tab_inl.get_long("I6");
    codvidim   = tab_inl.get("S1");
    stampa_bol = tab_inl.get_bool("B0");
    pagine_ann = tab_inl.get_bool("B1");    

    _righe_tabinl.add_riga(annoreg,mesereg,paginilib,pagfinlib,codditta,codreg,paginiut,pagfinut,codvidim,stampa_bol,pagine_ann);
    _righe_gia_presenti->set(numrig);
    ok = _rel->next_match(-ALIAS);
  }
}

bool BA3500_application::fill_sheet(TMask& m)
{
  long items;

  _righe_tabinl.destroy();

  TSheet_field& cs = (TSheet_field&)m.field(F_SHEET_LBU);
  cs.reset();

  for (int j = cs.items(); j < 16 ; j++)
    TToken_string &riga = cs.row(j);

  read_tabinl(m);

  items = _righe_tabinl.items();

  for (int i = 0; i < items; i++)
  {
    TToken_string &riga = cs.row(i);

    riga.cut(0);
    riga = (Riga_tabinl&)_righe_tabinl[i];
  }
  cs.force_update();

  _righe_tabinl.destroy();

  return TRUE;
}

/********
  void BA3500_application::init_insert_mode(TMask& m)
  {

  _righe_tabinl.destroy();

  TSheet_field& cs = (TSheet_field&)m.field(F_SHEET_LBU);
  cs.reset();

  for (int j = 0; j < 16 ; j++)
  TToken_string &riga = cs.row(j);

  cs.force_update();

  }
  **********/

void BA3500_application::init_query_mode(TMask& m)
{
  _righe_tabinl.destroy();

  TSheet_field& cs = (TSheet_field&)m.field(F_SHEET_LBU);
  cs.reset();

  for (int j = cs.items(); j < 16 ; j++)
    TToken_string &riga = cs.row(j);

  cs.force_update();

}


int BA3500_application::rewrite(const TMask& m)
{
  long items;
  //  TTable *tab_inl = (TTable*)_rel->lfile(TAB_INL);
  TTable& tab_inl = (TTable&)_rel->lfile(-ALIAS);

  int anno = m.get_int(F_ANNO);
  TString cod_lib = m.get(F_CODLIB);

  m.autosave(_rel);

  TSheet_field& cs = (TSheet_field&)m.field(F_SHEET_LBU);

  items = cs.items();

  for (int i = 0; i < items; i++)
  {
    TToken_string &riga = cs.row(i);
    TString codtab (format("%4d%-3s%6d",anno,(const char *)cod_lib,i));
    long year  = atol(riga.get(0));
    if (year != 0)
    {
      tab_inl.put ("CODTAB", codtab);
      tab_inl.put ("I0", year);
      tab_inl.put ("I1", riga.get());
      tab_inl.put ("I2", riga.get());
      tab_inl.put ("I3", riga.get());
      tab_inl.put ("I4", riga.get());
      tab_inl.put ("S0", riga.get());
      tab_inl.put ("I5", riga.get());
      tab_inl.put ("I6", riga.get());
      tab_inl.put ("S1", riga.get());
      tab_inl.put ("B0", riga.get());
      tab_inl.put ("B1", riga.get());
      if (_righe_gia_presenti->IS_IN(i))
      {
        tab_inl.rewrite();
        _righe_gia_presenti->togli(i);
      }
      else
        tab_inl.write();
    }
  }
  return _rel->rewrite();
}

int BA3500_application::write(const TMask& m)
{
  long items;
  //  TTable *tab_inl = (TTable*)_rel->lfile(TAB_INL);
  TTable& tab_inl = (TTable&)_rel->lfile(-ALIAS);

  int anno = m.get_int(F_ANNO);
  TString cod_lib = m.get(F_CODLIB);

  m.autosave(_rel);

  TSheet_field& cs = (TSheet_field&)m.field(F_SHEET_LBU);

  items = cs.items();

  tab_inl.zero();

  for (int i = 0; i < items; i++)
  {
    TToken_string &riga = cs.row(i);
    TString codtab (format("%4d%-3s%6d",anno,(const char *)cod_lib,i));
    long year  = atol(riga.get(0));
    if (year != 0)
    {
      tab_inl.put ("CODTAB", codtab);
      tab_inl.put ("I0", year);
      tab_inl.put ("I1", riga.get());
      tab_inl.put ("I2", riga.get());
      tab_inl.put ("I3", riga.get());
      tab_inl.put ("I4", riga.get());
      tab_inl.put ("S0", riga.get());
      tab_inl.put ("I5", riga.get());
      tab_inl.put ("I6", riga.get());
      tab_inl.put ("S1", riga.get());
      tab_inl.put ("B0", riga.get());
      tab_inl.put ("B1", riga.get());    
      tab_inl.write();
    }
  }
  return _rel->write();
}

bool BA3500_application::remove()
{
  TSheet_field& cs = (TSheet_field&)_msk->field(F_SHEET_LBU);

  const bool ok = TRelation_application::remove();

  if (ok)
    cancella(cs.items());
  
  return TRUE;
}

int BA3500_application::cancella(long items)
{
  TTable& tab_inl = (TTable&)_rel->lfile(-ALIAS);
  TRecfield an(tab_inl.curr(),"CODTAB",0,3);
  TRecfield cl(tab_inl.curr(),"CODTAB",4,6);
  long      anno;
  TString   codlib, dep;
  
  anno   = long(an);
  codlib = (const char*)cl; 
  for (long i = 0; i < items; i++)
  {
    tab_inl.zero();
    dep =  format ("%04d", anno);
    dep << format ("%-3s" , (const char*) codlib);
    dep << format ("%6d" , i);
    tab_inl.put("CODTAB", dep);
    if (tab_inl.read(_isequal, _lock) == NOERR)
      tab_inl.remove();
  }
  return tab_inl.status();
}

/*********

  void BA3500_application::init_modify_mode(TMask& m)
  {
  init_mask(m);
  }

  void BA3500_application::init_mask(TMask& m)
  {
  TString tpd(m.get(F_TIPO_DOC));
  TString tpm(m.get(F_TIPO_MOV));

  if (tpd.trim().empty())
  m.set(F_TIPO_MOV_2, tpm);
  else
  m.set(F_TIPO_MOV_1, tpm);
  }
  ***********/  
int BA3500_application::read(TMask& m)
{
  m.autoload(_rel);
  fill_sheet(m);

  return NOERR;
}

bool BA3500_application::user_create()
{
  _rel = new TRelation (TAB_LBU);

  _rel->add(TAB_INL, "CODTAB[1,7]==CODTAB" ,1, 0, ALIAS, TRUE); //-4 = alias, perche' le due tabelle sono entrambe in TABCOM.dta

  _tab_lbu = new TTable (TAB_LBU);
  _tab_inl = new TTable (TAB_INL);
  _tab_reg = new TTable (TAB_REG);
  _nditte  = new TLocalisamfile (LF_NDITTE);

  _msk = new TMask("ba3500a");

  return TRUE;
}

bool BA3500_application::user_destroy()
{
  delete _msk;
  delete _tab_lbu;
  delete _tab_inl;
  delete _tab_reg;
  delete _nditte;
  delete _rel;
  return TRUE;
}

int ba3500(int argc, char* argv[])
{
  BA3500_application a;
  a.run(argc, argv, "Tabella libro unico");
  return 0;
}