#include "ef0101.h"

//////////////////////////////////////////////////
// Definizione dei metodi della classe TEffetto // 
//////////////////////////////////////////////////

// costruttore di default 
TEffetto::TEffetto()
        : TRectype(LF_EFFETTI), _righe(LF_REFFETTI, REFF_NRIGATR), _cess(LF_CESS, CES_NRIGA)
{                                 
}

// costuisce l'effetto con il record passato
TEffetto::TEffetto(TRectype& rec)
        : TRectype(LF_EFFETTI), _righe(LF_REFFETTI, REFF_NRIGATR), _cess(LF_CESS, CES_NRIGA)
{        
   TLocalisamfile f(LF_EFFETTI);
   read(f,rec);                           
}

TEffetto::TEffetto(const TEffetto& eff)
        : TRectype(eff), _righe(eff._righe), _cess(eff._cess)
{
}

TObject* TEffetto::dup() const 
{
  TEffetto* e = new TEffetto((const TEffetto&)*this);
  return e;
}

// setta i campi per la prima chiave (nprogtr) 
void TEffetto::put_key(TRectype& rec, long numeff) const
{
  CHECKD(numeff >= 0, "Numero effetto non valido ", numeff);
  rec.put(EFF_NPROGTR, numeff);
}

// setta i campi per la quarta chiave (tipodist+ndist+nrigadist) 
void TEffetto::put_key(TRectype& rec,char tipodist, long ndist, long nrigadist)
{
  CHECK(tipodist == 'I' || tipodist == 'S' || tipodist == 'B' || tipodist == 0, "Tipo distinta");
  CHECKD(ndist >= 0, "Numero distinta non valido ", ndist);
  CHECKD(nrigadist >= 0, "Numero riga distinta non valido ", nrigadist);
  rec.put(EFF_TIPODIST, tipodist); 
  rec.put(EFF_NDIST, ndist);
  rec.put(EFF_NRIGADIST, nrigadist);
}

// ritorna la prossima chiave utilizzabile  
long TEffetto::get_next_key(const long codcf) const
{               
  static long n = 0;
  if (n == 0)
  {
    TLocalisamfile eff(LF_EFFETTI);
    TRectype& curr = eff.curr();
    put_key(curr, 9999999L);
    const int err = eff.read(_isgreat);
    if (err != _isemptyfile)
    {
      if (err == NOERR)
        eff.prev();
      if (curr.get_long(EFF_CODCF) == codcf)
        n = curr.get_long(EFF_NPROGTR);
    }     
  }      
  n++;
  return n;   
}

// rinumera la chiave 1 (nprogtr)
long TEffetto::renum(long numeff)
{
  if (numeff <= 0)
  {                             
    long codcf = codicec();
    numeff  = get_next_key(codcf);
  }   
  char num[7]; sprintf(num, "%ld", numeff);
  renum_key(EFF_NPROGTR, num);        // aggiorna testata
  _righe.renum_key(EFF_NPROGTR, num); // aggiorna righe ok
  _cess.renum_key(EFF_NPROGTR, num);  // aggiorna cessionari ok
  return numeff;
}

// restituisce il prossimo effetto
int TEffetto::next(TBaseisamfile& f)
{ 
  const int err = f.next(); 
  *this = f.curr();
  return err;  
}

// permette di leggere il record passato nel file passato, comune alla
// lettura per chiave 1 e per chiave 4 
int TEffetto::leggi(TLocalisamfile &f, const TRectype& r)   
{ 
  int err = TRectype::read(f); 
  const long nu = numero();
  // necessari per poter andare a leggere i due record array
  // cessionari e righe effetto 
  TRectype *k_reff = new TRectype(LF_REFFETTI),
           *k_cess = new TRectype(LF_CESS);             
  // setto la chiave per poter leggere dai due record array
  put_key(*k_reff, nu);                       
  put_key(*k_cess, nu);                       
  if (err == NOERR)
  { // leggo dai record array                                           
    _righe.read(k_reff); 
    _cess.read(k_cess);
  }  
  else // se ho trovato un errore
  {
    head() = r;          
    const long nu = numero();
    put_key(*k_reff, nu);
    put_key(*k_cess, nu);
    if (nu !=0)
    { 
      destroy_rows_r();
      destroy_rows_c();
      _cess.set_key(k_cess);
      _righe.set_key(k_reff); 
    }
  }  
  return err;    
}

// legge il record passato, con chiave 1
int TEffetto::read(TLocalisamfile& f, const TRectype& rec)
{ 
  head() = rec;  
  return leggi(f, rec); 
}

// legge l'effetto usando la chiave 4
int TEffetto::read(TLocalisamfile& f, char tipodist, long ndist, long nrigadist)
{ 
  f.setkey(4);                        
  TRectype rec(LF_EFFETTI);
  put_key(rec, tipodist, ndist, nrigadist);   
  head() = rec;
  return leggi(f, rec);
}

// scrive l'effetto, usando la chiave 1
int TEffetto::write(TLocalisamfile& f, bool force)
{ 
  const bool nuovo = numero() <= 0;   // E' nuovo!
  if (nuovo && force)                 // quindi ...
    force = FALSE;                    // ... non fare la rewrite
  f.setkey(1); 
  int err = NOERR;
  if (force)
  {
    if ((err=_righe.write(force)) == NOERR) err= _cess.write(force); 
    if (err == NOERR)
    {
      err = TRectype::rewrite(f);
      if (err != NOERR)
        err = TRectype::write(f);
    }
   }     
   else
  {             
    if (nuovo)
    {         
      TEffetto& myself = *(TEffetto*)this;
      if (numero() <= 0)
        myself.renum();
      do
      {
        err = TRectype::write(f);
        if (err == _isreinsert)
          myself.renum();
      } while (err == _isreinsert);
     }
    else 
    {
      err = TRectype::write(f);
      if (err != NOERR)
        err = TRectype::rewrite(f);
    }    
    if (err == NOERR)
      if ((err=_righe.write(force)) == NOERR) err= _cess.write(force); 
  }
  return err;  
}

// rimuove l'effetto
int TEffetto::remove(TLocalisamfile& f)const
{     
  int err;
  if ((err=_righe.remove()) == NOERR) err= _cess.remove(); 
  if (err == NOERR)
    err = TRectype::remove(f);
  return err;  
}

// restituisce true se l'effetto si riferisce ad una sola fattura
// ovvero se l'effetto non è raggruppato
bool TEffetto::fatt(long num)
{                        
   TLocalisamfile righe_eff(LF_REFFETTI);  
   righe_eff.put(REFF_NPROGTR, num);
   righe_eff.read();  
   // prende il numero delle righe dell'effetto 
   // ovvero di fatture a cui fa riferimento
   int items = rows_r();
   bool condition = (items == 1); 
   return condition; 
}      

// restituisce i dati relativi alle fatture a cui si riferisce l'effetto  
// costruendo una TToken_string del tipo
// "num_fatt0|data_fatt0|imp_fatt0|num_fatt1|data_fatt1|imp_fatt1|..."
TToken_string* TEffetto::dati_fatt(long num)
{  
   TToken_string* dati= new TToken_string;    
   dati->cut(0);    
                   
   TLocalisamfile righe_eff(LF_REFFETTI);  
   righe_eff.put(REFF_NPROGTR, num);
   righe_eff.read();  
   int items = rows_r();           // prende il numero delle righe dell'effetto
   for (int i = 1; i <= items; i++)// le legge tutte 
   { 
     dati->add(righe_eff.get(REFF_NFATT));//prende il numero   
     dati->add(righe_eff.get(REFF_DATAFATT));//prende la data
     dati->add(righe_eff.get(REFF_IMPFATT));//prende l' importo 
     righe_eff.next();// passa alla riga successiva
    }                              
   return dati; 
}      
