#include <stdlib.h>
#include <tabutil.h>
#include "770101.h"    
#include "perc.h"
#include "scperc.h"
#include "rver.h"
#include "rpag.h"

// Calcola l'anno di esercizio di una data                                
// Certified 99%
int date2esc(const TDate& d, int* prevesc)
{                   
  if (prevesc) *prevesc = 0;
  TTable esc("ESC");
  for (int err = esc.first(); err == NOERR; err = esc.next())
  {
    const TDate ia(esc.get("D0"));   // Data inizio esercizio
    const TDate fa(esc.get("D1"));   // Data fine esercizio
    TString16 sanno(esc.get("CODTAB")); sanno.cut(4);
    const int anno = atoi(sanno);
    if (d >= ia && d <= fa)
      return anno;
    if (prevesc) *prevesc = anno; 
  } 
  return 0;
}

///////////////////////////////////////////////////////////
// Scheda Percipiente
///////////////////////////////////////////////////////////

TSchedaPE::TSchedaPE()
: TRelation(LF_SCPERC), _old_ver(0), _old_pag(0)
{
  add(LF_RVER, "CODDITTA==CODDITTA|TIPOA==TIPOA|CODANAGR==CODANAGR|NPROG==NPROG");
  add(LF_RPAG, "CODDITTA==CODDITTA|TIPOA==TIPOA|CODANAGR==CODANAGR|NPROG==NPROG");
}

void TSchedaPE::destroy_rows()
{
  _pag.destroy();
  _ver.destroy();
}

TRectype& TSchedaPE::pag(int i)
{
  TRectype* r = (TRectype*)_pag.objptr(i);
  if (r == NULL)
  {
    r = new TRectype(LF_RPAG);
    _pag.add(r, i);
  }
  return *r;
}

TRectype& TSchedaPE::ver(int i)
{
  TRectype* r = (TRectype*)_ver.objptr(i);
  if (r == NULL)
  {
    r = new TRectype(LF_RVER);
    _ver.add(r, i);
  }
  return *r;
}

int TSchedaPE::read_scperc_rows()
{
  const TLocalisamfile& rver = lfile(LF_RVER);
  const TLocalisamfile& rpag = lfile(LF_RPAG);
  position_rels();

  destroy_rows();
  int i = 0;

// "Se ho delle righe vuote devo raggruppare"
  for(bool ok = is_first_match(LF_RVER); ok; ok = next_match(LF_RVER))
    ver(i++)      = rver.curr();

  _old_ver = ver_items();
  
  i = 0;
  for(ok = is_first_match(LF_RPAG); ok; ok = next_match(LF_RPAG))
    pag(i++)      = rpag.curr();

  _old_pag = pag_items();

  return NOERR;
}

int TSchedaPE::read(TIsamop op, TReclock lockop, TDate& atdate)
{
  int err = file().read(op, lockop, atdate);
  if (err == NOERR) err = read_scperc_rows();
  return err;
}

int TSchedaPE::write_rec(bool re, const TRectype& rec, TLocalisamfile& f)
{
  if (re)
  {
    const bool scrivi = f.rewrite(rec) != NOERR;
    if (scrivi) f.write(rec);
  }
  else
  {
    f.write(rec);
  }

  return f.status();
}

int TSchedaPE::cancella(TLocalisamfile& f, int da, int a)
{
  const long codditta = lfile().get_long(SPR_CODDITTA);
  const char tipoa    = lfile().get_char(SPR_TIPOA);
  const long codanagr = lfile().get_long(SPR_CODANAGR);
  const int  nprog    = lfile().get_int (SPR_NPROG);
  
  for (int i = da; i <= a; i++)
  {
    f.zero();
    f.put(VER_CODDITTA, codditta);
    f.put(VER_TIPOA   , tipoa);
    f.put(VER_CODANAGR, codanagr);
    f.put(VER_NPROG   , nprog);
    f.put(VER_NRIGA   , i);
    if (f.read(_isequal, _lock) == NOERR)
      f.remove();
  }
  return f.status();
}

bool TSchedaPE::empty_vers(TRectype& ver)
{
  TString16 datv(ver.get("DATAVERS"));
  TString16 v15(ver.get("VERS1015"));

  datv.trim();
  v15.trim();  
  return (datv.empty() && v15.empty());
}

int TSchedaPE::registra(bool re, bool force)
{
  TLocalisamfile& sc = lfile();
  
  const int err = write_rec(re, sc.curr(), sc);
  if (err != NOERR) return err;

  TLocalisamfile& rver = lfile(LF_RVER);
  
  const long codditta = sc.get_long("CODDITTA");
  const char tipoa    = sc.get_char("TIPOA");
  const long codanagr = sc.get_long("CODANAGR");
  const int  nprog    = sc.get_int ("NPROG");
  
  for (int i = 0 ; i < ver_items(); i++)
  {     
    const bool vers_vuoto = empty_vers(ver(i));

    if (!re) 
    {
      ver(i).put("CODDITTA", codditta);
      ver(i).put("TIPOA"   , tipoa);
      ver(i).put("CODANAGR", codanagr);
      ver(i).put("NPROG"   , nprog);      
    }

    ver(i).put("NRIGA" , i+1);
    
    if (vers_vuoto)
    {
      if (i < _old_ver)
        cancella(rver, i+1, i+1);
    }
    else
    {
      const int err = write_rec(re, ver(i), rver);
      if (!force && err != NOERR) return err;
    }
  }

  if (i < _old_ver)
    cancella(rver, i+1, _old_ver);

  _old_ver = ver_items();
  
  TLocalisamfile& rpag = lfile(LF_RPAG);

  for (i = 0 ; i < pag_items(); i++)
  {                                  
    if (!re) 
    {
      pag(i).put("CODDITTA", codditta);
      pag(i).put("TIPOA"   , tipoa);
      pag(i).put("CODANAGR", codanagr);
      pag(i).put("NPROG"   , nprog);
    }
    pag(i).put("NRIGA"   , i+1);
        
    const int err = write_rec(re, pag(i), rpag);
    if (!force && err != NOERR) return err;
  }

  if (i < _old_pag)
    cancella(rpag, i+1, _old_pag);
  _old_pag = pag_items();

  return err;
}

int TSchedaPE::write(bool force, TDate&)
{
  return registra(FALSE, force);
}

int TSchedaPE::rewrite(bool force, TDate&)
{
  return registra(TRUE, force);
}

int TSchedaPE::remove(TDate&)
{
  TLocalisamfile& scheda  = lfile();
  TLocalisamfile& rver    = lfile(LF_RVER);
  TLocalisamfile& rpag    = lfile(LF_RPAG);
  
  cancella(rver, 1, _old_ver);
  cancella(rpag, 1, _old_pag);  
  scheda.remove();
  _old_ver = _old_pag = 0;
  return scheda.status();
}

