#include <applicat.h>
#include <isam.h>
#include <mask.h>
#include <prefix.h>

#include "cg4.h"
#include "cg4200.h"

#include <pconti.h>

class TCopia_archivi : public TSkeleton_application
{
  TMask* _msk;
  long _default_firm;

protected:
  virtual bool create() ;                         
  virtual bool destroy() ;                        
  virtual void main_loop();
  
public:
  bool copyfile(int logicnum, long from, long to);
  bool check_comfile(int logicnum);
  void clearivd(long to);
  void copyivd(long from, long to);

  TCopia_archivi() : _msk(NULL) {}
};    

bool TCopia_archivi::check_comfile(int logicnum)
{                    
  TDir dir; dir.get(logicnum, _nolock, _comdir);
  const TFilename name = dir.filename();
  if (name.exist()) 
    return TRUE;
  else
    return error_box(FR("Non esiste il file sorgente : archivi comuni - %s"),  dir.filename());
}    

bool TCopia_archivi::copyfile(int logicnum, long from, long to)
{    
  // Controllo che la destinazione non sia un file comune
  set_firm(to);
  TDir dir;
  dir.get(logicnum, _nolock, _nordir, _sysdirop);
  if (dir.is_com())   
  {
    dir.get(logicnum);
    return error_box(FR("Impossibile copiare su un'archivio comune : ditta %ld - archivio %s"), to, dir.filename());
  }

  // Scarico il file sorgente su un file di testo
  if (from > 0) 
    set_firm(from);
  else
    prefix().set("com");
	TFilename t; t.tempdir(); t << "/tr" << logicnum << ".txt";
  if (t.not_empty())  // dummy test to ensure parenthesis
  {
	  TSystemisamfile file(logicnum);
	  if (file.dump(t) != NOERR)
		  return error_box(FR("Impossibile leggere i dati da copiare errore n. %d"), file.status());
  }
	
  // Scarico il file destinazione su un file di testo
  set_firm(to);
  TFilename s; s.tempdir(); s << "/sv" << logicnum << ".txt";

  TSystemisamfile file(logicnum);
  if (file.dump(s) != NOERR)
    return error_box(FR("Impossibile salvare i dati originali errore n. %d"), file.status());
  // Azzero il file destinazione
  file.zap();

  // Carico nel file destinazione il file di testo precedente
  if (file.load(t) != NOERR)
  {
    error_box(FR("Impossibile scrivere i dati errore n. %d. Ripristino dei dati originali."), file.status());
    // Ripristino il backup
    file.zap();
    if (file.load(s))
      error_box(FR("Impossibile ripristinare i dati originali errore n. %d"), file.status());
    return FALSE;
  }
  return TRUE;
}

void TCopia_archivi::clearivd(long to)
{
  TLocalisamfile pcon(LF_PCON);

  for (pcon.first(); pcon.good(); pcon.next())
  {
    pcon.put(PCN_SEZIVD, "0");
    pcon.zero(PCN_LETTIVD);
    pcon.zero(PCN_NUMRIVD);
    pcon.zero(PCN_NUMIVD);
    pcon.put(PCN_SEZIVDOPP, "0");
    pcon.zero(PCN_LETTIVDOPP);
    pcon.zero(PCN_NUMRIVDOPP);
    pcon.zero(PCN_NUMIVDOPP);
    pcon.rewrite();
  }
}

void TCopia_archivi::copyivd(long from, long to)
{
  if (from > 0) set_firm(from);
  else prefix().set("com");
  TLocalisamfile pcon(LF_PCON);
  TAssoc_array riclass;

  for (pcon.first(); pcon.good(); pcon.next())
  {
    TString16 key;
    TToken_string data;
    
    key.format("%03d%03d%06ld", pcon.get_int(PCN_GRUPPO),
               pcon.get_int(PCN_CONTO), pcon.get_long(PCN_SOTTOCONTO));
    data.add(pcon.get(PCN_SEZIVD));
    data.add(pcon.get(PCN_LETTIVD));
    data.add(pcon.get(PCN_NUMRIVD));
    data.add(pcon.get(PCN_NUMIVD));
    data.add(pcon.get(PCN_SEZIVDOPP));
    data.add(pcon.get(PCN_LETTIVDOPP));
    data.add(pcon.get(PCN_NUMRIVDOPP));
    data.add(pcon.get(PCN_NUMIVDOPP));
    riclass.add(key, data);
  }
  set_firm(to);
  for (pcon.first(); pcon.good(); pcon.next())
  {
    TString16 key;
    
    key.format("%03d%03d%06ld", pcon.get_int(PCN_GRUPPO),
               pcon.get_int(PCN_CONTO), pcon.get_long(PCN_SOTTOCONTO));

    TToken_string * data = (TToken_string *) riclass.objptr(key);

    if (data == NULL)
    {
      pcon.put(PCN_SEZIVD, "0");
      pcon.zero(PCN_LETTIVD);
      pcon.zero(PCN_NUMRIVD);
      pcon.zero(PCN_NUMIVD);
      pcon.put(PCN_SEZIVDOPP, "0");
      pcon.zero(PCN_LETTIVDOPP);
      pcon.zero(PCN_NUMRIVDOPP);
      pcon.zero(PCN_NUMIVDOPP);
    }
    else
    {
      pcon.put(PCN_SEZIVD, data->get(0));
      pcon.put(PCN_LETTIVD, data->get());
      pcon.put(PCN_NUMRIVD, data->get());
      pcon.put(PCN_NUMIVD, data->get());
      pcon.put(PCN_SEZIVDOPP, data->get());
      pcon.put(PCN_LETTIVDOPP, data->get());
      pcon.put(PCN_NUMRIVDOPP, data->get());
      pcon.put(PCN_NUMIVDOPP, data->get());
    }
    pcon.rewrite();
  }
}

bool TCopia_archivi::create()
{
  _msk = new TMask("cg4200a") ;
  _default_firm = get_firm();
  return TSkeleton_application::create();
}

bool TCopia_archivi::destroy()
{
  if (_msk != NULL) 
    delete  _msk;
  return TSkeleton_application::destroy();
}

void TCopia_archivi::main_loop()
{
  while (_msk->run() == K_ENTER)
  {
    const long from_firm = _msk->get_long(F_FROMFIRM);
    const long to_firm = _msk->get_long(F_TOFIRM);
    if (from_firm == to_firm)
      error_box(TR("La copia si puo' effettuare solo tra due ditte diverse"));
    else
    {
      const bool copy_pcon = _msk->get_bool(F_PCON);
      const bool copy_causali = _msk->get_bool(F_CAUS);
      const bool copy_clifo = _msk->get_bool(F_CLIFO);
      const bool copy_ivd = _msk->get_bool(F_IVD);
      if (copy_pcon || copy_causali || copy_clifo || copy_ivd) 
      {
        bool ok = TRUE;
        if (copy_pcon) ok = check_comfile(LF_PCON);
        if (ok && copy_causali) ok = check_comfile(LF_CAUSALI) && check_comfile(LF_RCAUSALI);
        if (ok && copy_clifo) ok = check_comfile(LF_CLIFO);
        if (ok && prefix().exist(to_firm))
        {
          set_firm(to_firm);
					{
						TLocalisamfile mov(LF_MOV);
						ok = (mov.eod() == 0);
					}
          
          if (ok || (!copy_pcon && !copy_causali && !copy_clifo)) 
          {
            TString mess;
            mess.format(FR("Attenzione! I seguenti archivi della ditta %ld verranno sovrascritti:\n"), to_firm);          
        
            int count = 0;
            if (copy_pcon)
            {
              mess << TR("piano dei conti");
              count++;
            }
            if (copy_causali)
            {
              if (count > 0) mess << ", "; 
              mess << TR(" causali");
              count++;
            }
            if (copy_clifo)
            {
              if (count > 0) mess << ", "; 
              mess << TR("clienti e fornitori");
              count++;
            }
            if (copy_ivd) 
            {
              if (count > 0) mess << ", "; 
              mess << TR("riclassificazione IV direttiva");
              count++;
            }
            mess << ".\n" ;
            
            TString msg1 = mess; msg1 << TR("Si desidera continuare?"); 
            if (yesno_box(msg1))
            {
              msg1 = mess; msg1 << TR("Si desidera veramente continuare?"); 
              if (yesno_box(msg1))
              {
                if (copy_pcon)
                {
                  if (copyfile(LF_PCON, from_firm, to_firm) && !copy_ivd)
                    clearivd(to_firm);
                }
                if (copy_causali)
                {
                  if (copyfile(LF_CAUSALI, from_firm, to_firm))
                    copyfile(LF_RCAUSALI, from_firm, to_firm);
                }
                if (copy_clifo)
                  copyfile(LF_CLIFO, from_firm, to_firm);
                if (!copy_pcon && copy_ivd)
                  copyivd(from_firm, to_firm);
              }
            }
          }
          else 
            error_box(TR("La copia si puo' effettuare solo se non sono stati registrati movimenti"));
          set_firm(_default_firm);
        }
        else error_box(FR("Gli archivi della ditta %ld non sono stati ancora generati"),to_firm);
        _msk->reset();
      }
    }
  }
}

int cg4200(int argc, char* argv[])
{
  TCopia_archivi a ;
  a.run(argc, argv, TR("Copia archivi"));
  return 0;
}