// Ricezione dati da sistema
#define STRICT
#include <windows.h>
#include <direct.h>

#include <colors.h>
#include <isam.h>
#include <archives.h>
#include <config.h>
#include <mask.h>
#include <prefix.h>
#include <printapp.h>
#include <tabutil.h>
#include <urldefid.h>
#include <utility.h>   
#include <progind.h>

#include <nditte.h>

#include "cglib04.h"

#include "cg6400.h"

class TRic_archivi : public TApplication
{
  TTable*           _tab_tra;                    
  TTransfer_file*   _tras_file;  
  TLocalisamfile*   _caus;
  TLocalisamfile*   _rcaus;  
  TLocalisamfile*   _clifo;
  TLocalisamfile*   _pcon;      
  TLocalisamfile*   _mov;
  TLocalisamfile*   _rmov;
  TLocalisamfile*   _rmoviva;  
  TLocalisamfile*   _occas;     
  TLocalisamfile*   _tab;
  TArchive          _arc;
  
  TString80 TEMP;                
  
  char    _scelta;     
  
  int     _numtotdisk,_progdisk,_numdisk,_numinv,_numinvp,_nultras;
  int     _stato_ripartenza,_nultras_tab;
  bool    _sequenza,_disketto;
  bool    _prima_volta,_baipassa;
  TString _nomeid,_nomeidp,_marker,_trasf,_trasfer,_pathname,_ragsoc_dittar;
  long    _dittainv,_dittainvp,_dittaric,_totrectras,_totrectrasp;      
  TDate   _datatras,_datatrasp,_dataultras_tab,_dataultras;
  TString _sigle_file,_nrec_file,_trasfhard;
  char    _agg_cau,_agg_pcon,_agg_cls,_agg_clifo,_agg_fatatt,_agg_fatpas;
  
public: 
  TString _titolo;
  
  virtual bool create();
  virtual bool destroy();
  virtual bool menu(MENU_TAG m);         
  bool    main_loop();
  bool    leggi_marker();                 
  bool    leggi_marker_rep();
  void    leggi_trasfer(const char* nome);
  void    ripristina_trasfer();
  void    trasfer2tempfile();
  long    leggi_tabella_tras();
  void    componi_path(TMask&);
  bool    video_ripartenza();
  void    ditta_ricevente();
  bool    ripartenza();
  bool    set_flag();
  void    aggiorna_tabella();                               
  int     controllo_ripartenza();
  
  static bool baipassa(TMask& m,KEY k);             
  
  TRic_archivi(char ric_trasfer);
};

HIDDEN TRic_archivi& app() { return (TRic_archivi &) main_app(); }

TRic_archivi::TRic_archivi(char ric_trasfer) : _scelta(toupper(ric_trasfer))
{
  if (_scelta == 'S')
    _titolo = "Ricezione archivi da sistema";

  if (_scelta == 'P')      
    _titolo = "Ricezione archivi da PC";
}

bool TRic_archivi::create()
{
  TApplication::create();
  
  _tab_tra    = new TTable ("%TRA");
  _tras_file  = new TTransfer_file();

  _caus    = new TLocalisamfile (LF_CAUSALI);
  _rcaus   = new TLocalisamfile (LF_RCAUSALI);
  _clifo   = new TLocalisamfile (LF_CLIFO);
  _pcon    = new TLocalisamfile (LF_PCON);
  _mov     = new TLocalisamfile (LF_MOV);
  _rmov    = new TLocalisamfile (LF_RMOV);
  _rmoviva = new TLocalisamfile (LF_RMOVIVA);
  _occas   = new TLocalisamfile (LF_OCCAS);
  _tab     = new TLocalisamfile (LF_TAB);  
  
  _numdisk     = 1;       
  _prima_volta = TRUE;
  _nultras     = 0;
  _nultras_tab = 0;     
  _baipassa    = FALSE;
  
  dispatch_e_menu (BAR_ITEM(1));

  return TRUE;
}

bool TRic_archivi::destroy()
{
  delete _tab_tra; 
  delete _tras_file;                         

  delete _caus;
  delete _rcaus;
  delete _clifo;
  delete _pcon;
  delete _mov;
  delete _rmov;
  delete _rmoviva;
  delete _occas;
  delete _tab;
  
  return TApplication::destroy();
}                                

void TRic_archivi::componi_path(TMask& msk)
{
  if (_scelta == 'S')
  { 
    TString path,drive;
    int     pos;

    path  = msk.get(F_PATHNAME);
    drive = msk.get(F_DRIVE);
    pos   = path.find(':');
  
    if (drive == "A:" || drive == "B:" || drive == "D:" || drive == "E:")
      _disketto = TRUE;         
    else
      _disketto = FALSE;
  
    if (pos)
      path = path.mid(pos+1);
  
    if (path != "")
    {  
      _marker << drive << "\\" << path << "\\marker";
      _trasfer << drive << "\\" << path << "\\trasfer";
      if (!_disketto)
        _pathname << drive << "\\" << path;
    }
    else
    {
      _marker << drive << "\\marker";
      _trasfer << drive << "\\trasfer";
      if (!_disketto)
        _pathname << drive << "\\";
    }
  }
  else
    if (_scelta == 'P')
    { 
      char drive;
      
      drive = msk.get(F_DRIVE)[0];
  
      _marker << drive << ":\\marker";
    }
}

bool TRic_archivi::leggi_marker()
{ 
  TString16     tmp;
  
  if (!fexist(_marker))
  {
    if (_disketto)
      return error_box("File marker non presente sul dischetto %d: impossibile proseguire", _numdisk);
    else
      return error_box("File marker non presente in %s: impossibile proseguire", (const char*)_pathname);  
  }
  
  FILE* i;

  const word size = 64;
  TString buffer(size);
  
  if ( (i = fopen(_marker,"r+t")) != NULL)
  {  
    const word letti = fread((char*)(const char*)buffer,sizeof(char),size,i);
    
    _progdisk   = atoi(buffer.sub(31,33));
    _numtotdisk = atoi(buffer.sub(29,31));
    
    if (_progdisk != _numdisk)
    {
      message_box("Il dischetto inserito non rispecchia la giusta sequenza");
      _sequenza = FALSE;
      fclose(i);
      return TRUE;
    }                   
    else
      _sequenza = TRUE;
    
    if (letti == 0)
      return error_box("Rilevati ERRORI nel file MARKER: impossibile proseguire");
    
    _nomeid     = buffer.sub(0,10);
    _dittainv   = atol(buffer.sub(10,14));
    _totrectras = atol(buffer.sub(23,29));
    _numinv     = atoi(buffer.sub(14,17));
    tmp         = buffer.sub(17,23);
    _datatras   = converti(tmp,FALSE);
    
    if (_numdisk > 1)  //Va fatto solo dal disco 2 in poi
      if (_nomeid != _nomeidp || _dittainv != _dittainvp || _totrectras != _totrectrasp
          || _numinv != _numinvp || _datatras != _datatrasp)
        return error_box("I dati del marker del disco %d, non corrispondono ai dati del marker del disco 1", _numdisk);           
    
    _nomeidp      = _nomeid;
    _dittainvp    = _dittainv;
    _totrectrasp  = _totrectras;
    _numinvp      = _numinv;
    _datatrasp    = _datatras;
    
    fclose(i);
    
    if (_numdisk == 1) // Va fatto solo per il primo disco
    {
      _dittaric   = leggi_tabella_tras();
      
      if (_dittaric != 0)
      {
        if (!prefix().exist(_dittaric))
          return error_box("Libreria archivi ditta non presente su disco");
      }   
      else
        return error_box("Codici NON PRESENTI in tabella ricezione: caricarli e riprovare");
    }
    
    return TRUE;
  }    
  
  return FALSE;
}

bool TRic_archivi::leggi_marker_rep()
{ 
  TString16     tmp;
  
  if (!fexist(_marker))
      return error_box("File marker non presente sul dischetto %d: impossibile proseguire", _numdisk);
  
  FILE* i;

  const word size = 64;
  TString buffer(size);
  
  if ( (i = fopen(_marker,"r+t")) != NULL)
  {  
    const word letti = fread((char*)(const char*)buffer,sizeof(char),size,i);
    
    if (letti == 0)
      return error_box("Rilevati ERRORI nel file MARKER: impossibile proseguire");
    
    _nomeid     = buffer.sub(0,10);
    _dittainv   = atol(buffer.sub(10,15));
    _totrectras = atol(buffer.sub(24,30));
    _numinv     = atoi(buffer.sub(15,18));
    tmp         = buffer.sub(18,24);
    _datatras   = converti(tmp,TRUE);
    
    fclose(i);
    
    if (_numdisk == 1) // Va fatto solo per il primo disco
    {
      _dittaric   = leggi_tabella_tras();
      
      if (_dittaric != 0)
      {
        if (!prefix().exist(_dittaric))
          return error_box("Libreria archivi ditta non presente su disco");
      }   
      else
        return error_box("Codici NON PRESENTI in tabella ricezione: caricarli e riprovare");
    }
    
    return TRUE;
  }    
  
  return FALSE;
}

bool TRic_archivi::main_loop()
{ 
  if (_scelta == 'S')
  {
    TMask msk ("cg6400b");
    KEY     tasto;
  
    tasto = msk.run();            
  
    if (tasto == K_ENTER)
    { 
      componi_path(msk);  

      do
      {  
        if (_disketto)
        { 
          char drive = msk.get(F_DRIVE)[0];
          if (yesno_box("Inserire il dischetto %d nell' unita' %c", _numdisk,drive))
          {      
            if (!leggi_marker())
              return FALSE;
          
            if (_sequenza)
            {  
              if (video_ripartenza())
                ripristina_trasfer();
              else
                return FALSE;
            
              _numdisk++;  
            }
          }
          else
            return FALSE;
        }
        else
        {
          if (!leggi_marker())
            return FALSE;
        
          if (_sequenza)
          {  
            if (video_ripartenza())
              ripristina_trasfer();
            else
              return FALSE;
          
            _numdisk++;  
          }
          else
            return FALSE;
        }
      }
      while (_numdisk <= _numtotdisk);  

      trasfer2tempfile();
      set_flag();
      aggiorna_tabella();
      _tras_file->close(); // Chiude il trasfer letto dalla directory della ditta
      fremove(_trasf);
      TString80 tab = _tras_file->path(_dittaric);
      TString tabcdx = tab; 
      TString tabdbf = tab; 
      tabcdx << "\\ttab.cdx";
      tabdbf << "\\ttab.dbf";
      fremove(tabcdx);
      fremove(tabdbf);
    }                                
  }  
  else
    if (_scelta == 'P')
    {
      TMask msk ("cg6400c");
      KEY     tasto;
  
      tasto = msk.run();            
  
      if (tasto == K_ENTER)
      { 
        componi_path(msk);  

        if (!leggi_marker_rep())
          return FALSE;
          
        if (video_ripartenza())
        { 
          char floppy = msk.get(F_DRIVE)[0];
          bool temp = FALSE;
          
          TFilename firm;
          firm.tempdir();
          firm << "\\ftemp";

          set_firm(_dittaric);
          TString dir = _tras_file->path(_dittaric);

          _arc.restore(firm, floppy, temp);  
          
          TString head = firm;
          head << "\\header";
          _tras_file->open(head);
          _tras_file->read_control_rec();
          TString sigle = _tras_file->sigle_file();
          sigle.trim();
          _tras_file->close();
          
          _tras_file->temp_dir(firm,dir,sigle); //Copio i file dalla directory temporanea ftemp alla directory della ditta
          _tras_file->canc_file_dir_temp(firm); //Cancello i file nella directory temporanea ftemp
        }
        else
          return FALSE;
      }
                   
      _trasfhard = _tras_file->path(_dittaric);
      _trasfhard << HEADER;
 
      set_flag();
      aggiorna_tabella();
    }
    
  return FALSE;
}

void TRic_archivi::leggi_trasfer(const char* nome)
{ 
  _nultras = 0;
  
  _trasf = _tras_file->path(_dittaric);
  _trasf << nome;
  
  _tras_file->open(_trasf);
  
  if (_tras_file->exist())
  {  
    if (_tras_file->read_control_rec_t())
    {
      _nultras    = _tras_file->nultras();
      _dataultras = _tras_file->dataultras();
    }
  }  
}

// Questa funzione ritorna:
// - 0 se non vengono rilevate condizioni di ripartenza o di trasferimento
//   non completato.                                                      
// - 1 se viene rilevato uno stato di RIPARTENZA CON DATI CONTRADDITORI
// - 2 se viene rilevato un trasferimento precedente NON COMPLETATO

int TRic_archivi::controllo_ripartenza()
{
  TString std;             
  bool    flag = FALSE;              
  int     var = 0;
  
  TString trasfer;       
  trasfer = _tras_file->path(_dittaric);
  trasfer << HEADER;
  
  _tras_file->open(trasfer);
         
  TConfig conf(CONFIG_DITTA);           
  
  std = conf.get("FlStTra");
  
  if (_tras_file->read_control_rec())
    flag = TRUE;
  
  if (std == "" && flag)
    var = 1;
  
  if (std == "*" && flag)   
  {
    TString ult_file = _tras_file->ult_file();
    TString key      = _tras_file->key();
    if (ult_file != "" || key != "")
      var = 1;
  }
  
  if (std != "" && std != "*")
    var = 2;
  
  _tras_file->close();
  
  return var;
}

bool TRic_archivi::ripartenza()
{  
  if (_stato_ripartenza == 1)
    return error_box("Rilevato stato di RIPARTENZA CON DATI CONTRADDITORI: procedura interrotta");

  if (_stato_ripartenza == 2)
    return error_box("Trasferimento precedente NON COMPLETATO: completarlo prima di questo");    

  return TRUE;
}

bool TRic_archivi::video_ripartenza()
{                    
  TDate dataultras;
  
  if (_prima_volta)
  {      
    leggi_trasfer("\\trasfer");
    
    _prima_volta = FALSE;
    TMask msk ("cg6400a");
    KEY  tasto;
    
    ditta_ricevente();       
    _stato_ripartenza = controllo_ripartenza();
    
    msk.set(F_NOMEID,        _nomeid);
    msk.set(F_CODDITTAINV,   _dittainv);
    msk.set(F_CODDITTARIC,   _dittaric);
    msk.set(F_RAGSOC,        _ragsoc_dittar);
    msk.set(F_NULTRASDSK,    _numinv);
    TString data1 = _datatras.string();
    msk.set(F_DATAULTRASDSK, data1);         

    if (_nultras != 0)
    {
      msk.set(F_NULTRASTAB,    _nultras);    
      TString data2 = _dataultras.string();
      msk.set(F_DATAULTRASTAB, data2);            
    }
    else    
    {
      msk.set(F_NULTRASTAB,    _nultras_tab);
      TString data2 = _dataultras_tab.string();
      msk.set(F_DATAULTRASTAB, data2);      
    }
    
    if (_stato_ripartenza == 1 || _stato_ripartenza == 2 )
      msk.set(F_STATO, "NON COMPLETO");
    else 
      if (_stato_ripartenza == 0)
        msk.set(F_STATO, "COMPLETO");
    
    if (_numdisk == 1)  // Va fatto solo per il primo disco
    {
      do
      { 
        msk.set_handler(baipassa);
        
        tasto = msk.run();
        
        if (tasto != K_ENTER)
          return FALSE;
        
        if (_baipassa)
          return TRUE;
        
        if (!ripartenza())
          return FALSE;     
        
        if (_numinv > (_nultras_tab + 1))
          warning_box("Trasferimento FUORI SEQUENZA: manca un trasferimento intermedio");
        else
          if (_numinv < (_nultras_tab +1))
            warning_box("I dischetti risultano GIA' TRASFERITI");  
          else
            return TRUE;
      }
      while (tasto == K_ENTER);
    }
  }
  
  return TRUE;
}

bool TRic_archivi::baipassa(TMask& m,KEY k)
{
  if ( (k == K_SHIFT+K_F7) && (app()._stato_ripartenza == 0)  )
    app()._baipassa = TRUE;
  else
    app()._baipassa = FALSE;
  
  return FALSE;
}

void TRic_archivi::ripristina_trasfer()                       
{ 
  TProgind prg (1,"Trasferimento archivi in corso\nPrego attendere",FALSE, FALSE);
  
  if (_numdisk == 1)           
  {
    set_firm(_dittaric);
    fcopy(_trasfer,_trasf,FALSE);
  }
  else
    fcopy(_trasfer,_trasf,TRUE);
}

void TRic_archivi::trasfer2tempfile()                       
{ 
  _trasfhard = _tras_file->path(_dittaric);
  _trasfhard << HEADER;

  _tras_file->fcopytemp(_trasf,_trasfhard);
}

void TRic_archivi::ditta_ricevente()
{
  TLocalisamfile nditte (LF_NDITTE);
  
  nditte.setkey(1);
  nditte.zero();
  nditte.put(NDT_CODDITTA, _dittaric);
  if (nditte.read() == NOERR)
    _ragsoc_dittar = nditte.get(NDT_RAGSOC);
}

long TRic_archivi::leggi_tabella_tras()
{               
  TString dep;                               
  long    ditta = 0;                    
  bool    agg_fatatt,agg_fatpas;
  
  _tab_tra->zero();
  dep = format("%10s%05d", (const char*) _nomeid, _dittainv);
  _tab_tra->put("CODTAB", (const char*) dep);
  if (_tab_tra->read() == NOERR)    
  {
    ditta           = _tab_tra->get_long("I0");
    _nultras_tab    = _tab_tra->get_int ("I1");
    _dataultras_tab = _tab_tra->get_date("D0");
    _agg_cau        = _tab_tra->get_char("S0");
    _agg_clifo      = _tab_tra->get_char("S1");
    _agg_pcon       = _tab_tra->get_char("S2");
    _agg_cls        = _tab_tra->get_char("S3");
    agg_fatatt      = _tab_tra->get_bool("B0");
    if (agg_fatatt)
      _agg_fatatt = 'X';
    else
      _agg_fatatt = ' ';
    
    agg_fatpas      = _tab_tra->get_bool("B1");
    if (agg_fatpas)
      _agg_fatpas = 'X';
    else
      _agg_fatpas = ' ';
  }
  
  return ditta;
}

bool TRic_archivi::set_flag()
{
  TString    sigla;
  long       nrec;       
  int        j;                    
  int        k = 0;
  TString    flag;
  TString    record;
  TString    ana_com,pcon_cau;
  TString    uselab;  
  bool       fatto = TRUE;
  
  TConfig conf(CONFIG_DITTA);           
  
  ana_com  = conf.get("AnCfCm","cg");
  pcon_cau = conf.get("PcTcCm","cg");
  
  _tras_file->open(_trasfhard);
  
  if (_tras_file->exist())
  {  
    if (_tras_file->read_control_rec())
    {                                       
      _nultras    = _tras_file->nultras();
      _dataultras = _tras_file->dataultras();
      _sigle_file = _tras_file->sigle_file();
      _nrec_file  = _tras_file->nrec_file();
      record      = _tras_file->record();   
    }
    
    for (j = 0; j < _sigle_file.len(); j++)
    {                      
      sigla  = _sigle_file.mid(j,1);     
      nrec   = atol(_nrec_file.mid(k,6));
      
      if (fatto)
      {
        if (sigla == "W" || sigla == "P")
        {
          if (nrec > 0 && pcon_cau == "")    
          {
            flag  = "T";
            fatto = FALSE;
          }
        }
        else
          if (sigla == "A")
          {
            if (nrec > 0 && ana_com == "")
            {
              flag  = "T";
              fatto = FALSE;
            }
          }              
          else
            if (sigla == "Z" || sigla == "U" || sigla == "B")
            {
              if (nrec > 0)
              {
                flag  = "C";
                fatto = FALSE;
              }
            }
            else 
            {
              flag = "*";  
              fatto = FALSE;
            }
        
        if (flag == "T")
          uselab = sigla; 
        else 
          uselab = "";                               
      }
      
      if (sigla == "W" || sigla == "P")
      {  
        if (pcon_cau == "X")
        {
          _sigle_file.overwrite(" ",j);   
          _nrec_file.overwrite("000000",k);
        }  
      }
      
      if (sigla == "A")
      {
        if (ana_com == "X")
        {
          _sigle_file.overwrite(" ",j);   
          _nrec_file.overwrite("000000",k);
        }
      }            
      k += 6;
    } 
    
    record.overwrite(_sigle_file,41);
    record.overwrite(_nrec_file,50);
    
    TString agg(7);
    
    agg[0] = _agg_cls;
    agg[1] = _agg_cau;
    agg[2] = _agg_clifo;
    agg[3] = _agg_pcon;
    agg[4] = _agg_fatatt;
    agg[5] = _agg_fatpas;    
    agg[6] = '\0';
    
    record.overwrite(agg,234);
    record.overwrite(uselab,240);
    record.overwrite("               ",241);
    
    const int size = 256;
    
    if (!_tras_file->write_control_rec(record, size)) 
      return FALSE;
  }  
  
  conf.set("FlStTra", flag);
  
  return TRUE;
}

void TRic_archivi::aggiorna_tabella()
{
  TString dep;                               
  
  _tab_tra->zero();
  dep = format("%10s%05d", (const char*) _nomeid, _dittainv);
  _tab_tra->put("CODTAB", (const char*) dep);
  if (_tab_tra->read() == NOERR)    
  {
    _tab_tra->put("I1", (long)_nultras);
    _tab_tra->put("D0", _dataultras);
    _tab_tra->rewrite();
  }
}

bool TRic_archivi::menu(MENU_TAG m)
{
  if (m == BAR_ITEM(1))
    return main_loop(); 
  return FALSE;
}

int cg6400 (int argc, char* argv[])
{                                
  TRic_archivi main_app(*argv[2]);
  main_app.run(argc, argv,main_app._titolo);

  return TRUE;
}
