// 771231.cpp - Quadri F
//
#include <relapp.h>
#include <defmask.h>  
#include <msksheet.h>
#include <recarray.h>

#include "77lib.h"
#include "774200.h"
#include "771231a.h"  // F, F-1
#include "771232.h"   // quadro G
#include "prospe1.h"
#include "quadrif.h"
#include "ca7.h"
                
// Righe spreadsheet F                
#define S_CODC  101
#define S_DESC  102
#define S_ALIQ  103
#define S_SOGG  104
#define S_ROPE  105
#define S_SOMM  106

class TQuadroF : public TRelation_application
{
  private:
    TRelation*      _rel;
    TMask*          _msk;

    int             _anno_dic;  // anno dichiarazione
    long            _codditta;
    TRecord_array*  _prosp_a, *_prosp_b, *_prosp_c;
    bool            _registra;
    
    static void     calcola_ritenuta_operata(TMask& m, char prosp);
    static bool     aliq_handler(TMask_field& f, KEY k);
    static bool     sogg_handler(TMask_field& f, KEY k);
    static bool     rope_handler(TMask_field& f, KEY k);

    static bool     dprov_handler(TMask_field& f, KEY k);        
    static bool     daliq_handler(TMask_field& f, KEY k);        
    
    static bool     mainmsk_handler(TMask& m, KEY k);        

    int salva_prospetto(char prosp, bool re);

  protected:
    virtual bool  user_create();
    virtual bool  user_destroy();
    virtual int   read(TMask& m);
    virtual int   rewrite(const TMask& m);
    virtual int   write  (const TMask& m);  
    virtual bool  remove();
    virtual TRelation*  get_relation() const { return _rel; }
    virtual TMask*  get_mask(int mode) { return _msk; }
    virtual bool  changing_mask(int mode) { return FALSE; }
    virtual void  init_query_mode (TMask&);
    virtual void  init_insert_mode (TMask&);
    virtual void  init_modify_mode (TMask&);
    
    void init_mask (TMask&);
    void init_sheet(TSheet_field& s);
    void fill_ss();
    void ss_pack(TSheet_field& ss) const;
    void riempi_prospetto(const char prosp);
    int  re_write(bool re);

  public:                      
    TString _quadro, _title;
    const char* taitol() const { return _title; }
    
    TQuadroF(char quadro = '0');
    virtual ~TQuadroF() {};
};                    

TQuadroF::TQuadroF(char quadro)
{
  _registra = FALSE;
  switch (quadro)
  {
    case '0':
      _quadro = "F";  
      _title  = "Quadro F";
      break;
    case '1':
      _quadro = "F1";  
      _title  = "Quadro F1";
      break;
    case '2':
      _quadro = "F2";  
      _title  = "Quadro F2";
      break;
    default:
      break;
  }
}

inline TQuadroF& app() { return (TQuadroF&) main_app(); }
                                          
void TQuadroF::init_insert_mode (TMask& m)
{                                                                   
  init_mask(m);
}
                                          
void TQuadroF::init_modify_mode (TMask& m)
{                                                                   
//  m.disable(DLG_DELREC);   // disabilito Elimina nella toolbar
}

void TQuadroF::init_query_mode (TMask& m)
{
  TString16 codditta;
  codditta << _codditta; 
  TMask_field& f = m.field(DLG_CODDITTA);
  f.set(codditta);
  f.check();
  m.send_key(K_AUTO_ENTER,0);
}

void TQuadroF::init_mask (TMask&)
{
  fill_ss();
}

void TQuadroF::init_sheet(TSheet_field& s) 
{
   const int delta = _quadro == "F1" ? 3 : 0;

   TMask& m = s.sheet_mask();
   for (short id = S_CODC; id <= S_DESC; id++)
   {
     TEdit_field& e = m.efield(id+delta);
     TBrowse* browse = e.browse();
     CHECKD(browse, "Manca la ricerca sul file delle causali nel campo ", id);
     TCursor* cur = browse->cursor();
     TString16 filter; filter << "S1=" << "\"" << _quadro << "\"";
     cur->setfilter(filter);
   }                    
   
   m.set_handler(S_ALIQ + delta, aliq_handler);
   m.set_handler(S_SOGG + delta, sogg_handler);
   m.set_handler(S_ROPE + delta, rope_handler);
}

bool TQuadroF::user_create() 
{
  _codditta = get_firm_770();

  if (_quadro == "F")
  {
    _msk = new TMask("771231a");
    _msk->set_handler(D_PROVENTI, dprov_handler);
    _msk->set_handler(D_ALI,      daliq_handler);

    _msk->set_handler(mainmsk_handler);
    
    TSheet_field& p_a = (TSheet_field&) _msk->field(F_A);  
    init_sheet(p_a);
    
    TSheet_field& p_b = (TSheet_field&) _msk->field(F_B);  
    init_sheet(p_b);
    
    TSheet_field& p_c = (TSheet_field&) _msk->field(F_C);  
    init_sheet(p_c);

    _rel = new TRelation(LF_QUAF);
    for (char prosp = 'D'; prosp <= 'H'; prosp++)
    {          
       TString80 filter;
       filter.format("CODDITTA=%ld|TIPOPRO=\"%c\"|NPROG=1", 
                     _codditta, prosp); 
       const int alias = -PROSP_A + prosp - 'A';
      _rel->add(LF_RIGHEF, filter, 1, 0, alias);
      _rel->write_enable(-alias);
    }
    
    TRectype dep(LF_RIGHEF);
    dep.zero();                
    dep.put("CODDITTA", _codditta);
    dep.put("TIPOPRO", "A");
    _prosp_a = new TRecord_array(dep, "NPROG");
    dep.put("TIPOPRO", "B");
    _prosp_b = new TRecord_array(dep, "NPROG");
    dep.put("TIPOPRO", "C");
    _prosp_c = new TRecord_array(dep, "NPROG");
  }

  if (_quadro == "F1")
  {
    _msk = new TMask("771232a");
    _msk->set_handler(mainmsk_handler);
    TSheet_field& p_a = (TSheet_field&) _msk->field(F_A);
    init_sheet(p_a);

    _rel = new TRelation(LF_QUAF1);
    TString80 filter;
    filter.format("CODDITTA=%ld|NPROG=1", _codditta); 
    _rel->add(LF_RIGHEF1, filter);

    TRectype dep(LF_RIGHEF1);
    dep.zero();                
    dep.put("CODDITTA", _codditta);
    dep.put("TIPOPRO", "A");
    _prosp_a = new TRecord_array(dep, "NPROG");
  }

  if (_quadro == "F2")
  {
    _msk = new TMask("771233a");
    _msk->set_handler(mainmsk_handler);
    TSheet_field& p_a = (TSheet_field&)_msk->field(F_A);  
    init_sheet(p_a);

    _rel = new TRelation(LF_QUAF2);
    TString80 filter;
    filter.format("CODDITTA=%ld|NPROG=1", _codditta); 
    _rel->add(LF_RIGHEF2, filter);

    TRectype dep(LF_RIGHEF2);
    dep.zero();                
    dep.put("CODDITTA", _codditta);
    dep.put("TIPOPRO", "A");
    _prosp_a = new TRecord_array(dep, "NPROG");
  }

  _msk->disable(DLG_CANCEL);   // disabilito Annulla nella toolbar
  _msk->disable(DLG_NEWREC);   // disabilito Nuovo   nella toolbar
  _msk->disable(DLG_DELREC);   // disabilito Elimina nella toolbar
  _msk->disable(DLG_FINDREC);  // disabilito Ricerca nella toolbar
    
  return TRUE;                               
}

bool TQuadroF::user_destroy()
{ 
  delete _msk;
  delete _rel;
  delete _prosp_a;
  
  if (_quadro == "F")
  {
    delete _prosp_b; 
    delete _prosp_c; 
  }

  if (_registra) 
  {  
    TRiporti rip;
    rip.set(_quadro);
  }
  
  return TRUE;
}

const int PROSP_RIGHE = 16;

void TQuadroF::riempi_prospetto(const char prosp)
{
  TSheet_field& ss = (TSheet_field&)_msk->field(F_A + prosp - 'A');
  TRecord_array& prosp_x = *(prosp == 'B' ? _prosp_b : (prosp == 'C' ? _prosp_c : _prosp_a));
  const int last = prosp_x.last_row();
  int i;
  for (i = 0; i < last; i++)
  {
    TRectype& r = prosp_x.row(i+1, TRUE);
    TToken_string& row = ss.row(i);                 
    if (_quadro == "F1")
    {                           
      row.add(r.get(RQF1_TIPOA));
      row.add(r.get(RQF1_CODANAGR));
      row.add("");
    }
    row.add(r.get(QUF_CODCAUS));
    row.add(r.get(QUF_DENCAUS));
    row.add(r.get(QUF_ALIQUOTA));
    
    const real sogg = r.get_real(QUF_SOGRIT);
    const real rope = r.get_real(QUF_ROPE);
    const real somm = sogg - rope;
    row.add(sogg.string());
    row.add(rope.string());
    row.add(somm.string());
    
    ss.check_row(i);
  }
  for (i = last; i < PROSP_RIGHE; i++)
    ss.row(i);    
}

void TQuadroF::fill_ss()
{
  riempi_prospetto('A');
  if (_quadro == "F")
  {
    riempi_prospetto('B');
    riempi_prospetto('C');
  }
}

int TQuadroF::read(TMask& m)
{
  int err = TRelation_application::read(m);
  if (err == NOERR)
  {                
    _prosp_a->read(_prosp_a->key());
    if (_quadro == "F")
    {
      _prosp_b->read(_prosp_b->key());
      _prosp_c->read(_prosp_c->key());
    }
    fill_ss();
  }  
  return err;
}            

int TQuadroF::write(const TMask& m)
{
  int err = TRelation_application::write(m);
  if (err == NOERR)
    err = re_write(FALSE);   
  _registra = err == NOERR;    
  return err;
}

int TQuadroF::rewrite(const TMask& m)
{
  int err = re_write(TRUE);
  if (err == NOERR)
    err = TRelation_application::rewrite(m);
  _registra = err == NOERR;    
  return err;
}

void TQuadroF::ss_pack(TSheet_field& ss) const
{
  TString_array& rows = ss.rows_array();

  const int max = rows.items();
  for (int i = 0; i < max; i++)
  {
    TToken_string& r = (TToken_string&)rows[i];
    const int pos = _quadro == "F1" ? 4 : 1;
    const char* desc = r.get(pos);
    bool destroy = desc == NULL;
    if (!destroy)                        
    {
      const TFixed_string desccaus(desc);
      destroy = desccaus.blank();
    }
    if (destroy) 
      rows.destroy(i, FALSE);
  }
  rows.pack();
}        

int TQuadroF::salva_prospetto(char prosp, bool re)
{ 
  TRecord_array& prosp_x = *(prosp == 'B' ? _prosp_b : (prosp == 'C' ? _prosp_c : _prosp_a));
  prosp_x.destroy_rows();                      
  prosp_x.renum_key("CODDITTA", _codditta);
  
  TSheet_field& p_x = (TSheet_field&)_msk->field(F_A + prosp - 'A');
  TString_array& rows = p_x.rows_array();
  ss_pack(p_x);
  
  TString caus, desc, aliq, sogg, rope;
  
  for (int i = 0;  i < p_x.items(); i++)
  {
    TToken_string &riga = p_x.row(i);
    
    const int delta = _quadro == "F1" ? 3 : 0;
    caus = riga.get(delta);
    desc = riga.get();     
    aliq = riga.get();   
    sogg = riga.get();
    rope = riga.get();

    const int row = i + 1;
    TRectype& r = _prosp_a->row(row, TRUE);
    r.zero();                          // Probabilmente inutile
    r.put (QUF_CODDITTA, _codditta);   // Probabilmente inutile
    r.put (QUF_TIPOPRO,  prosp);       // Probabilmente inutile
    r.put (QUF_NPROG,    row);         // Probabilmente inutile

    if (app()._quadro == "F1")
    {
      r.put (RQF1_TIPOA,    riga.get(0));
      r.put (RQF1_CODANAGR, riga.get());
    }
    r.put (QUF_ALIQUOTA, aliq);
    r.put (QUF_CODCAUS,  caus);
    r.put (QUF_DENCAUS,  desc);
    r.put (QUF_SOGRIT,   sogg);
    r.put (QUF_ROPE,     rope);
  }
  return _prosp_a->write(re);  
}        

int TQuadroF::re_write(bool re)
{
  int err = salva_prospetto('A', re);  
  if (_quadro == "F")
  { 
    if (err == NOERR)
      err = salva_prospetto('B', re);  
    if (err == NOERR)
      err = salva_prospetto('C', re);  
  } 
  return err;
}

bool TQuadroF::remove()
{  
  bool ok, ok_a, ok_b, ok_c;
  ok = TRelation_application::remove();
  ok_a = _prosp_a->remove() == NOERR; 
  _prosp_a->destroy_rows();
  
  if (_quadro == "F")
  {
    ok_b = _prosp_b->remove() == NOERR;   
    _prosp_b->destroy_rows();
    ok_c = _prosp_c->remove() == NOERR;
    _prosp_c->destroy_rows();
    return _registra = ok && ok_a && ok_b && ok_c;
  }                 
  else
    return _registra = ok && ok_a;
}

bool TQuadroF::mainmsk_handler(TMask& m, KEY k)
{ 
  if (k == K_ESC)
  {
    TOperable_field& f = m.focus_field();
    m.set_focus_field(f.dlg()); 
  } 
  return TRUE;
}

bool TQuadroF::dprov_handler(TMask_field& f, KEY k)
{
  if (k == K_TAB && f.focusdirty())
  {                          
    calcola_ritenuta_operata(f.mask(), 'D');
  }
  return TRUE;
}
        
bool TQuadroF::daliq_handler(TMask_field& f, KEY k)
{
  if (k == K_TAB && f.focusdirty())
  {                         
    calcola_ritenuta_operata(f.mask(), 'D');
  }
  return TRUE;
}

bool TQuadroF::aliq_handler(TMask_field& f, KEY k)
{
  if (k == K_TAB && f.focusdirty())
  {            
    TMask& m = f.mask();
    TSheet_field* s = m.get_sheet();
    char prosp = 'A' + s->dlg() - F_A;
    calcola_ritenuta_operata(m, prosp);
  }
  return TRUE;
}

bool TQuadroF::sogg_handler(TMask_field& f, KEY k)
{
  if (k == K_TAB && f.focusdirty()) 
  {
    TMask& m = f.mask();
    TSheet_field* s = m.get_sheet();
    char prosp = 'A' + s->dlg() - F_A;
    calcola_ritenuta_operata(m, prosp);
  }
  return TRUE;
}

bool TQuadroF::rope_handler(TMask_field& f, KEY k)
{
  if (k == K_TAB && f.focusdirty())
  {              
    TMask& m = f.mask();
    const real sogg = m.get_real(f.dlg()-1);
    const real rope = m.get_real(f.dlg());
    const real somm = sogg - rope;
    m.set(f.dlg()+1, somm);
  }
  return TRUE;
}

void TQuadroF::calcola_ritenuta_operata(TMask& m, char prosp)
{   
  if (app()._msk->is_running())
  {
    int id_ali, id_sogg, id_rope, id_somm;
    
    if (prosp == 'D')
    {                 
      id_ali  = D_ALI;
      id_sogg = D_PROVENTI;
      id_rope = D_ROP;
      id_somm = 0;
    }
    else                    // A, B, C
    {
      const int delta = app()._quadro == "F1" ? 3 : 0;
      id_ali  = S_ALIQ + delta;
      id_sogg = S_SOGG + delta;
      id_rope = S_ROPE + delta;     
      id_somm = S_SOMM + delta;
    }
    
    real sogg = m.get_real(id_sogg);
    real ali  = m.get_real(id_ali);
    real rope = (sogg * ali) / 100.00;           
    rope.round();
    
    if (rope != ZERO)  // Evita di scrivere "0" nel campo (v. reqif_func nella msk)
      m.set(id_rope, rope);
    else
      m.reset(id_rope);
      
    if (id_somm)  
    {
      real somma = sogg - rope;
      m.set(id_somm, somma);
    }
  }
}


int quadroF(int argc, char* argv[])
{
  const char quadro = *argv[2];  // 0 = F, 1 = F-1, 2 = F-2, 3 = G
                                 // 4 = distinta G, 5 = G-1
  if (quadro <= '2')
  {  
    TQuadroF a(quadro);
    a.run(argc, argv, a.taitol());
  }

  if (quadro == '3')
    quadro_g(argc,argv);

  if (quadro == '4')
    distinta_quadro_g(argc,argv);

  if (quadro == '5')
    quadro_g1(argc, argv);

  return 0;
}