#ifdef WIN32 //qui verificare
#include <direct.h>
#endif

#include <applicat.h>
#include <archives.h>
#include <mask.h>    
#include <progind.h>
#include <tabutil.h>
#include <utility.h>

#include "ve5100a.h"    

#include "velib.h"

class TDeletedoc_app : public TSkeleton_application
{                                     
  TArchive       _arc;      
  TString        _desc, _last_std;
  TString16      _num;
  int            _anno;
  char           _unit;
  TFilename      _tmp_dir;
  TIsamtempfile  *_tdoc,*_trdoc;
  
protected:

  void backup_delete_doc(int op, int who, bool pack_rows); // Backup e cancellazione dei documenti da eliminare
  void restore_doc();                      // Ripristino documenti da disco
  void create_tmp_files(bool create=TRUE);
  void delete_tmp_files(bool remove=TRUE);
  virtual bool create();
  virtual bool destroy();
  virtual void main_loop();  

static bool state_handler(TMask& m, KEY k);
  
public:

  TDeletedoc_app() {};  
  ~TDeletedoc_app() {};  
};

bool TDeletedoc_app::state_handler(TMask& m, KEY k)
{
  if (k == K_SHIFT + K_F7)
    m.enable(F_STATUS);
  
  return TRUE;
}

void TDeletedoc_app::backup_delete_doc(int op, int who, bool pack_rows)
{
  
  TIsamfile doc(LF_DOC);
  TIsamfile rdoc(LF_RIGHEDOC);
  TIsamfile clifo(LF_CLIFO);
  TIsamfile cfven(LF_CFVEN);
  TIsamfile indsp(LF_INDSP);
  TIsamfile tab(LF_TAB);
  TIsamfile occas(LF_OCCAS);
  TIsamfile movmag(LF_MOVMAG);
  TIsamfile rmovmag(LF_RMOVMAG);
  
  
  doc.open();
  rdoc.open();
  clifo.open();
  cfven.open();
  indsp.open();
  tab.open();
  occas.open();
  movmag.open();
  rmovmag.open();
  
  int err= NOERR;  
//  int err = doc.lock();
  if (err != NOERR) 
  {
    error_box("Il file documenti non puo' essere bloccato in modo esclusivo."
              " Nessun documento cancellato. Errore %d.",err);
    return;
  }

  TDocumento documento;
  if (op & 0x2)
    create_tmp_files();

  TString_array to_zap; // Array contenente le chiavi dei documenti da eliminare
  TString_array to_pack; // Array contenente le chiavi dei documenti da compattare
  TRecnotype total = 0;
  
  doc.zero();                                        
  // Scorre il file dei documenti
  {
    TProgind p(doc.items(), "Ricerca dei documenti ...", TRUE, TRUE);
    for (int scanerr = doc.first(); 
         scanerr == NOERR && !p.iscancelled(); 
         scanerr = doc.next())
    {   
      p.addstatus(1);
      if (_anno != 0 && _anno != doc.get_int(DOC_ANNO))
        continue;
      if (_num.not_empty() && _num != doc.get(DOC_CODNUM))
        continue;
      documento.read(doc.curr());
      
      bool to_delete = FALSE;
      
      if (who & 0x1)
      {
        if (doc.get(DOC_STATO) == _last_std) 
          to_delete = TRUE;
      }
      if (who & 0x2)
      {
        if (doc.get_bool(DOC_DOCEVASO)) 
          to_delete = TRUE;
      }
  
      if (pack_rows && !to_delete && documento.tipo().is_ordine())
      {   
        const int rows = documento.physical_rows();
        for (int x = 1; x <= rows; x++)
        {
          if (documento[x].is_evasa())   
          {
            TToken_string id(30);
            id = doc.get(DOC_PROVV);
            id.add(doc.get(DOC_ANNO));
            id.add(doc.get(DOC_CODNUM));
            id.add(doc.get(DOC_NDOC));
            to_pack.add(id);        
            break;
          }
        }
      }
  
      if (to_delete) // Se TRUE il puo' essere eliminato!
      {              // Memorizza la chiave 1 del documento in un array
        if (op & 0x1)
        {
          TToken_string id(30);
          id = doc.get(DOC_PROVV);
          id.add(doc.get(DOC_ANNO));
          id.add(doc.get(DOC_CODNUM));
          id.add(doc.get(DOC_NDOC));
          to_zap.add(id);
        }
        if (op & 0x2)
        {
          err = _tdoc->write(doc.curr());
          const int rows = documento.physical_rows();
          // Memorizza le righe del documento sui file temporanei
          for (int x = 1; err == NOERR && x <= rows; x++)
            err = _trdoc->write(documento[x]);   
        }
        else
          err = NOERR;
        total++;
      }       
    }  // end of for
    if (p.iscancelled()) 
      total = 0;
  }

  if (total != 0) 
  {
    if (err==NOERR)           
    {
      bool rt = TRUE;
      if (op & 0x2)
      {
        doc.close();   rdoc.close(); clifo.close();
        cfven.close(); tab.close();  occas.close();
        movmag.close(); rmovmag.close();
        const char * dir = &_tmp_dir[1];
        delete_tmp_files(FALSE); //Close tmp files only
        rt = _arc.backup(dir,_unit,_desc, FALSE);// Backup dei documenti da eliminare, prefix unnecessary
        create_tmp_files(FALSE); // Reopen tmp files.
        doc.open(_excllock); rdoc.open(); clifo.open();
        cfven.open(); tab.open(); occas.open();
        movmag.open(); rmovmag.open();
      }
      if (rt & (op & 0x1)) 
      {
        // Effettiva cancellazione dei documenti
        TString caption("Confermare la cancellazione di ");
        caption.add_plural(total, "documento");
        if (yesno_box(caption))
        {                                       
          {
            TProgind pi(total, caption, FALSE, TRUE, 10);
            for (int i = 0; i < to_zap.items(); i++)
            {          
              TToken_string& id = to_zap.row(i);        
              id.restart();
              const char provv = id.get_char();
              const int  anno  = id.get_int();
              const TString16 codnum = id.get();
              const long numdoc = id.get_long();
              documento.read(provv,anno,codnum,numdoc);
              documento.TMultiple_rectype::remove(doc);
              pi.addstatus(1);
            }   
          }
          {
            TProgind pi1(to_pack.items(), "Compattamento documenti", FALSE, TRUE, 10);
            for (int i = 0; i < to_pack.items(); i++)
            {          
              TToken_string& id = to_pack.row(i);        
              id.restart();
              const char provv = id.get_char();
              const int  anno  = id.get_int();
              const TString16 codnum = id.get();
              const long numdoc = id.get_long();
              documento.read(provv,anno,codnum,numdoc);
              const int rows = documento.physical_rows();
              // Memorizza le righe del documento sui file temporanei
              for (int x = rows;  x >= 1; x--)
                if (documento[x].is_evasa())
                  documento.destroy_row(x, TRUE);
              documento.rewrite(doc);
              pi1.addstatus(1);
            }   
          }

        }
      }                                          
    }
    else
      error_box("Errore %d scrivendo sui files temporanei."
                " La cancellazione dei documenti chiusi non verra' effettuata.",err);
  }
  if (op & 0x2)
    delete_tmp_files();    // Physical remove of tmp files
  
}

void TDeletedoc_app::restore_doc()
{
  TIsamfile doc(LF_DOC);
  TLocalisamfile rdoc(LF_RIGHEDOC);

  doc.open();
  int err = doc.lock();
  if (err != NOERR)  
  {
    error_box("Il file documenti non puo' essere bloccato in modo esclusivo."
              " Nessuna documento ripristinato. Errore %d.",err);
    return ;
  }
  const char* dir =& _tmp_dir[1]; // Cut out % sign
  if (_arc.restore(dir,_unit,FALSE, FALSE))
  {
    create_tmp_files(FALSE);  // In realta' ci sono gia'
    const TRecnotype items = _tdoc->items() + _trdoc->items();
    TProgind pi(items, "Ripristino documenti archiviati", FALSE, TRUE, 10);

    for (_tdoc->first();_tdoc->good() && err==NOERR;_tdoc->next())
    {
      if ((err=doc.write(_tdoc->curr())) == _isreinsert)
        err=doc.rewrite(_tdoc->curr());
      pi.addstatus(1);
    }
    if (err != NOERR) 
      error_box("Errore %d ripristinando il file DOCUMENTI.",err);  
    else
    {
      for (_trdoc->first();_trdoc->good() && err==NOERR;_trdoc->next())
      {
        if ((err=rdoc.write(_trdoc->curr())) == _isreinsert)
          err=rdoc.rewrite(_trdoc->curr());
        pi.addstatus(1);
      }
      if (err != NOERR)
        error_box("Errore %d ripristinando il file RIGHE DOCUMENTI.",err);  
    }
    delete_tmp_files();  // Removes tmp files!
  } 
  else
    error_box("Errore nel ripristino dei file da dischetto. Nessuna documento ripristinato.");
  doc.close();
}

void TDeletedoc_app::create_tmp_files(bool create)
{
  TFilename tf(_tmp_dir);
  tf.add("f1");
  _tdoc   = new TIsamtempfile(LF_DOC,tf,create);
  tf.rtrim(1); tf << "2";
  _trdoc   = new TIsamtempfile(LF_RIGHEDOC,tf,create);
}                     

void TDeletedoc_app::delete_tmp_files(bool remove)
{
  if (remove)        // Cosi' posso forzare la cancellazione in chiusura
  {
    _tdoc->set_autodel();
    _trdoc->set_autodel();
  }
  delete _tdoc;
  delete _trdoc;
  _tdoc = NULL;
  _trdoc = NULL;
}

bool TDeletedoc_app::create()
{
  _tmp_dir.temp();
  _tmp_dir = _tmp_dir.path();
  _tmp_dir << "VE";
  if (!_tmp_dir.exist()) 
    make_dir(_tmp_dir);
  _tmp_dir.insert("%");  // Add % sign 
  
  // Guy says: NON ESISTE UNO STATO ELIMINABILE VALIDO PER TUTTI I DOCUMENTI!!!!!!!!!!!!!!!!!!
  // Quanto segue � completamente ERRATO ed impensabile da usare.
  TTable std("%STD");
  std.last(); // Reperisce lo stato eliminabile
  _last_std = std.get("CODTAB");

  return TSkeleton_application::create();
}

bool TDeletedoc_app::destroy()
{                
  _tmp_dir=_tmp_dir.sub(1); // Cut out % sign
  if (_tmp_dir.exist()) 
    xvt_fsys_rmdir(_tmp_dir);
  return TSkeleton_application::destroy();
}

void TDeletedoc_app::main_loop()
{               
  TMask m("ve5100a");
  m.set_handler(state_handler);

  m.set(F_STATUS,_last_std);
  
  while (m.run() != K_QUIT) 
  {                 
    _unit       = m.get(F_UNIT)[0];
    _desc       = m.get(F_DESC);
    const int scelta = m.get_int(F_OPERAZIONE);
    const int cosa = m.get_int(F_DOCUMENTI);
    const bool pack_rows = m.get_bool(F_COMPATTA);
    _anno = m.get_int(F_ANNO);
    _num = m.get(F_CODNUM);
    switch (scelta)
    {
      case 1 : backup_delete_doc(0x1, cosa, pack_rows); break;
      case 2 : backup_delete_doc(0x2, cosa, pack_rows); break;
      case 3 : backup_delete_doc(0x3, cosa, pack_rows); break;
      default: restore_doc(); break;
    }
  }
}


int ve5100(int argc, char* argv[])
{
  TDeletedoc_app a;
  a.run(argc, argv, "Eliminazione documenti");
  return 0;
}