#include <applicat.h>
#include <automask.h>
#include <defmask.h>
#include <progind.h>
#include <recarray.h>
#include <reprint.h>

#include "celib.h"

#include "ce2101.h"
#include "ce3.h"
#include "ce3900.h"

#include "../cg/cglib01.h"

#include "ammce.h"
#include "ammmv.h"
#include "cespi.h"
#include "movam.h"
#include "movce.h"
#include "salce.h"

////////////////////////////////////////////////////////
//	MASCHERA
////////////////////////////////////////////////////////
class TStampa_sintetica_mask : public TAutomask
{
  bool _preview;

protected:
  bool on_field_event(TOperable_field& o, TField_event e, long jolly);
public:
  bool preview() const { return _preview; }
  TStampa_sintetica_mask();
};


bool TStampa_sintetica_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{ 
  bool ok = true;
  switch (o.dlg())
  {
  case F_FROM_CAT:
  case F_D_FROM_CAT:
  case F_TO_CAT:
  case F_D_TO_CAT:
    {
      TDitta_cespiti& dc = ditta_cespiti();
      ok = dc.on_category_event(o, e, jolly);
    }
    break;
	case F_ESERCIZIO:
  case F_GRUPPO:
  case F_SPECIE:
    if ((e == fe_init && o.dlg() == F_ESERCIZIO)|| e == fe_modify)
    {
      TRelation ccb("CCB");
			int err = NOERR;
      const TString& esercizio = get(F_ESERCIZIO);
			if (esercizio.full())
			{
        const TString& gruppo = get(F_GRUPPO);
        const TString& specie = get(F_SPECIE);
        TString16 key; key << esercizio << gruppo << specie;
        ccb.curr().put("CODTAB", key);
        err = ccb.read();
			}
			else
				err = ccb.last();
			if (err == NOERR)
			{
        autoload(ccb);
				o.check();
			}
    }
    break;
  case DLG_PRINT:
    if (e == fe_button)
      _preview = false;
    break;
  case DLG_PREVIEW:
    if (e == fe_button)
    {
      _preview = true;
      stop_run(K_ENTER);
    }
    break;
  default: break;
  }
  return ok;
}

TStampa_sintetica_mask::TStampa_sintetica_mask() : TAutomask("ce3900"), _preview(false)
{}

///////////////////////////////////////////////////////////////
//	RECORDSET
///////////////////////////////////////////////////////////////

class TStampa_sintetica_recordset : public TISAM_recordset
{
public:
  void set_filter(const TStampa_sintetica_mask& msk);
  TStampa_sintetica_recordset(const TString& sql) : TISAM_recordset(sql) { }
};

static const TStampa_sintetica_recordset* myself = NULL;

//metodo per caricare i valori nel recordset dalla maschera...fighissimo!!
void TStampa_sintetica_recordset::set_filter(const TStampa_sintetica_mask& msk)
{
	const TString& dacat = msk.get(F_FROM_CAT);
	const TString& acat = msk.get(F_TO_CAT);
	TString query = "USE CESPI\nSELECT ";
  query << "(ANSI(DTCOMP)<=" << msk.get_date(F_DATAFINE).date2ansi() << ")";
  //cespiti alienati esclusi?
  if (msk.get_bool(F_EXCLUDE_ALIENS))
	  query << "&&((DTALIEN='')||(ANSI(DTALIEN)>=" << msk.get_date(F_DATAINIZIO).date2ansi() << "))";

	if (dacat.full() || acat.full())
	{
		if (dacat == acat)
			query << "&&(CODCAT==" << dacat << ")";
		else
      query << "&&(BETWEEN(CODCAT," << dacat << ',' << acat << "))";
	}

	query << "\nBY CODCAT|CODIMP|CODLOC|IDCESPITE";	//query standard senza raggruppamenti
	set(query);	//setta la nuova query nel report (che avrebbe solo USE CESPI)
}

////////////////////////////////////////////////////////
//	REPORT
////////////////////////////////////////////////////////
class TStampa_sintetica_rep : public TReport
{
	int _anno;
	int _tpamm;
	int _group_codimp, _group_codloc;
	TCespite _cespite;

protected:
	real val_amm(const TRectype& rec_saldi) const;
	virtual bool get_usr_val(const TString& name, TVariant& var) const;
public:
	void set_filter(const TStampa_sintetica_mask& msk);
};

void TStampa_sintetica_rep::set_filter(const TStampa_sintetica_mask& msk)
{
  _anno = msk.get_int(F_ESERCIZIO);
	_tpamm = msk.get_int(F_SITUAZIONE);

	_group_codimp = msk.get_bool(F_GROUP_CODIMP);
	_group_codloc = msk.get_bool(F_GROUP_CODLOC);

	((TStampa_sintetica_recordset*) recordset())->set_filter(msk);
}

real TStampa_sintetica_rep::val_amm(const TRectype& rec_saldi) const
{
	real valore = rec_saldi.get_real(SALCE_CSTO);

  if (_tpamm == 1)  //solo fiscale
    valore -= rec_saldi.get_real(SALCE_VNONAMM06);

	if (_tpamm == 2)  //solo civilistico
  {
		valore -= rec_saldi.get_real(SALCE_VNONAMMC);
    valore += rec_saldi.get_real(SALCE_RIVGC);
  }
	else  //fiscale e/o gestionale
  {
		valore -= rec_saldi.get_real(SALCE_VNONAMM);
    valore += rec_saldi.get_real(SALCE_RIVGF);
  }
	
	valore += rec_saldi.get_real(SALCE_RIV75);
	valore += rec_saldi.get_real(SALCE_RIV83);
	valore += rec_saldi.get_real(SALCE_RIV90);
	valore += rec_saldi.get_real(SALCE_RIV91);

	if (valore < ZERO)
		valore = ZERO;

	return valore;
}

//metodo per il calcolo dei campi da calcolare (ma va'!) nel report
bool TStampa_sintetica_rep::get_usr_val(const TString& name, TVariant& var) const
{
	const TRecordset& recset = *recordset();
	const TString& idcespite = recset.get(CESPI_IDCESPITE).as_string();
  if (idcespite != _cespite.get(CESPI_IDCESPITE))
	{
		TCespite& c = (TCespite&)_cespite;
		c.read(idcespite);
		c.load_saldi(_tpamm, _anno);
	}

	if (name == "#DESCAT")	//categoria (descrizione della categoria corrente)
	{		
		const int gruppo = recset.get("CODCGRA").as_int();
		const TString& specie = recset.get("CODSPA").as_string();
		const int categoria = recset.get("CODCAT").as_int();
		const TRectype& rec_cac = ditta_cespiti().categoria(gruppo, specie, categoria);
		var = rec_cac.get("S0");
		return true;
	}

	if (name.starts_with("#COSTO"))	//valore dell'anno (iniziale e finale, comprese rivalutazioni e non ammortizz.)
	{
		if (name.ends_with("FIN"))  //tiposaldo finale
		{
			var = val_amm(_cespite.sal_pro());
		}
		else												//tiposaldo iniziale
		{
			var = val_amm(_cespite.sal_ini());
		}
		return true;
	}

	if (name == "#GROUP_CODIMP")
	{
		var.set(_group_codimp);
		return true;
	}

	if (name == "#GROUP_CODLOC")
	{
		var.set(_group_codloc);
		return true;
	}

	if (name == "#PERCAMM")	// percentuale ammortamento
	{
    real percamm;
    real valamm = val_amm(_cespite.sal_ini());
    if (valamm.is_zero()) // Non riesce a calcolare il valore ammortizzabile dei cespiti nuovi
    {
      const int anno_acq = _cespite.get_date(CESPI_DTCOMP).year();
      if (anno_acq == _anno)
        valamm = val_amm(_cespite.sal_pro());
    }
    if (!valamm.is_zero())
    {
      TVariant qamm, qammmv;
      get_usr_val("#QAMM", qamm);
      get_usr_val("#QAMMMV", qammmv);
      percamm = CENTO * (qamm.as_real() + qammmv.as_real()) / valamm;
      percamm.round(1);
    }  
		var = percamm;
		return true;
	}

	if (name == "#QAMMMV")	//quote ammortamento su movimento esercizio corrente
	{
		real quote_ammmv;
		const TArray& array_ammmv = _cespite.ammmv();
		for (int i = 0; i < array_ammmv.items(); i++)
		{
			const TRectype& rec_ammmv = (const TRectype&)array_ammmv[i];
			quote_ammmv += rec_ammmv.get_real(AMMMV_QNOR) + rec_ammmv.get_real(AMMMV_QACC) +
			               rec_ammmv.get_real(AMMMV_QANT) + rec_ammmv.get_real(AMMMV_QPERSE) + 
                     rec_ammmv.get_real(AMMMV_QPPRIVATE) + rec_ammmv.get_real(AMMMV_FPRIVATO);
		}
    var = quote_ammmv;
    return true;
  }
	if (name == "#QAMM")	//quote ammortamento esercizio corrente
	{
		const TRectype& rec_ammce = _cespite.amm_pro();
		var = real(rec_ammce.get_real(AMMCE_QNOR) + rec_ammce.get_real(AMMCE_QACC) + 
               rec_ammce.get_real(AMMCE_QANT) + rec_ammce.get_real(AMMCE_QPERSE) + 
               rec_ammce.get_real(AMMCE_QPPRIVATE) + rec_ammce.get_real(AMMCE_FPRIVATO));
		return true;
	}
 	if (name == "#QAMM_FPRIVATO")	//fondo ammortamento privato corrente
	{
		const TRectype& rec_ammce = _cespite.amm_pro();
		var = rec_ammce.get_real(AMMCE_FPRIVATO);
		return true;
	}
	if (name == "#FAMM")	//fondo ammortamento alla fine dell'esercizio precedente
	{
		const TRectype& rec_ammce = _cespite.amm_ini();
		real fondo = real(rec_ammce.get_real(AMMCE_QNOR) + rec_ammce.get_real(AMMCE_QACC) + 
                      rec_ammce.get_real(AMMCE_QANT) + rec_ammce.get_real(AMMCE_QPERSE) + 
                      rec_ammce.get_real(AMMCE_QPPRIVATE) + rec_ammce.get_real(AMMCE_FPRIVATO));
    var = fondo;
		return true;
	}
 	if (name == "#FAMM_FPRIVATO")	//fondo ammortamento alla fine dell'esercizio precedente
	{
		const TRectype& rec_ammce = _cespite.amm_ini();
		var = rec_ammce.get_real(AMMCE_FPRIVATO);
		return true;
	}
	if (name == "#CESSELIM")	//cessioni elminiazioni
	{
		real cesselim;
		const TArray& array_movam = _cespite.movam();
		for (int i = 0; i < array_movam.items(); i++)
		{
			const TRectype& rec_movam = (const TRectype&)array_movam[i];
			cesselim += rec_movam.get_real(MOVAM_QNOR) + rec_movam.get_real(MOVAM_QACC) + 
                  rec_movam.get_real(MOVAM_QANT) + rec_movam.get_real(MOVAM_QPERSE) + 
                  rec_movam.get_real(MOVAM_QPPRIVATE) + rec_movam.get_real(MOVAM_FPRIVATO);
		}
    var = cesselim;
		return true;
	}
	if (name == "#RESAMM")	//residuo da ammortizzare
	{
		var = _cespite.res_amm();
		return true;
	}
	if (name == "#SITUAZIONE")	//tipo situazione da stampare in testata
	{
		var.set(_tpamm);
		return true;
	}
  if (name == "#ANNO")
  {
    var.set(_anno);
    return true;
  }

	return TReport::get_usr_val(name, var);
}

////////////////////////////////////////////////////////
//	APPLICAZIONE
////////////////////////////////////////////////////////
class TStampa_sintetica : public TSkeleton_application
{
protected:
  virtual void main_loop();
};


void TStampa_sintetica::main_loop()
{
	TStampa_sintetica_mask mask;
  while (mask.run() == K_ENTER)
  {
		//report e book dei report
		TReport_book book;
		TStampa_sintetica_rep rep;
		rep.load("ce3900a");

		rep.set_filter(mask);
		book.add(rep);

    //stampa il book dei report
    if (mask.preview())
      book.preview();
    else
		  book.print();	
	}
}

int ce3900(int argc, char* argv[])
{
  TStampa_sintetica a;
  a.run(argc, argv, TR("Registro cespiti sintetico"));
  return 0;
}