#include <applicat.h>
#include <automask.h>
#include <progind.h>
#include <relation.h>
#include <viswin.h>

#include "ceeur.h"
#include "ceeur20.h"

#include "ammce.h"
#include "cespi.h"
#include "salce.h"

class TEuro02_app : public TEuro_app
{
protected:
  virtual void main_loop();
  
public:  
  real valore_ammortizzabile(const TRelation& rel, int tipo_sit) const;
  real fondo(const TRelation& rel, int tipo_sit) const;
  real confronta_valori(const real& val_lit, const real& val_eur) const;
  void print_arr(int tipo_sit) const;
};

///////////////////////////////////////////////////////////
// Maschera di selezione
///////////////////////////////////////////////////////////

class TEuro02_mask : public TAutomask
{
protected:
  virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);

public:
  TEuro02_mask() : TAutomask("ceeur20") { }
};

bool TEuro02_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
  switch (o.dlg())
  {
  case F_DITTA:
    if (e == fe_close)
    {
      const long ditta = atol(o.get());
      main_app().set_firm(ditta);
    }
    break;
  default: break;
  }
  return TRUE;
}

///////////////////////////////////////////////////////////
// Applicazione principale
///////////////////////////////////////////////////////////

real TEuro02_app::confronta_valori(const real& val_lit, const real& val_eur) const
{
  real expected_val_eur = val_lit / EURO; expected_val_eur.round(2);
  real error = expected_val_eur - val_eur;
  return error;
}

real TEuro02_app::valore_ammortizzabile(const TRelation& rel, int tipo_sit) const
{
  const TRectype& salpro = rel.curr();
  real val = salpro.get_real(SALCE_CSTO) - salpro.get_real(SALCE_PLUSREIN) +
             salpro.get_real(SALCE_RIV75) + salpro.get_real(SALCE_RIV83);
    
  if (tipo_sit == 1)
  {
    val -= salpro.get_real(SALCE_VNONAMM);
    val += salpro.get_real(SALCE_RIVGF);
  } 
  if (tipo_sit == 2)
  {
    val += salpro.get_real(SALCE_RIVGC);
  }
    
  const real riv90 = salpro.get(SALCE_RIV90);
  const real riv91 = salpro.get(SALCE_RIV91);
  if (riv90 != ZERO || riv91 != ZERO)
  {
    const int annipost90 = salpro.get_int(SALCE_ANNIPOST90);
    if (riv91 != ZERO || annipost90 >= 3)
      val += riv90;
  }
  val += riv91;

  return val;
}

real TEuro02_app::fondo(const TRelation& rel, int tipo_sit) const
{          
  const TString16 idcesp = rel.curr().get(SALCE_IDCESPITE);
  const TRectype& ammpro = rel.curr(LF_AMMCE);
  
  real fondo;                                    // Fondo ammortamento
  if (ammpro.get(AMMCE_IDCESPITE) == idcesp)
  {
    if (ammpro.get_int(AMMCE_TPAMM) == tipo_sit)
    {
      fondo += ammpro.get_real(AMMCE_QNORP);
      fondo += ammpro.get_real(AMMCE_QANTP);
      fondo += ammpro.get_real(AMMCE_QACCP);
      fondo += ammpro.get_real(AMMCE_QPERSEP);
      fondo += ammpro.get_real(AMMCE_QPPRIVATEP);
      fondo += ammpro.get_real(AMMCE_FPRIVATOP);

      fondo += ammpro.get_real(AMMCE_QNOR);
      fondo += ammpro.get_real(AMMCE_QANT);
      fondo += ammpro.get_real(AMMCE_QACC);
      fondo += ammpro.get_real(AMMCE_QPERSE);
      fondo += ammpro.get_real(AMMCE_QPPRIVATE);
      fondo += ammpro.get_real(AMMCE_FPRIVATO);
    }
  }  
  else
  {
    fondo = ZERO;
  }
  return fondo;
}

void TEuro02_app::print_arr(int tipo_sit) const
{
  TViswin vw(NULL, TR("Controllo arrotondamenti"), FALSE, TRUE, FALSE, 0, 0, 0, 0, FALSE);
  vw.maximize();
  vw.open_modal();
  
  TString expr;
  expr << "CODES==CODES|IDCESPITE==IDCESPITE|TPSALDO==2|TPAMM==" << tipo_sit;
  
  TRelation rel_lit(LF_SALCE);
  rel_lit.add(LF_AMMCE, expr);
  
  TEuroisamfile* salce_eur = new TEuroisamfile(LF_SALCE, TRUE);
  TEuroisamfile* ammce_eur = new TEuroisamfile(LF_AMMCE, TRUE);
  
  TRelation rel_eur(salce_eur);
  rel_eur.add(LF_AMMCE, expr);
  rel_eur.replacef(ammce_eur, LF_AMMCE, expr);
  rel_eur.add(LF_CESPI, "IDCESPITE==IDCESPITE");
  
  TCursor cur_eur(&rel_eur, "(CODES==2001)&&(TPSALDO==2)");
  const long items = cur_eur.items();
  cur_eur.freeze();
  
  const TRectype& salce = cur_eur.curr();
  const TRectype& cespi = cur_eur.curr(LF_CESPI);
  
  for (cur_eur = 0L; cur_eur.pos() < items; ++cur_eur)
  {
    rel_lit.curr() = cur_eur.curr();
    if (rel_lit.read() == NOERR)
    {
      const TString16 idcespite = salce.get(SALCE_IDCESPITE);
  
      const real val_amm_lit = valore_ammortizzabile(rel_lit, tipo_sit);
      const real val_amm_eur = valore_ammortizzabile(rel_eur, tipo_sit);
        
      const real fondo_lit = fondo(rel_lit, tipo_sit);
      const real fondo_eur = fondo(rel_eur, tipo_sit);
        
      const real residuo_lit = val_amm_lit - fondo_lit;
      const real residuo_eur = val_amm_eur - fondo_eur;
        
      const real err = confronta_valori(residuo_lit, residuo_eur);
      if (err <= -0.01 || err >= 0.01)
      {
        TString str;
        str << TR("Cespite ") << idcespite << " - " << cespi.get(CESPI_DESC);
        str << TR(" - Situazione ");
        switch (tipo_sit)
        {
        case  2: str << TR("Civilistica"); break;
        case  3: str << TR("Gestionale"); break;
        default: str << TR("Fiscale"); break;
        }
        vw.add_line(str); str.cut(0);
  
        str << TR("Residuo in Lire ") << residuo_lit.string(".");
        str << TR(" - Residuo in Euro ") << residuo_eur.string(".2");
        vw.add_line(str); str.cut(0);
  
        str << TR("Errore di arrotondamento in Euro ") << err.string(".2");
        vw.add_line(str); str.cut(0);
            
        vw.add_line(str);
      }
    }
  }
  
  vw.close_print();
  vw.run();
  vw.close_modal();
}

void TEuro02_app::main_loop()
{
  goto_lire();
  TEuro02_mask m;
  while (m.run() == K_ENTER)
  {
    const int tipo_sit = m.get_int(F_TIPO);
    print_arr(tipo_sit);
  }
}

int ceeur02(int argc, char* argv[])
{  
  TEuro02_app aa;
  aa.run(argc, argv, TR("Controllo arrotondamenti"));
  
  return 0;
}