#include <mask.h>
#include <printapp.h>
//#include <relation.h>
#include <tabutil.h>
//#include <utility.h>
#include <sort.h>
#include <progind.h>

#include <nditte.h>
#include <anagr.h> 
#include <comuni.h>

#include "ba3.h"
#include "ba3600.h"

#define ALIAS 50

static TString256 tmp;

const int       TABLBU = (int)TTable::name2log("%LBU");

class BA3600_application : public TPrintapp
{
  struct ind_lib
  {
    char   anno[5];
    char   mese[3];
    char   nini_plib[6];
    long   num_riga;
    long   nfin_plib;
    long   codditta;
    char   cod_reg[4];
    long   nini_put;
    long   nfin_put;
    char   cod_vid[4];
    bool   stamp_bol;
    bool   pag_ann;
  };

  TMask*            _msk;
  TTable*           _tab_lbu;
  TTable*           _tab_reg;
  TLocalisamfile*   _indlib;
  TLocalisamfile*   _nditte;
  TLocalisamfile*   _anag;
  TLocalisamfile*   _comuni;
  TSort*            _sort;
  TProgind*         _prog;
  ind_lib*          _lib;
  const char*       _buff;

  TDate   _datastampa;
  int     _tipo_stampa, _meseda, _mesea, _mese, _meseprec;
  long    _anno, _numini_paglib, _numfin_paglib, _numini_pagut, _numfin_pagut;
  long    _codditta, _pag_fin, _num_riga, _nfin_plib_prec,_codana_intesta,_codana_ditta;
  TString _cod_lib, _cod_lib_su, _rag_soc, _cod_reg, _descrizione, _cod_vidimaz;
  TString _cod_lib_stampa, _stamp_bollato_str, _desc_cod_lib,_desc_cod_lib_su;
  char    _tipo_intesta,_tipoa_ditta;
  bool    _stamp_bollato, _pag_ann, _pag_fuori_sequenza,_stampa_intesta,_stampa_ind;
  TString _ind_dta,_civ_dta,_cap_dta,_com_dta,_prov_dta;

public:
  
  bool menu (MENU_TAG m) { return TPrintapp::menu(m) ; }
  virtual bool user_create() ;
  virtual bool user_destroy();
  bool set_print(int);
  
  virtual bool preprocess_page (int,int);
  virtual print_action postprocess_page (int,int);
  
  virtual void preprocess_header();
  virtual void set_page(int,int);

  void        init_sort();
  void        crea_sort();
  bool        preprocess_prova(int);
  bool        preprocess_bollato();
  void        crea_intestazione_prova();
  void        crea_intestazione_bollato();
  const char* ragsoc_ditta(long);
  const char* descrizione_codreg(const TString&);
  void        setta_righe_prova();
  void        setta_righe_bollato();
  void        dati_libro_unico();
  void        intestatario(TString&,TString&,TString&,TString&,TString&,TString&,TString&,TString&);
  void        compatta_ragsoc(TString&);
  void        descrizione();                            
  void        dati_anagrafici_ditta(TString&,TString&,TString&,TString&,TString&);
  
  BA3600_application() {}
};

void BA3600_application::init_sort()
{
  _lib  = new ind_lib;
  _sort = new TSort (sizeof(ind_lib));
  
  _sort -> addsortkey((char*)&(_lib->anno)      - (char*)&(_lib->anno),4);
  _sort -> addsortkey((char*)&(_lib->mese)      - (char*)&(_lib->anno),2);
  _sort -> addsortkey((char*)&(_lib->nini_plib) - (char*)&(_lib->anno),5);
  _sort->init();
}

//Crea sort ordina i record della tabella %INL per mese registrazione, anno
//registrazione e numero iniziale pagine registro libro unico

void BA3600_application::crea_sort()
{
  long    anno,numini_paglib,numfin_paglib,codditta,numini_pagut,numfin_pagut; 
  TString cod_reg,cod_vidimaz,dep,app;
  long    mese, ultimo_mese;
  bool    stamp_bollato = FALSE;
  bool    pagine_ann    = FALSE;
  bool    stampato      = FALSE;
  mese        = 0;
  ultimo_mese = 0;  

  init_sort();
  
  _tab_lbu->zero();
  //  TString dep (format ("%4d%-3s", _anno, (const char*) _cod_lib));
  //  sprintf(__tmp, "%4d", _anno);
  //  strcat (__tmp, _cod_lib);
  dep.format ("%4d%-3s", _anno, (const char*)_cod_lib);
  _tab_lbu->put("CODTAB", (const char*) dep);

  if (_tab_lbu->read(_isequal) == NOERR)
  { 
    _indlib->setkey(1);
    _indlib->zero();
    _indlib->put("ANNO",   _anno);
    _indlib->put("CODLIB", (const char*) _cod_lib);

    TRectype rec (_indlib->curr());

    for (_indlib->read(); !_indlib->eof(); _indlib->next())
    {
      if (_indlib->curr() > rec)  break;
      
      mese = _indlib->get_int("MESEREG");

      if (((_tipo_stampa == 1) && (mese >= _meseda) && (mese <= _mesea)) ||
          ((_tipo_stampa == 2) && (mese <= _mesea)))
      {
        long num_riga = _indlib->get_long("NUMREG");
        anno          = _indlib->get_long("ANNOREG");
        numini_paglib = _indlib->get_long("PAGINI");
        numfin_paglib = _indlib->get_long("PAGFIN");
        codditta      = _indlib->get_long("CODDITTA");
        cod_reg       = _indlib->get("CODREG");
        cod_vidimaz   = _indlib->get("CODVID");
        numini_pagut  = _indlib->get_long("PAGINIUT");
        numfin_pagut  = _indlib->get_long("PAGFINUT");        
        stamp_bollato = _indlib->get_bool("STAMPATO");
        pagine_ann    = _indlib->get_bool("ANNULLATE");
        
        //Se tipo_stampa = 1 (stampa di prova) stampo ugualmente. Se tipo_stampa = 2
        // (stampa su bollato), stampo solamente se il flag di stampa su bollato e'
        // FALSE.
        
        if ((_tipo_stampa == 1) || ((_tipo_stampa == 2) && (!stamp_bollato)))
        {
          ultimo_mese = mese;
          stampato    = TRUE;
          sprintf (_lib->anno,      "%4d", anno);
          sprintf (_lib->mese,      "%2d", mese);
          sprintf (_lib->nini_plib, "%5d", numini_paglib);
          _lib->num_riga  = num_riga;
          _lib->nfin_plib = numfin_paglib;
          _lib->codditta  = codditta;
          sprintf (_lib->cod_reg,   "%3s", (const char*) cod_reg);
          _lib->nini_put  = numini_pagut;
          _lib->nfin_put  = numfin_pagut;
          sprintf (_lib->cod_vid,   "%3s", (const char*) cod_vidimaz);
          _lib->stamp_bol = stamp_bollato;
          _lib->pag_ann   = pagine_ann;
          _sort->sort ((const char*) _lib);

          //Se si tratta di una stampa su bollato e il flag "stampa su bollato" indica
          //che non e' mai stato stampato su bollato (flag = FALSE), allora devo stampare
          //il record della tabella %INL, e contemporaneamente aggiornare il flag, per
          //evitare di ristampare successivamente su bollato

          if (_tipo_stampa == 2)
          {
            _indlib->put("STAMPATO", "X");
            _indlib->rewrite();
          }
        }
      }
    }
    _sort->endsort();
  }

  // Se si tratta di una stampa su libro bollato, aggiorno sulla tabella %LBU    // l' ultimo mese stampato, l' ultima pagina stampata e il flag che indica se
  // quel record e' stato stampato su bollato      
  
  if ((_tipo_stampa == 2) && (stampato)) // stampato e' il flag che mi dice
  {                                      //se almeno un record, nella stampa
    _tab_lbu->put("I0", ultimo_mese);    //su bollato, va in stampa. In caso
    _tab_lbu->put("I1", numfin_paglib);  //contrario non avrebbe senso 
    _tab_lbu->rewrite();                 //aggiornare %LBU. ES:tutti i record
  }                                      //di quel mese sono gia stati stampati
}                                        //su bollato (flag = TRUE).

void BA3600_application::dati_libro_unico()
{
  TTable lbu ("%LBU");
  TString16 dep;
  dep.format("%4d%-3s", _anno, (const char*) _cod_lib);

  lbu.put("CODTAB", (const char*) dep);

  if (lbu.read(_isequal) == NOERR)
  {
    _stampa_intesta = lbu.get_bool("B0");          
    _stampa_ind     = lbu.get_bool("B1");
    _tipo_intesta   = lbu.get_char("S2");
    _codana_intesta = lbu.get_long("I4");
    _desc_cod_lib   = lbu.get     ("S0");
  }
}                                        

void BA3600_application::descrizione()
{
  TTable lbu ("%LBU");
  TString16 dep;
  dep.format ("%4d%-3s", _anno, (const char*) _cod_lib_su);
  lbu.put("CODTAB", (const char*) dep);

  if (lbu.read(_isequal) == NOERR)
    _desc_cod_lib_su = lbu.get     ("S0");
}

void BA3600_application::intestatario(TString& cofi,TString& paiv,TString& ragsoc,TString& ind,
                                      TString& civ,TString& cap,TString& com,TString& prov)
{    
  TString codcom;
  
  _anag->setkey(1);        
  _anag->zero();
  _anag->put(ANA_TIPOA,    _tipo_intesta);
  _anag->put(ANA_CODANAGR, _codana_intesta);

  if (_anag->read(_isequal) == NOERR)
  {   
    cofi   = _anag->get(ANA_COFI);
    paiv   = _anag->get(ANA_PAIV);
    codcom = _anag->get(ANA_COMRF);
    ragsoc = _anag->get(ANA_RAGSOC);
    
    if (codcom != "")
    {
      ind = _anag->get(ANA_INDRF);
      civ = _anag->get(ANA_CIVRF);
      cap = _anag->get(ANA_CAPRF);
    }                             
    else
    {
      codcom = _anag->get(ANA_COMRES);
      ind    = _anag->get(ANA_INDRES);
      civ    = _anag->get(ANA_CIVRES);
      cap    = _anag->get(ANA_CAPRES);
    }                                 
  }
  
  _comuni->setkey(1);
  _comuni->zero();
  _comuni->put(COM_COM,   codcom);
  if (_comuni->read(_isequal) == NOERR)
  {
    com  = _comuni->get(COM_DENCOM);
    prov = _comuni->get(COM_PROVCOM);
  }
}

bool BA3600_application::set_print(int)
{
  KEY tasto;
  
  //  _msk->set_mode(MODE_QUERY);
  tasto = _msk->run();

  if (tasto == K_ENTER) 
  {
    _tipo_stampa = _msk->get_int(F_TIPO_STAMPA);

    if (_tipo_stampa == 1)
    {
      _cod_lib     = _msk->get(F_LIBRO_UNICO1);
      _datastampa  = (_msk->get(F_DATA_STAMPA)); 
      _meseda      = _msk->get_int(F_MESEDA);
      _mesea       = _msk->get_int(F_MESEA);
      _anno        = _msk->get_long(F_ANNO);
    }
    else if (_tipo_stampa == 2)
    {
      _cod_lib        = _msk->get(F_LIBRO_UNICO2);
      _cod_lib_su     = _msk->get(F_CODLIB_STAMPA);
      _mesea          = _msk->get_int(F_STAMPA_MESE);
      _anno           = _msk->get_long(F_STAMPA_ANNO);
      _cod_lib_stampa = _msk->get(F_CODLIB_STAMPA);
      _pag_fin        = _msk->get_long(F_PAGFINALE);
    }        
    
    _meseprec = 0;
    
    _pag_fuori_sequenza = FALSE;
    
    dati_libro_unico();

    crea_sort();
    
    
    //    if (_tipo_stampa == 2)
    //      crea_intestazione_bollato();

    return TRUE;
  }
  return FALSE;
}

/*********
  bool BA3600_application::preprocess_page(int file, int counter)
  {
  if (_tipo_stampa == 1)
  {
  if (preprocess_prova(counter))
  return TRUE;
  else 
  return FALSE;
  }
  else if (_tipo_stampa == 2)
  {
  if (preprocess_bollato())
  return TRUE;
  else 
  return FALSE;
  }

  return TRUE;
  }
  ***********/

bool BA3600_application::preprocess_page(int file, int counter)
{
  struct ind_lib* lib = (struct ind_lib*) _buff;
  long nini_plib;

  reset_print();

  _buff = _sort->retrieve();

  if (_buff != NULL)
  {
    lib = (struct ind_lib*) _buff;
    
    _mese          = atoi(lib->mese);                                              
    _numini_paglib = atoi(lib->nini_plib);   
    _numfin_paglib = lib->nfin_plib;
    _codditta      = lib->codditta;
    _rag_soc       = ragsoc_ditta(_codditta);
    dati_anagrafici_ditta(_ind_dta,_civ_dta,_cap_dta,_com_dta,_prov_dta);
    _cod_reg       = lib->cod_reg;
    _descrizione   = descrizione_codreg(_cod_reg);
    _cod_vidimaz   = lib->cod_vid;
    _numini_pagut  = lib->nini_put;
    _numfin_pagut  = lib->nfin_put;
    _num_riga      = lib->num_riga;
    _stamp_bollato = lib->stamp_bol;
    _pag_ann       = lib->pag_ann;
    if (_stamp_bollato)
      _stamp_bollato_str = "X";
    else
      _stamp_bollato_str = "";

    //Il controllo di pagine fuori sequenza viene sempre effettuato, tranne che per
    //il primo record. (solo per stampa di prova)

    if ( (counter) && (_tipo_stampa == 1) )
    {
      nini_plib = _numini_paglib - 1;
      
      if (_nfin_plib_prec != nini_plib)
        _pag_fuori_sequenza = TRUE;
      else
        _pag_fuori_sequenza = FALSE;
    }
    
    if (counter)
      if (_mese != _meseprec)
        printer().formfeed();  
    
    _meseprec = _mese;
    
    _nfin_plib_prec = _numfin_paglib;
    
    return TRUE;
  }
  else 
    return FALSE;
  
  return TRUE;
}

void BA3600_application::set_page(int file, int counter)
{ 
  if (_tipo_stampa == 1)
    setta_righe_prova();
  else if (_tipo_stampa == 2)
    setta_righe_bollato();
}

void BA3600_application::setta_righe_prova()
{ 
  int i;

  i = 1;

  if (_pag_fuori_sequenza)
    set_row (i++,"@10gPAGINE FUORI SEQUENZA");

  set_row (i,  "@1g#t",     &_cod_lib);
  set_row (i,  "@6g#5d",    &_numini_paglib);
  set_row (i,  "@13g#5d",   &_numfin_paglib);

  if ((_pag_ann) && (_codditta == 0))
    set_row (i,"@27gPAGINE ANNULLATE");
  else
  {
    set_row (i,"@21g#5d",   &_codditta);
    set_row (i,"@27g#.41t", &_rag_soc);
  }
  if ((_pag_ann) && (_codditta != 0) && (_cod_reg == ""))
    set_row (i,"@73gPAGINE ANNULLATE");
  else
  {
    set_row (i,"@69g#t",    &_cod_reg);
    set_row (i,"@73g#.31t", &_descrizione);
  }

  set_row (i,  "@105g#t",   &_cod_vidimaz);
  set_row (i,  "@111g#5d",  &_numini_pagut);
  set_row (i,  "@117g#5d",  &_numfin_pagut);
  set_row (i,  "@124g#5d",  &_num_riga);
  set_row (i++,"@131g#t",   &_stamp_bollato_str);
  if (_stampa_ind)
    set_row (i  ,"@27g#t #t #t #t #t", &_ind_dta, &_civ_dta, &_cap_dta, &_com_dta, &_prov_dta);
}

void BA3600_application::setta_righe_bollato()
{ 
  int i;

  i = 1;

  //  if (_pag_fuori_sequenza)
  //    set_row (i++,"@10gPAGINE FUORI SEQUENZA");

  set_row (i,"@1g#t",     &_cod_lib);
  set_row (i,"@6g#5d",    &_numini_paglib);
  set_row (i,"@13g#5d",   &_numfin_paglib);

  if ((_pag_ann) && (_codditta == 0))
    set_row (i,"@27gPAGINE ANNULLATE");
  else
  {
    set_row (i,"@21g#5d",   &_codditta);
    set_row (i,"@27g#.41t", &_rag_soc);
  }
  if ((_pag_ann) && (_codditta != 0) && (_cod_reg == ""))
    set_row (i,"@73gPAGINE ANNULLATE");
  else
  {
    set_row (i,"@69g#t",    &_cod_reg);
    set_row (i,"@73g#.31t", &_descrizione);
  }

  set_row (i,"@105g#t",   &_cod_vidimaz);
  set_row (i,"@111g#5d",  &_numini_pagut);
  set_row (i,"@117g#5d",  &_numfin_pagut);
  set_row (i++,"@124g#5d",  &_num_riga);
  //  set_row (i++,"@130g#t",   &_stamp_bollato_str);
  if (_stampa_ind)
    set_row (i  ,"@27g#t #t #t #t #t", &_ind_dta, &_civ_dta, &_cap_dta, &_com_dta, &_prov_dta);
}

print_action BA3600_application::postprocess_page(int file, int counter)
{  
  if (_buff == NULL) 
    return NEXT_PAGE;

  return REPEAT_PAGE;
}

const char* BA3600_application::ragsoc_ditta(long codditta)
{
  TLocalisamfile nditte(LF_NDITTE);

  nditte.zero();
  nditte.put(NDT_CODDITTA, codditta);
  nditte.read();
  if (nditte.bad())        
    nditte.zero();
  tmp = nditte.get(NDT_RAGSOC);
  _tipoa_ditta  = nditte.get_char(NDT_TIPOA);
  _codana_ditta = nditte.get_long(NDT_CODANAGR);
  
  return tmp;
}

void BA3600_application::dati_anagrafici_ditta(TString& ind,TString& civ,TString& cap,
                                               TString& com,TString& prov)
{
  TLocalisamfile anag (LF_ANAG);
  TLocalisamfile comuni (LF_COMUNI);
  TString codcom;
  
  anag.setkey(1);
  anag.zero();
  anag.put(ANA_TIPOA,    _tipoa_ditta);
  anag.put(ANA_CODANAGR, _codana_ditta);
  if (anag.read(_isequal) == NOERR)
  { 
    codcom = anag.get(ANA_COMRF);
    
    if (codcom != "")
    {
      ind = anag.get(ANA_INDRF);
      civ = anag.get(ANA_CIVRF);
      cap = anag.get(ANA_CAPRF);
    }                             
    else
    {
      codcom = anag.get(ANA_COMRES);
      ind    = anag.get(ANA_INDRES);
      civ    = anag.get(ANA_CIVRES);
      cap    = anag.get(ANA_CAPRES);
    }                                 
  }
  
  comuni.setkey(1);
  comuni.zero();
  comuni.put(COM_COM,   codcom);
  if (comuni.read(_isequal) == NOERR)
  {
    com  = comuni.get(COM_DENCOM);
    prov = comuni.get(COM_PROVCOM);
  }
}

const char* BA3600_application::descrizione_codreg(const TString& codreg)
{
  TString16 dep;
  dep.format("%4d%-3s", _anno, (const char*)codreg);

  _tab_reg->zero();
  _tab_reg->put("CODTAB", dep);
  _tab_reg->read();

  if (_tab_reg->bad())
    _tab_reg->zero();
  tmp = _tab_reg->get("S0");

  return tmp;
}

void BA3600_application::compatta_ragsoc(TString& ragsoc)
{   
  TString app;
  
  if (_tipo_intesta == 'F')
  {
    app  = ragsoc.mid(29,20);
    app.trim();
    ragsoc = ragsoc.mid(0,30);
    ragsoc.trim();
    ragsoc << ' ' << app; 
  }
}

void BA3600_application::preprocess_header()
{                         
  if (_tipo_stampa ==1)      
    crea_intestazione_prova();
  else
    if (_tipo_stampa == 2)
      crea_intestazione_bollato();
}

void BA3600_application::crea_intestazione_prova()
{
  TString datastampastr;
  TString sep(132);
  TString cofi,paiv,ind,civ,cap,com,prov,ragsoc;
  
  intestatario(cofi,paiv,ragsoc,ind,civ,cap,com,prov);
  compatta_ragsoc(ragsoc);
  
  reset_header();

  set_header (1,"Studio %s %s %s %s %s %s", (const char*) ragsoc,(const char*) ind,(const char*) civ,
              (const char*) cap,(const char*) com,(const char*) prov);
  
  sep << "Pag. @#";
  sep.right_just(132); 
  set_header (2,(const char*) sep);
  
  datastampastr = _datastampa.string();

  set_header (2,"@0gPartita iva %11s", (const char*) paiv);
  set_header (2,"@30gCodice fiscale %16s", (const char*) cofi);
  set_header (2,"@75gLIBRO UNICO DI PROVA");
  set_header (2,"@105gData@110g%s",(const char*) datastampastr);

  set_header (3,"@0gLibro unico : %s %s", (const char*) _cod_lib,(const char*) _desc_cod_lib);
  TString mese = itom(_mese);
  set_header (3,"@75gmese di %s", (const char*) mese);
  set_header (3,"@92g%4d", _anno);

  sep.fill('-');                             //Stampa 132 - (sep(132))       
  set_header (4, (const char *) sep);
  set_header (5,"@0gCod.@6gNumero@13gpagine@21gCodice@69gCod.@104gCodice@111gN.pag.@118gutente@126gNum.@131gS");
  set_header (6,"@0gLibro@8gda@16ga@21gditta@28gDenominazione@69greg.@74gDescrizione@104gvidim.@112gutilizzate@126greg.@131gB");
  set_header (7, (const char *) sep);
}

void BA3600_application::crea_intestazione_bollato()
{
  TString datastampastr;
  TString sep(132);                      
  TString cofi,paiv,ind,civ,cap,com,prov,ragsoc;
  
  descrizione();
  
  reset_header();
  
  sep << "Pag. @#";
  sep.right_just(132); 
  set_header (2,(const char*) sep);
  
  datastampastr = _datastampa.string();
  
  if (_stampa_intesta)
  {                 
    intestatario(cofi,paiv,ragsoc,ind,civ,cap,com,prov);
    compatta_ragsoc(ragsoc);
    
    set_header (1,"Studio %s %s %s %s %s %s", (const char*) ragsoc,(const char*) ind,(const char*) civ,
                (const char*) cap,(const char*) com,(const char*) prov);                 
    set_header (2,"@0gPartita iva %11s", (const char*) paiv);
    set_header (2,"@30gCodice fiscale %16s", (const char*) cofi);
  }

  set_header (3,"@0gLibro unico : %s %s", (const char*) _cod_lib_su,(const char*) _desc_cod_lib_su);
  TString mese = itom(_mese);
  set_header (3,"@75gmese di %s", (const char*) mese);
  set_header (3,"@92g%4d", _anno);

  sep.fill('-');                             //Stampa 132 - (sep(132))       
  set_header (4, (const char *) sep);
  set_header (5,"@0gCod.@6gNumero@13gpagine@21gCodice@69gCod.@104gCodice@111gN.pag.@118gutente@126gNum.");
  set_header (6,"@0gLibro@8gda@16ga@21gditta@28gDenominazione@69greg.@74gDescrizione@104gvidim.@112gutilizzate@126greg.");
  set_header (7, (const char *) sep);
}

bool BA3600_application::user_create()
{
  _nditte = new TLocalisamfile (LF_NDITTE);
  _anag   = new TLocalisamfile (LF_ANAG);
  _comuni = new TLocalisamfile (LF_COMUNI);
  _indlib = new TLocalisamfile (LF_INDLIB);
  
  _tab_lbu = new TTable (TAB_LBU);
  _tab_reg = new TTable (TAB_REG);

  _msk = new TMask("ba3600a");
  return TRUE;
}

bool BA3600_application::user_destroy()
{
  delete  _msk;

  delete _tab_lbu;
  delete _tab_reg;
  delete _indlib;
  delete _nditte;
  delete _anag;
  delete _comuni;
  
  return TRUE;
}

int ba3600 (int argc, char* argv[])
{

  BA3600_application a;

  a.run(argc, argv, "Stampa indici registro libro unico");

  return 0;
}



