// --------------------------------------------------------------------------
// Scadenzario
// fv 24/8/94
// --------------------------------------------------------------------------

#include "cg2102.h"
#include "cg2100.h"
#include "cg2104a.h"
#include "pagament.h"

struct shuttle 
{
  Pagamento*    _pag;      // pagamento
  TSheet_field* _sheet;    // sheet       
  TMask*        _mask;     // maschera
  TArray*       _rows;     // righe spreadsheet nella versione originale
};

bool TPrimanota_application::pag_notify(int r, KEY k)
{                                                          
  // questo e' il bello
  shuttle* sh = (shuttle*)(((TPrimanota_application&)main_app()).get_app_data());

  Pagamento*    pag = sh->_pag;
  TSheet_field* ps  = sh->_sheet; 
  TMask*        msk = sh->_mask;      
  TArray*       rws = sh->_rows;                                
  
  int rdiff = atoi(msk->get(F_RDIFFER));
  
  // ts contiene la vecchia riga, ns la nuova                                       
  TToken_string ts(36), ns(36);

  
  bool doit = TRUE, m_imp = FALSE, m_perc = FALSE, m_pag = FALSE;
  bool m_scad = FALSE, m_tipo = FALSE, mod = FALSE;
  word ahiahi = P_OK;                                
  
  TString news(15), newi(15), newp(15), newt(2);                                  

  bool recalc = msk->get_bool(F_RECALC); 
  bool mcomm  = msk->get_bool(F_MCOMM);
  
  switch (k)
  {
  case K_SPACE:
    break;
  case K_ENTER:
    ns  = ps->row(r);     
    ts  = (TToken_string&)(*rws)[r];    
    
    news = ns.get(0);
    newp = ns.get(1);
    newi = ns.get(2);
    newt = ns.get(3);                                            
    
    // qui viene il bello, si fa per dire 
    if (strcmp(ts.get(0),news) != 0)  // modificata data scadenza
    {                            
      mod  = m_scad = TRUE;        
    }
    if (strcmp(ts.get(1),newp) != 0)  // modificata percentuale
    {                
      mod  = m_perc = TRUE;        
    }
    if (strcmp(ts.get(2),newi) != 0)  // modificato importo
    {          
      if ((recalc && !m_perc) || (!recalc))  // se si modifica la percentuale l'importo non viene cagato
      {
        mod  = m_imp = TRUE;   
      }
    }
    if (strcmp(ts.get(3),newt) != 0)  // modificato tipo pagamento
    {                 
      mod = m_tipo  = TRUE;      
    }
    break;
  case K_DEL:
  case K_INS:
    doit = FALSE;
    break;
  default:
    break;
  }          
  

  // settato da recalc_rate se occorre ridefinire lo sheet
  // aggiungendo o togliendo righe
  bool need_recalc = FALSE;      

  if (k == K_ENTER) 
  {
    if (mod && recalc)
    {
      // ricalcola sheet come sai fare tu
      ahiahi = pag->recalc_rate(r, m_perc, 
                                ((m_perc || m_imp) ? 
                                 (m_perc ? (const char*)newp : (const char*)newi) : 
                                 NULL), 
                                (m_scad ? (const char*)news : NULL),
                                (m_tipo ? (const char*)newt : NULL), 
                                rdiff, mcomm, need_recalc);
      // see if rdiff changed                          
      msk->field(F_RDIFFER).set(pag->rate_differenziate() ? "1" : "2");
    }
    if (!recalc)
    {                              
      ahiahi = P_OK;
      // put data as they are
      TToken_string& trw = pag->rata(r);
      TToken_string  srw = trw;
      if (m_scad)  trw.add(news,3);
      if (m_perc)  trw.add(newp,1);
      if (m_imp)   trw.add(newi,4);
      if (m_tipo)  trw.add(newt,2);
      // validate the payment
      if ((ahiahi = pag->validate()) != P_OK)
        pag->rata(r) = srw;
    }
    if (ahiahi)  // any error?
      // rimetti le righe com'erano prima
    {  
      beep(); 
      
      // se gli errori sono voluti, spiegali
      if (!recalc)
      {                    
        TString s(256);
        pag->strerr(ahiahi,s);
        warning_box(s);
      }
      
      ps->row(r) = (TToken_string&)(*rws)[r]; 
      ps->force_update(r); 
    } 
    
      else if (recalc && mod && need_recalc) 
      {                                   
        // ridefinisci lo sheet sulla base delle nuove rate
        pag->set_sheet(*ps);
        ps->force_update(-1);         
        rws->destroy();
        (*rws) = ps->rows_array();      
      } 
  }
  
  return doit;
}                            

void TPrimanota_application::aggiorna_scadenzario(const TMask& m)
{                                                                  
  real      imponibile(0.0);   
  real      imposta(0.0);   
  real      spese(0.0);        
  TString   dt(m.get(F_DATAREG));
  Pagamento pag(m.get(F_CODPAG), (const char*)dt);

  if (pag.is_new()) return;

  TMask ms("cg2104a");  
  TSheet_field& ps = (TSheet_field&)ms.field(F_RATESHEET);
  ps.set_notify(pag_notify);                        
  
  ms.field(F_RDIFFER).set(pag.rate_differenziate() ? "1" : "2");
  ms.field(F_NAMEPAG).set(pag.name());
  ms.field(F_TIPOPR).set(pag.desc_tpr());
  ms.field(F_MCOMM).set(pag.mese_commerciale() ? "X" : "");
  
  TSheet_field& iva_sh = ivas();
  
  for (int i = 0; i < iva_sh.items(); i++)
  {
    TToken_string& tt = iva_sh.row(i);
    real mpo(tt.get(0)); 
    real imp(tt.get(3));
    imponibile += mpo;
    imposta    += imp;
    // TBI: le spese che cazzo sono?
    // -----------------------------
  }                    
  
  ms.field(F_IMPONIBILE).set(imponibile.string());
  ms.field(F_IMPOSTA).set(imposta.string());
  ms.field(F_SPESE).set(spese.string());
  ms.field(F_RECALC).set("X");

  pag.set_total(imponibile, imposta, spese);                              

  // se c'e' una rateazione gia' registrata
  // zappettare e settare le rate a mano  
  bool new_part = FALSE;

  // should never happen but it doesn't hurt
  if (_rel->cg(0).empty()) return; 

  TLocalisamfile partita (LF_PARTITE);
  TLocalisamfile scadenza(LF_SCADENZE);
  
  TString nreg(_rel->lfile().get("NUMREG"));
  TString ndoc(_rel->lfile().get("NUMDOC"));
  TString tmov(_rel->lfile().get("TIPOMOV"));
  TDate   ddoc(_rel->lfile().get_date("DATADOC"));
  TDate   dreg(_rel->lfile().get_date("DATAREG"));                                    
  TString reg (_rel->lfile().get("REG")); 
  TString protiva(_rel->lfile().get("PROTIVA")); 
  TString codcaus(_rel->lfile().get("CODCAUS")); 
  TString codval (_rel->lfile().get("CODVAL")); 
  TString cambio (_rel->lfile().get("CAMBIO")); 
  
  TString numpart = m.get(F_NUMRIF);
  TString anno    = m.get(F_ANNORIF);
  
  char sezione    = _rel->cg(0).get_char("SEZIONE"); // Dare/Avere
  char tipocf     = _rel->cg(0).get_char("TIPOC"); // Cliente || Fornitore || Uncazzo
  int  gruppo     = (tipocf == 'C' || tipocf == 'F') ? 0 : 
  _rel->cg(0).get_char("GRUPPO");
  int  conto      = (tipocf == 'C' || tipocf == 'F') ? 0 : 
  _rel->cg(0).get_char("fCONTO");
  long sottoconto = _rel->cg(0).get_long("SOTTOCONTO");
  int  nriga      = 1;
  int  numrig     = 1;
  
  partita.put("TIPOCF",     tipocf);
  partita.put("GRUPPO",     gruppo);
  partita.put("CONTO",      conto);
  partita.put("SOTTOCONTO", sottoconto);
  partita.put("ANNO",       anno);
  partita.put("NUMPART",    numpart);
  partita.put("NRIGA",      nriga);
  
  bool fromscratch = FALSE;
  
  if (partita.read() == NOERR)
  {    
    // se si e' specificato un codice pagamento diverso si rifa' da capo       
    if (pag.code() != partita.get("CODPAG"))
      fromscratch = TRUE;                                       
    // se invece la maschera contiene importi diversi da quelli
    // registrati si passa la palla al culano
    else if (imponibile != partita.get_real("IMPORTO") || 
             imposta    != partita.get_real("IMPOSTA") ||
             spese      != partita.get_real("SPESE"))  
    {
      fromscratch = !yesno_box("Gli importi totali sono stati modificati rispetto"
                               " all'ultima registrazione. Si desidera mantenere"
                               " comunque la rateazione precedente");
      // nel caso, of course, si disabilitano gli automatismi
      if(!fromscratch) ms.field(F_RECALC).set("");
    }
    if (fromscratch)
      pag.set_rate_auto();
    else
    {    
      pag.zap_rate();

      for (int i = 0; ; i++)
      { 
        // cerca rata            
        scadenza.zero();
        scadenza.put("TIPOCF",     tipocf);
        scadenza.put("GRUPPO",     gruppo);
        scadenza.put("CONTO",      conto);
        scadenza.put("SOTTOCONTO", sottoconto);
        scadenza.put("ANNO",       anno);
        scadenza.put("NUMPART",    numpart);
        scadenza.put("NRATA",      i+1);
        
        if (scadenza.read() == NOERR)
        {
          // TBI setta rate
          real  importo = scadenza.get("IMPORTOVAL"); 
          TDate scad    = scadenza.get("DATASCAD");
          int tipop     = scadenza.get_int("TIPOPAG");     
          bool paid     = scadenza.get_bool("PAGATA");
          TString ulc(scadenza.get("ULTCLASS"));
          
          pag.set_rata(i, importo, scad, tipop, ulc, paid);
        } 
        else break; 
      } // for
    } //else
  }
  else
  {
    pag.set_rate_auto();          
    new_part = TRUE; 
  }  
  
  // prepara lo sheet
  pag.set_sheet(ps);
  TArray rows(ps.rows_array());

  // se la prima rata e' fissa non si tocca
  if (pag.tipo_prima_rata() > 0)
  {
    ps.disable_cell(0,0);
    ps.disable_cell(0,1);
    ps.disable_cell(0,2);
    ps.disable_cell(0,3);
  }              
  
  
  shuttle sh;
  
  sh._pag    = &pag;
  sh._sheet  = &ps;
  sh._mask   = &ms;              
  sh._rows   = &rows;
  
  set_app_data(&sh); 
  
  if (ms.run() == K_SAVE) 
  {
    // se modificato riaggiusta partite e scadenze
    if (pag.dirty() || new_part)
    {
      if (new_part) 
      {
        partita.zero(); 
        partita.put("TIPOCF",     tipocf);
        partita.put("GRUPPO",     gruppo);
        partita.put("CONTO",      conto);
        partita.put("SOTTOCONTO", sottoconto);
        partita.put("ANNO",       anno);
        partita.put("NUMPART",    numpart);
        partita.put("NRIGA",      nriga);
      }   
      // put data on partita
      partita.put("TIPOMOV",tmov);
      partita.put("NREG",   nreg);
      partita.put("DATAREG",dreg);
      partita.put("DATADOC",ddoc);
      partita.put("REG",    reg);
      partita.put("PROTIVA",protiva);
      partita.put("CODCAUS",codcaus);
      partita.put("SEZ",    sezione);
      partita.put("CODPAG", pag.code());
      partita.put("CODVAL", codval);
      partita.put("CAMBIO", cambio);
      partita.put("IMPORTO",pag.imponibile());
      partita.put("IMPOSTA",pag.imposta());
      partita.put("SPESE",  pag.spese());
      partita.put("NUMRIG", numrig);
      
      if (new_part) partita.write(); 
      else          partita.rewrite();
      
      bool new_scad = FALSE;
      
      for (int i = 0; i < pag.n_rate(); i++)
      {  
        new_scad = FALSE;
        scadenza.zero();         
        scadenza.put("TIPOCF",     tipocf);
        scadenza.put("GRUPPO",     gruppo);
        scadenza.put("CONTO",      conto);
        scadenza.put("SOTTOCONTO", sottoconto);
        scadenza.put("ANNO",       anno);
        scadenza.put("NUMPART",    numpart);
        scadenza.put("NRATA",      i+1);
        
        if (scadenza.read() != NOERR)
        {   
          new_scad = TRUE;
          scadenza.zero();
          scadenza.put("TIPOCF",     tipocf);
          scadenza.put("GRUPPO",     gruppo);
          scadenza.put("CONTO",      conto);
          scadenza.put("SOTTOCONTO", sottoconto);
          scadenza.put("ANNO",       anno);
          scadenza.put("NUMPART",    numpart);
          scadenza.put("NRATA",      i+1);
        }
        // set everything 
        scadenza.put("CODPAG",    pag.code());
        scadenza.put("TIPOPAG",   pag.tipo_rata(i));
        scadenza.put("ULTCLASS",  pag.ulc_rata(i));
        scadenza.put("IMPORTOVAL",pag.tpay_rata(i));
        scadenza.put("DATASCAD",  pag.data_rata(i));
        scadenza.put("PAGATA",    pag.ratapagata(i));
        
        if (new_scad) scadenza.write();
        else          scadenza.rewrite();
      }  
      // elimina eventuali altre scadenze oltre l'ultima registrata
      for (; !new_scad ; i++)
      {  
        scadenza.zero();
        scadenza.put("TIPOCF",     tipocf);
        scadenza.put("GRUPPO",     gruppo);
        scadenza.put("CONTO",      conto);
        scadenza.put("SOTTOCONTO", sottoconto);
        scadenza.put("ANNO",       anno);
        scadenza.put("NUMPART",    numpart);
        scadenza.put("NRATA",      i+1);
        
        if (scadenza.read() == NOERR)
          scadenza.remove();
        else new_scad = TRUE;
      }
    }
  }                       
}
