// 771232.cpp - Quadri G
#include <relapp.h>
#include <config.h>
#include <msksheet.h>
#include <sort.h>
#include <tabutil.h>
#include <execp.h>
#include <progind.h>
#include <defmask.h>

#include "quadrog.h"
#include "77lib.h"
#include "774200.h"
#include "771234a.h"   // G
#include "771232.h"

/////////////////////////////////////////////////////////////////////////////////////////////
//
// Lista modifiche:
//
// 17.4.96	Corretto scambio di colonne nel prospetto 3 in scrittura
//
//
/////////////////////////////////////////////////////////////////////////////////////////////

// Descrizioni prospetto 3
HIDDEN const char* p3_date_delib[20] = 
{
    "1-1-1976/31-12-1995",
    "1-1-1976/31-12-1995",
    "1-1-1976/31-12-1995",    
    "1-1-1976/31-12-1995",    
    "1-1-1976/31-12-1995",    
    "1-1-1976/31-12-1995",    
    "1-1-1976/31-12-1995",                
    "9-4-1974/31-12-1975", 
    "9-4-1974/31-12-1975",
    "9-4-1974/31-12-1975",
    "9-4-1974/31-12-1975",
    "1-1-1974/8-4-1974"  ,
    "1-1-1974/8-4-1974"  ,
    "1-1-1974/8-4-1974"  ,
    "24-2-1964/31-12-1973", 
    "24-2-1964/31-12-1973",
    "24-2-1964/31-12-1973",
    "1-1-1963/23-2-1964", 
    "1-1-1963/23-2-1964", 
    "1-1-1963/23-2-1964" 
};

// Aliquote prospetto 3  
HIDDEN const char* aliq[15] =
{
  "10",
  "12.5",
  "15",
  "30",
  "32.4",
  "50",
  "10",
  "15",
  "30",
  "10",
  "30",
  "5",
  "30",
  "8",
  "15"
};
  
// Date prospetto 2
HIDDEN const char* p2_date_delib[5] = 
{
    "1-1-1976/31-12-1995",
    "9-4-1974/31-12-1975",
    "1-1-1974/8-4-1974"  ,
    "24-2-1964/31-12-1973",
    "1-1-1963/23-2-1964" 
};
  

HIDDEN const int	RIGHE_P1 = 4;
HIDDEN const int	RIGHE_P2 = 5;
HIDDEN const int	RIGHE_PII = 3;
HIDDEN const int	RIGHE_PIII = 20;
HIDDEN const char*	DISTINTA_APP = "771mod -6 4";

#define	NUM_AZ		105
#define	AMM_AZ		104
#define	AMM_COMP	106

HIDDEN	real __amm_az = ZERO;
HIDDEN	real __num_az = ZERO;  

TQuadroG::TQuadroG(const char quadro)
{
  _registra   = _bUsatoDistinta = FALSE;
  switch (quadro)
  {
    case '3':
      _quadro = "G";  
      _title  = "Quadro G";
      break;
    default:
      break;
  }
}

inline TQuadroG& app() { return (TQuadroG&) main_app(); }

int TQuadroG::read(TMask& m)
{
  int err = TRelation_application::read(m);

  if (err == NOERR)
  {  
    fill_ss(m);  
    fill_arr(m);
  }  
  return err;
}

void TQuadroG::init_insert_mode (TMask& m)
{
  fill_ss(m);
  fill_arr(m);
}

void TQuadroG::init_modify_mode (TMask& m)
{
  m.disable(DLG_DELREC);
}

void TQuadroG::init_query_mode (TMask& m)
{
  TString16 codditta; codditta << _codditta;
  if (codditta != "0")        
  {
    m.field(F_CODDITTA).set(codditta);
    m.field(F_CODDITTA).check();
  }
  m.send_key(K_AUTO_ENTER,0);
}

void TQuadroG::update_totals(TSheet_field& f, int ss)
{
  int i = 0;
  switch (ss)
  {
    case 1:
    {
      real tot_numq, tot_amm;
      tot_numq = tot_amm = ZERO;
      TSheet_field&	p1 = f;
// Calcolo il totale
      for (i = 0;  i < RIGHE_P1; i++)
      {
        TToken_string& r = p1.row(i);
        real numq(r.get(4));
        real amm (r.get(5));     
        tot_numq += numq;
        tot_amm  += amm;
      }
// Setto le celle di totale
      TToken_string& row = p1.row(i);
      row.add(tot_numq.string(), 4);
      row.add(tot_amm.string(),  5);
      p1.force_update(i);
    }       
      break;
    case 2:
    {
      TSheet_field&	p2 = f;
      real tot_c2, tot_c3, tot_c4, tot_c5, tot_c6;
      tot_c2 = tot_c3 = tot_c4 = tot_c5 = tot_c6 = ZERO;
      for (i = 0;  i < RIGHE_P2; i++)
      {
        TToken_string& r2 = p2.row(i);
        real c2 (r2.get(1));
        real c3 (r2.get());   
        real c4 (r2.get());
        real c5 (r2.get());
        real c6 (r2.get());

        tot_c2 += c2;
        tot_c3 += c3;
        tot_c4 += c4;
        tot_c5 += c5;
        tot_c6 += c6;                  
      }
// Setto le celle di totale
      TToken_string& row2 = p2.row(i);
      row2.add(tot_c2.string(), 1);
      row2.add(tot_c3.string(), 2);
      row2.add(tot_c4.string(), 3);
      row2.add(tot_c5.string(), 4);
      row2.add(tot_c6.string(), 5);        
      p2.force_update(i);
    }
    break;      
  case 3:
    {
      real tot_valult;
      tot_valult = ZERO;
      TSheet_field&	pII = f;
// Calcolo il totale
      for (i = 0;  i < RIGHE_PII; i++)
      {
        TToken_string& r = pII.row(i);
        real val(r.get(2));
        tot_valult  += val;
      }
// Setto le celle di totale
      TToken_string& row = pII.row(i);
      row.add(tot_valult.string(), 2);
      pII.force_update(i);
    }       
    break;
  case 4:
    {
      real tcol2, tcol3, tcol5, tcol6, tcol7;
      tcol2 = tcol3 = tcol5 = tcol6 = tcol7 = ZERO;
      TSheet_field&	pIII = f;
// Calcolo il totale
      for (i = 0;  i < RIGHE_PIII; i++)
      {
        TToken_string& r = pIII.row(i);
        real c2(r.get(1));
        real c3(r.get(2));
        real c5(r.get(4));
        real c6(r.get(5));
        real c7(r.get(6));                        
        tcol2  += c2;
        tcol3  += c3;
        tcol5  += c5;
        tcol6  += c6;                
        tcol7  += c7;
      }
// Setto le celle di totale
      TToken_string& row = pIII.row(i);
      row.add(tcol2.string(), 1);
      row.add(tcol3.string(), 2);
      row.add(tcol5.string(), 4);
      row.add(tcol6.string(), 5);
      row.add(tcol7.string(), 6);                  
      pIII.force_update(i);
    }       
    break;
  default:
    break;
  }
}

// Quadro G prospetto 1 - I
// Calcola amm_complessivo = num_quote * amm_azione
bool TQuadroG::calc_amm(TMask_field& f, KEY k)
{
  if (k == K_TAB)
  {                    
    TMask& m = f.mask();
    real amm_az(m.get(AMM_AZ));
//    const int num_az = m.get_int(NUM_AZ);
// 12.6.96 num_az adesso e' un real!
    real rNumAz = m.get_real(NUM_AZ);
    bool ricalcola = FALSE;
    real amm_comp(m.get(AMM_COMP));
// Determina se uno dei valori e' stato modificato        
    ricalcola = ( (__amm_az != amm_az) || (__num_az != rNumAz) );
// Se non e' stato cambiato non toccare il totale gia' impostato    
    if (!ricalcola && amm_comp != ZERO)
      return TRUE;   
      
// Calcola e setta il valore
    real amm = ZERO;
    amm = amm_az * rNumAz;
    amm.trunc();
    m.set(AMM_COMP, amm.string());   
// Setta i flag usati per il confronto successivo
    __amm_az = amm_az;
    __num_az = rNumAz;
  }
  return TRUE;
}

bool TQuadroG::exec_distinta(TMask_field& f, KEY k)
{
  if (k == K_SPACE)
  {
    TExternal_app zzz(DISTINTA_APP);
    zzz.run();
// Fai il ricalcolo    
    app()._bUsatoDistinta = TRUE;
  }
  return TRUE;
}

bool TQuadroG::user_create() 
{
  _msk = new TMask("771234a");
  _rel = new TRelation(LF_QUAG);
  _codditta = get_firm_770();
  _msk->set_handler(DLG_DISTINTA, exec_distinta);  
  TSheet_field& p1 = (TSheet_field&) _msk->field(F_P1);  
  p1.set_notify(p1_notify);                          
  p1.sheet_mask().set_handler(NUM_AZ, calc_amm);
  p1.sheet_mask().set_handler(AMM_AZ, calc_amm);  
  TSheet_field& p2 = (TSheet_field&) _msk->field(F_P2);  
  p2.set_notify(p2_notify);                              
  TSheet_field& pII = (TSheet_field&) _msk->field(F_PII);
  pII.set_notify(pII_notify);          
  TSheet_field& pIII = (TSheet_field&) _msk->field(F_PIII);
  pIII.set_notify(pIII_notify);          
  return TRUE;
}

bool TQuadroG::user_destroy() 
{
  delete _rel; delete _msk;
  if (_registra || _bUsatoDistinta)
    _rip.set(_quadro);  
  return TRUE;
}                           

void TQuadroG::arr2rel(const TMask& m)
{
  TToken_string p3a;
  TToken_string p3b;
  TToken_string p3c;    
  TToken_string p3d;    
  TToken_string p3e;        
  TToken_string p3f;        
  TRectype& r = _rel->curr();        
  int dlg; dlg = 0;
  
// Prospetto 3 - Prospetto delle ritenute
  TSheet_field&	pIII = (TSheet_field&)m.field(F_PIII);
  
  for (int i = 0;  i < RIGHE_PIII; i++)
  {
    TToken_string& r = pIII.row(i);
    TString ut94 (r.get(1));  // Salto data delibera che e' fisso
    TString imp  (r.get());   
    TString ali  (r.get());
    TString racc (r.get());
    TString rimp (r.get());
    TString utnsogg (r.get());
                   	
    p3a.add(ut94);
    p3b.add(imp);
    p3c.add(ali);
    p3d.add(racc);
    p3e.add(rimp);
    p3f.add(utnsogg);        
  }

  r.put(QG_P33A, p3a);
  r.put(QG_P33B, p3b);

  r.put(QG_P35A, p3c);
  r.put(QG_P35B, p3d);

  r.put(QG_P36A, p3e);
  r.put(QG_P36B, p3f); 

// Salvo i totali che servono poi per i riporti e le stampe (774200.cpp)
  TToken_string& r_tot = pIII.row(i);
  real tot_col3(r_tot.get(2));
  real tot_col5(r_tot.get(4));  
  real tot_col6(r_tot.get(5));  
  real tot_col7(r_tot.get(6));    
  
  r.put(QG_P33TOT, tot_col3);
  r.put(QG_P35TOT, tot_col5);
  r.put(QG_P36TOT, tot_col6);
  r.put(QG_P37TOT, tot_col7);      
}

void TQuadroG::ss2rel(const TMask& m)
{
  TSheet_field&	p1 = (TSheet_field&)m.field(F_P1);
  TRectype& rec = _rel->curr();
  
  for (int i = 0;  i < RIGHE_P1; i++)
  {
    TToken_string& r = p1.row(i);
    TString datad (r.get(0));
    TString titol (r.get());   
    TString datap (r.get());
    TString ammq  (r.get());
    TString numq  (r.get());
    TString amm   (r.get());

// Costruisco i nomi dei campi (sono numerati)
    TString16 n_datad ("P1DATAD");
    n_datad << i+1;
    TString16 n_titol ("P1TITOLO");   
    n_titol << i+1;
    TString16 n_datap ("P1DATAP");            
    n_datap << i+1;
    TString16 n_ammq  ("P1AMMQ");
    n_ammq << i+1;
    TString16 n_numq  ("P1NUMQ");
    n_numq << i+1;
    TString16 n_amm   ("P1AMM");
    n_amm << i+1;

// Scrivo i suddetti campi nella relazione
    rec.put(n_datad, datad);
    rec.put(n_titol, titol);
    rec.put(n_datap, datap);
    rec.put(n_ammq, ammq);
    rec.put(n_numq, numq);
    rec.put(n_amm, amm);
  }
// Salvo i totali                
  TToken_string& r = p1.row(i);
  TString tot_numq  (r.get(4));
  TString tot_amm   (r.get(5));
  rec.put("P1NUMQT", tot_numq);    
  rec.put("P1AMMT",  tot_amm);    
  
// costruisco le token_string leggendole dallo spreadsheet
  TToken_string p22(200);
  TToken_string p23(200);
  TToken_string p24(200);    
  TToken_string p25(200);    
  TToken_string p26(200);        
  
  TSheet_field&	p2 = (TSheet_field&)m.field(F_P2);
  for (i = 0;  i < RIGHE_P2; i++)
  {
    TToken_string& r = p2.row(i);
    TString c2 (r.get(1));
    TString c3 (r.get());   
    TString c4 (r.get());
    TString c5  (r.get());
    TString c6  (r.get());
    p22.add(c2);
    p23.add(c3);  
    p24.add(c4);  
    p25.add(c5);      
    p26.add(c6);      
  }
// scrivo finalmente nel file le tokens. di cui sopra  
  rec.put("P22", p22);
  rec.put("P23", p23);
  rec.put("P24", p24);
  rec.put("P25", p25);  
  rec.put("P26", p26);    
// scrivo i totali
  TToken_string& r2 = p2.row(i);
  TString tc2 (r2.get(1));
  TString tc3 (r2.get());   
  TString tc4 (r2.get());
  TString tc5 (r2.get());
  TString tc6 (r2.get());
  rec.put("P22TOT", tc2);
  rec.put("P23TOT", tc3);
  rec.put("P24TOT", tc4);
  rec.put("P25TOT", tc5);
  rec.put("P26TOT", tc6);      

// Prospetto 1 - II Utili in natura
  TSheet_field&	pII = (TSheet_field&)m.field(F_PII);
//  TRectype& rec = _rel->curr();
  
  for (i = 0;  i < RIGHE_PII; i++)
  {
    TToken_string& r = pII.row(i);
    TString descr (r.get(0));
    TString datad (r.get());   
    TString val   (r.get());

// Costruisco i nomi dei campi (sono numerati)
    TString16 n_descr ("P2DESC");
    n_descr << i+1;
    TString16 n_data ("P2DATA");   
    n_data << i+1;
    TString16 n_val ("P2VAL");            
    n_val << i+1;

// Scrivo i suddetti campi nella relazione
    rec.put(n_descr, descr);
    rec.put(n_data,  datad);
    rec.put(n_val,   val);
  }
// Salvo i totali                
  TToken_string& rII = pII.row(i);
  TString tot_val  (rII.get(2));
  rec.put(QG_P2VALT, tot_val);    
}

void TQuadroG::fill_arr(TMask& m)
{                                      
  TRectype& r = _rel->curr();        
  TToken_string p3a(r.get("P33A"));
  TToken_string p3b(r.get("P33B"));
  TToken_string p3c(r.get("P35A"));    
  TToken_string p3d(r.get("P35B"));    
  TToken_string p3e(r.get("P36A"));        
  TToken_string p3f(r.get("P36B"));        
  int dlg, j; dlg = j = 0;

  TSheet_field&	pIII = (TSheet_field&)m.field(F_PIII);
  const int COL_ALIQ = 3;
  int       ind_aliq = 0;
  for (int i = 1; i <= RIGHE_PIII; i++)
  { 
    TRectype& r = _rel->curr();        
    TToken_string& row = pIII.row(i-1);
    row.add(p3_date_delib[i-1]);
    row.add(p3a.get(i-1));
    row.add(p3b.get(i-1));
    row.add(p3c.get(i-1));
    row.add(p3d.get(i-1));
    row.add(p3e.get(i-1));
    row.add(p3f.get(i-1));           

    if (i != 7 && i != 11 && i != 14 && i != 17 && i != 20)
    {
      row.add(aliq[ind_aliq++], 3);
      pIII.disable_cell(i-1, COL_ALIQ);
    }
  }
  
  if (m.mode() == MODE_MOD)
    update_totals(pIII,4);
  else
  {
// Aggiungo la riga per i totali     
    TToken_string& row = pIII.row(i-1);
    row.add("Totali", 0);
    pIII.disable_cell(i-1, -1);
    pIII.force_update();
  }
}

void TQuadroG::fill_ss(TMask& m)
{
  TSheet_field&	p1 = (TSheet_field&)m.field(F_P1);
  for (int i = 1; i <= RIGHE_P1; i++)
  { 
    TRectype& r = _rel->curr();        
    TToken_string& row = p1.row(i-1);

// Costruisco i nomi dei campi (sono numerati)
    TString16 n_datad ("P1DATAD");
    n_datad << i;
    TString16 n_titol ("P1TITOLO");   
    n_titol << i;
    TString16 n_datap ("P1DATAP");            
    n_datap << i;
    TString16 n_ammq  ("P1AMMQ");
    n_ammq << i;
    TString16 n_numq  ("P1NUMQ");
    n_numq << i;
    TString16 n_amm   ("P1AMM");
    n_amm << i;

// Leggo i campi
    TString datad (r.get(n_datad));
    TString titol (r.get(n_titol));   
    TString datap (r.get(n_datap));
    TString ammq  (r.get(n_ammq));
    TString numq  (r.get(n_numq));
    TString amm   (r.get(n_amm));

    row.add(datad);
    row.add(titol);
    row.add(datap);
    row.add(ammq);
    row.add(numq);
    row.add(amm);    
  }
  if (m.mode() == MODE_MOD)
    update_totals(p1,1);
  else
  {
// Aggiungo la riga per i totali     
    TToken_string& row = p1.row(i-1);
    row.add("Totali", 1);
    p1.disable_cell(i-1, -1);
    p1.force_update();
  }

  TRectype& r = _rel->curr();        
  TToken_string p22(r.get("P22"));
  TToken_string p23(r.get("P23"));
  TToken_string p24(r.get("P24"));    
  TToken_string p25(r.get("P25"));    
  TToken_string p26(r.get("P26"));        
  
  TSheet_field&	p2 = (TSheet_field&)m.field(F_P2);
  for (i = 1; i <= RIGHE_P2; i++)
  { 
    TToken_string& row2 = p2.row(i-1);
    row2.add(p2_date_delib[i-1]);
    row2.add(p22.get(i-1));    
    row2.add(p23.get(i-1));    
    row2.add(p24.get(i-1));    
    row2.add(p25.get(i-1));            
    row2.add(p26.get(i-1));    
  }
  if (m.mode() == MODE_MOD)
    update_totals(p2,2);
  else
  {
// Aggiungo la riga per i totali     
    TToken_string& row2 = p2.row(i-1);   
    row2.add("Totali", 0);  
    p2.disable_cell(i-1, -1);
    p2.force_update();
  }

  TSheet_field&	pII = (TSheet_field&)m.field(F_PII);
  for (i = 1; i <= RIGHE_PII; i++)
  { 
    TRectype& r = _rel->curr();        
    TToken_string& row = pII.row(i-1);

// Costruisco i nomi dei campi (sono numerati)
    TString16 pII_desc ("P2DESC");
    pII_desc << i;
    TString16 pII_data ("P2DATA");   
    pII_data << i;
    TString16 pII_val ("P2VAL");            
    pII_val << i;

// Leggo i campi
    TString descr (r.get(pII_desc));
    TString datap (r.get(pII_data));   
    TString valul (r.get(pII_val));

    row.add(descr);
    row.add(datap);
    row.add(valul);
  }
  if (m.mode() == MODE_MOD)
    update_totals(pII,3);
  else
  {
// Aggiungo la riga per i totali     
    TToken_string& row = pII.row(i-1);
    row.add("Totale utili in natura", 0);
    pII.disable_cell(i-1, -1);
    pII.force_update();
  }
}

int TQuadroG::write(const TMask& m)
{
  ss2rel(m);  
  arr2rel(m);
  int err = TRelation_application::write(m);
  _registra = err == NOERR;    
  return err;
}

int TQuadroG::rewrite(const TMask& m)
{
  ss2rel(m);
  arr2rel(m);
  int err = TRelation_application::rewrite(m);
  _registra = err == NOERR;    
  return err;
}

bool TQuadroG::remove()
{  
  const bool ok = TRelation_application::remove();
  return ok;
}

bool TQuadroG::p1_notify(TSheet_field& s, int r, KEY k)
{
  switch(k)
  {                               
    case K_ENTER:
      __amm_az = ZERO;
      __num_az = ZERO;
      update_totals(s, 1);    
      break;
    case K_SPACE: 
      {
      TToken_string& row = s.row(r);
      __num_az  = row.get(3);
      __amm_az  = row.get(4);
      }
      break;
// Rifiuta di entrare sull'ultima riga
    case K_TAB: 
      return r < RIGHE_P1;
      break;
    case K_INS:                   
      if (s.mask().is_running())
        return FALSE;  // rifiuta inserimento di nuove righe
      break;
    default:
      break;
  }
  return TRUE;
}

bool TQuadroG::p2_notify(TSheet_field& s, int r, KEY k)
{
  switch(k)
  {                               
    case K_SPACE: 
      break;
    case K_ENTER:
      update_totals(s, 2);    
      break;
// Rifiuta di entrare sull'ultima riga
    case K_TAB: 
      return r < RIGHE_P2;
      break;
    case K_INS:                   
      if (s.mask().is_running())
        return FALSE;  // rifiuta inserimento di nuove righe
      break;
    default:
      break;
  }
  return TRUE;
}

bool TQuadroG::pII_notify(TSheet_field& s, int r, KEY k)
{
  switch(k)
  {                               
    case K_SPACE: 
      break;
    case K_ENTER:
      update_totals(s, 3);    
      break;
// Rifiuta di entrare sull'ultima riga
    case K_TAB: 
      return r < RIGHE_PII;
      break;
    case K_INS:                   
      if (s.mask().is_running())
        return FALSE;  // rifiuta inserimento di nuove righe
      break;
    default:
      break;
  }
  return TRUE;
}

bool TQuadroG::pIII_notify(TSheet_field& s, int r, KEY k)
{
  switch(k)
  {                               
    case K_SPACE: 
      break;
    case K_ENTER:
      update_totals(s, 4);    
      break;
// Rifiuta di entrare sull'ultima riga
    case K_TAB: 
      return r < RIGHE_PIII;
      break;
    case K_INS:                   
      if (s.mask().is_running())
        return FALSE;  // rifiuta inserimento di nuove righe
      break;
    default:
      break;
  }
  return TRUE;
}