#include <applicat.h>
#include <date.h>
#include <isam.h>
#include <relation.h>
#include <tabutil.h>
#include <mask.h>
#include <prefix.h>
#include <progind.h>
#include <utility.h>

#include <mov.h>
#include <urldefid.h>

#include "cg5.h"
#include "cg5400.h"

class TRipristina_stampa : public TApplication
{
  TMask* _msk;
  long _default_firm;

  virtual bool create() ;                         
  virtual bool destroy() ;                        
  bool menu(MENU_TAG);
  bool do_restore(long firm, const char * reg, const char * year, int month,
		  bool giornale);
  static bool firm_handler(TMask_field& f, KEY key);

public:
  TRipristina_stampa() : _msk(NULL) {}
};

bool TRipristina_stampa::firm_handler(TMask_field& f, KEY key)
{
  if (f.to_check(key))
  {
    const long firm = atol(f.get());

    if (firm < 0)
      return f.error_box("Codice ditta impossibile");
    else
      if (firm == 0)
	return f.error_box("La ditta e' obbligatoria");
      else
	if (!prefhndl->exist(firm))
	  return f.error_box("Gli archivi della ditta %d non sono stati ancora generati",firm);
	else
	  main_app().set_firm(firm);
  }
  return TRUE;
}

bool TRipristina_stampa::do_restore(long firm, const char * regist, 
				    const char * year, int month,
				    bool giornale)
{
  bool ok = TRUE;
  CHECK(firm > 0, "Non posso ripristinare sui dati comuni");
  CHECK(regist != NULL && strlen(regist) < 4, "Registro impossibile");
  CHECK(month > 0 && month < 13, "Mese impossibile");
  set_firm(firm);

  const char * const fieldname = giornale ? MOV_STAMPATO : MOV_REGST;
  TRelation rel(LF_MOV);
  TLocalisamfile & mov = rel.lfile();
  TTable reg("REG");
  TString16 s;

  s.format("%-4s%s", year, regist);
  
  reg.zero();
  reg.put("CODTAB", s);
  if (reg.read(_isequal, _lock) == NOERR)
  {
    TDate dlast(reg.get_date("D3"));
    int wyear = atoi(year);

    if (giornale)
    {
      TTable esc("ESC");
      esc.zero();
      esc.put("CODTAB", year);
      if (esc.read() != NOERR)
      {
	set_firm(_default_firm);
	return error_box("Esercizio %s assente", year);
      }
      
      TDate wd(esc.get_date("D0"));
      
      wyear = wd.year();
      if (wd.month() > month)
	wyear++;
    }
    TDate d(1, month, wyear);
    
    TRectype from(mov.curr()); from.zero();
    TRectype to(from);
    TString16 filter;
    
    from.put(MOV_DATAREG, d);
    to.put(MOV_DATAREG, dlast);
    if (!giornale)
       filter.format("%s==\"%s\"", MOV_REG, regist);
     
    TCursor cursor(&rel, filter, 2, &from, &to);
    long last_num = 0L;
    
    cursor = 0L;
    const long nitems = cursor.items();
    
    TProgind p(nitems ? nitems : 1, format("Ripristino stampa del registro %s", (const char *) regist) , TRUE, TRUE, 70);
        
    if (giornale)
    {
      last_num = mov.get_long(MOV_NUMGIO);
      if (last_num > 0) last_num--;
      CHECK(last_num >= 0, "Ultimo numero stampato impossibile"); 
    }
    for (; ok && cursor.pos() < cursor.items(); ++cursor)
    {
      p.addstatus(1);
      mov.read(_isequal, _lock);
      mov.zero(fieldname);
      ok = (mov.rewrite() == NOERR);
      if (!ok)
	error_box("Errore nell' aggiornamento del movimento %ld.\n Errore n. %d",
		  mov.get_long(MOV_NUMREG), mov.status());
    }
    --d;
    reg.put("D3", d);
    if (giornale)
      reg.put("I6", last_num);
    ok = (reg.rewrite() == NOERR);
    if (!ok)
      error_box("Errore nell' aggiornamento del registro %s.\n Errore n. %d",
		(const char * ) regist, mov.status());
  
  }
  else
    ok = error_box("Non riesco a leggere il registro %s anno %s", (const char *) regist, (const char *) year);

  set_firm(_default_firm);
  return ok;
}

bool TRipristina_stampa::create()
{
  _msk = new TMask("cg5400a") ;
  _msk->set_handler(F_FIRM, firm_handler);
  _default_firm = get_firm();
  dispatch_e_menu(BAR_ITEM(1));
  return TRUE;
}

bool TRipristina_stampa::destroy()
{
  if (_msk != NULL) delete  _msk;
  return TRUE;
}

bool TRipristina_stampa::menu(MENU_TAG)
{
  while (_msk->run() == K_ENTER)
  {
    const long firm = _msk->get_long(F_FIRM);
    const TString16  reg  = _msk->get(F_REG);
    const bool giornale = _msk->get_int(F_TIPO) == 5;
    const TString16 year = _msk->get(giornale ? F_ESER : F_YEAR);
    int month = _msk->get_int(F_MESE);
    
    if (prefhndl->exist(firm))
    {
      TString mess;
      
      mess.format("Attenzione sara' ripristinata la stampa\n del registro %s %s %s della ditta %ld dal mese di %s. Devo continuare",
		  (const char *) reg, giornale ? "esercizio" : "anno",
		  (const char *) year, (const char *) firm, itom(month));
      if (yesno_box((const char *) mess))
      {
	mess.rtrim(16); mess << " Devo veramente continuare";
	if (yesno_box((const char *) mess))
	  do_restore(firm, reg, year, month, giornale);
      }
    }
    else error_box("Gli archivi della ditta %d non sono stati ancora generati",firm);
    _msk->reset();
  }
  return FALSE;
}

int cg5400(int argc, char* argv[])
{
  TRipristina_stampa a ;
  a.run(argc, argv, "Ripristino stampa registri");
  return 0;
}
