// 77g1.cpp - Quadro G1
#include <defmask.h>
#include <msksheet.h>
#include <relapp.h>
#include <recarray.h>

#include "quadrog1.h"
#include "774200.h"
#include "77g1a.h"   
#include "77lib.h"

class TQuadroG1 : public TRelation_application
{
  private:
    TRelation*    _rel;
    TMask*        _msk;
    long          _codditta;
    TString16     _quadro;
    TString80     _title;
    bool          _registra;

    static bool   prosp_notify(TSheet_field& s, int r, KEY k);
    static bool   mainmsk_handler(TMask& m, KEY k);        
    static bool   aliquota_handler(TMask_field& f, KEY k);

  protected:
    virtual bool  user_create();
    virtual bool  user_destroy();
    virtual int   rewrite(const TMask& m);
    virtual int   read(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&);    
    void      fill_arr(TMask& m);    
    void      arr2rel(const TMask& m);                  
  public:                      
    const char*   taitol() { return (const char*)_title; }
    TMask&      main_mask() const { return (TMask&) *_msk; }
        
    TQuadroG1();
    virtual ~TQuadroG1() {};
};                    

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

TQuadroG1::TQuadroG1()
{
  _registra   = FALSE;
  _quadro = "G1";  
  _title  = "Quadro G1";
}

bool TQuadroG1::aliquota_handler(TMask_field& f, KEY k)
{ 
  bool ok = TRUE;  
  if (k == K_TAB && f.focusdirty())
  {                       
    TMask& m = f.mask();
    for (short id = 101; id <= 102; id++)
    {
      TEdit_field& utili = m.efield(id);
      utili.set_dirty();
      utili.on_hit();
    }  
  }
  if (k == K_ENTER)
  {
    TMask& m = f.mask();
    
    TSheet_field& s = *m.get_sheet();
    const int selected = s.selected();
    TToken_string& row = s.row(selected);
    
    if (selected > 2 && !row.empty_items())
    {
      const real aliquota = f.get();
      for (int i = 0; i < s.items(); i++) if (i != selected)
      { 
        const real aliq = s.row(i).get(2);
        if (aliquota == aliq)
        {
          ok = f.yesno_box("L'aliquota %s%% e' gia' stata utilizzata al rigo %d.\n"
                           "Si desidera sommare gli importi nello stesso rigo?", 
                           (const char*)aliq.string(".2"), i+1);
          if (ok)
          { 
            // Forza aggiornamento riga corrente dello sheet con la maschera
            row.cut(0);                        
            for (short id = 101; id <= 107; id++)
              row.add(m.get(id));
            
            // Sceglie come destinazione la riga piu' in alto
            int src = selected, dst = i;
            if (src < dst)
            { int tmp = src; src = dst; dst = tmp; }
            
            // Righe conivolte nella somma  
            TToken_string& srcrow = s.row(src);
            TToken_string& dstrow = s.row(dst);
              
            for (int x = 0; x < 7; x++) if (x < 2 || x > 4)
            {
              real tot = dstrow.get(x);
              if (x < 2 || dst != 2)
              {
                tot += real(srcrow.get(x)); 
                dstrow.add(tot.string(), x);
              }
              if (dst == selected)
                m.set(101+x, tot);
              else
                m.reset(101+x);
            }
            if (src == selected)
            {
              m.reset(103);
              s.force_update(dst);
            }  
            else
            {
              srcrow.cut(0); 
              s.force_update(src);
            }  
          }
          break;
        }
      }
    }  
  }
  return ok;
}


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

int TQuadroG1::read(TMask& m)
{
  int err = TRelation_application::read(m);
  if (err == NOERR)
    fill_arr(m);
  return err;
}

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

bool TQuadroG1::user_create() 
{
  _msk = new TMask("77g1a");
  _rel = new TRelation(LF_QUAG1);
  
  _codditta = get_firm_770();

  _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

  _msk->set_handler(mainmsk_handler);
  TSheet_field& prosp = (TSheet_field&)_msk->field(F_PI);  
  prosp.set_notify(prosp_notify);                          
  
  TMask& sm = prosp.sheet_mask();
  sm.set_handler(103, aliquota_handler);
  
  return TRUE;
}

bool TQuadroG1::user_destroy() 
{
  delete _rel; 
  delete _msk;
  if (_registra)
  { 
    TRiporti rip;
    rip.set(_quadro);  
  }
  return TRUE;
}                           

void TQuadroG1::arr2rel(const TMask& m)
{
  TRecord_array arr(LF_QUAG1, "NPROG");
  arr.renum_key("CODDITTA", _codditta);
  
  int last_saved = 0;
  TSheet_field& ss = (TSheet_field&)m.field(F_PI);
  
  for (int i = 0; i < ss.items(); i++)
  {                      
    TToken_string& row  = ss.row(i);
    real tot;
    const real utili1s  = row.get(0); tot +=  utili1s;
    const real utili2s  = row.get();  tot +=  utili2s;
    const real aliquota = row.get();
    const real racc1s   = row.get();  tot +=  racc1s;
    const real racc2s   = row.get();  tot +=  racc2s;
    const real rimp1s   = row.get();  tot +=  rimp1s;
    const real rimp2s   = row.get();  tot +=  rimp2s;
    if (i == 0 || tot > 0.0)
    { 
      if (i < 3)
        last_saved = i;
      else               
      {
        if (last_saved < 3)
          last_saved = 3;
      }    
      last_saved++;
      
      TRectype& rec = arr.row(last_saved, TRUE);
      rec.put(QG1_UTILI1S,   utili1s);
      rec.put(QG1_UTILI2S,   utili2s);
      rec.put(QG1_ALIQUOTA,  aliquota);
      rec.put(QG1_RACCVER1S, racc1s);
      rec.put(QG1_RACCVER2S, racc2s);
      rec.put(QG1_RIMPVER1S, rimp1s);
      rec.put(QG1_RIMPVER2S, rimp2s);
    }
  }
  arr.rewrite();
}

void TQuadroG1::fill_arr(TMask& m)
{                                      
  TRecord_array arr(LF_QUAG1, "NPROG");
  arr.renum_key("CODDITTA", _codditta);
  arr.read(arr.key());
  
  int last = arr.last_row();
  if (last < 16)
    last = 16;
  
  TSheet_field& ss = (TSheet_field&)m.field(F_PI);
  ss.destroy();
  for (int i = 0; i < last; i++)
  {  
    TToken_string& row = ss.row(i);
    if (arr.exist(i+1))
    {  
       const TRectype& r = arr.row(i+1);
       row.add(r.get("UTILI1S"),   0);
       row.add(r.get("UTILI2S"),   1);
       if (i > 2)
         row.add(r.get("ALIQUOTA"),  2);
       if (i == 0)  
       {
         row.add(r.get("RACCVER1S"), 3);
         row.add(r.get("RACCVER2S"), 4);
       }
       if (i != 2)
       {
         row.add(r.get("RIMPVER1S"), 5);
         row.add(r.get("RIMPVER2S"), 6);
       }  
    }
    
    if (i < 3)
    {
      const char* const ali = i == 0 ? "10.00" : (i == 1 ? "12.50" : "");
      row.add(ali, 2);
      ss.disable_cell(i, 2);
      if (i == 2)
      {
        ss.disable_cell(i, 5); 
        ss.disable_cell(i, 6);
      }
    }
    if (i > 0)
    {
      ss.disable_cell(i, 3); 
      ss.disable_cell(i, 4);
    } 
  }
}

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

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

bool TQuadroG1::remove()
{  
  _registra = TRelation_application::remove();
  return _registra;
}

bool TQuadroG1::prosp_notify(TSheet_field& s, int r, KEY k)
{
  bool ok = TRUE;
  switch(k)
  {                               
    case K_CTRL+K_INS:
      s.disable_cell(r, 3);
      s.disable_cell(r, 4);
      break;
    case K_DEL: 
      ok = r > 2;
      break;
    default:
      break;
  }
  return ok;
}
 
bool TQuadroG1::mainmsk_handler(TMask& m, KEY k)
{ 
  if (k == K_ESC)
  {
    TOperable_field& f = m.focus_field();
    m.set_focus_field(f.dlg()); 
  } 
  return TRUE;
} 

///////////////////////////////////////////////////////////
// Funzione chiamata dal main
///////////////////////////////////////////////////////////

bool quadro_g1(int argc, char* argv[])
{
  TQuadroG1 a;
  a.run(argc, argv, a.taitol());
  return TRUE;
}