#include <applicat.h>
#include <automask.h>
#include <execp.h>
#include <progind.h>
#include <recarray.h>

#include <rcausali.h>
#include <clifo.h>
#include <mov.h>
#include <rmov.h>

#include "ps0713lib.h"

#include "../ca/calib01.h"
#include "../ca/calib02.h"
#include "../ca/movana.h"
#include "../ca/rmovana.h"

#include "ps0713500a.h"


                                //////////////////////////////////
                                ////    TIMPORTA_SPESE_MSK    ////
                                //////////////////////////////////

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

public:
  TImporta_spese_msk(const char* name);
};
  
TImporta_spese_msk::TImporta_spese_msk(const char* name) 
                   :TAutomask (name) {}  

//ON_FIELD_EVENT: metodo che gestisce i comportamenti dei vari campi della maschera
//(per adesso segnaposto)
bool TImporta_spese_msk::on_field_event(TOperable_field& f, TField_event e, long jolly)
{
  return true;
}

                                //////////////////////////////////
                                ////    TIMPORTA_SPESE_APP    ////
                                //////////////////////////////////

//Classe TImporta_spese_app
class TImporta_spese_app : public TSkeleton_application
{
  TImporta_spese_msk*  _msk;
protected:
  virtual bool check_autorization() const {return false;}
  virtual const char * extra_modules() const {return "ve";}

  void chiudi_movimento(TConfig& configfile, TImporto& tot_doc, TDate& data, const long numreg, TAssoc_array& righean);

public:           
  virtual void main_loop();
  long genera_movcg(const TDate& datareg);
  void genera_movana(const long numreg, const TDate& datareg, TAssoc_array& righean);
	bool transfer();
 
  TImporta_spese_app() {};
};

const char* const nomeini = "ps0713500ats.ini";

void TImporta_spese_app::chiudi_movimento(TConfig& configfile, TImporto& tot_doc, TDate& data, const long numreg, TAssoc_array& righean)
{
  genera_movana(numreg, data, righean);
  //aggiungo i campi che mancano in testata
  configfile.set_paragraph("23");
  configfile.set(MOV_DATAREG, data);
  configfile.set(MOV_DATADOC, data);
  configfile.set(MOV_DATACOMP, data);

	tot_doc.normalize();

  //aggiungo la prima riga che bilancia le righe successive
	TString8 paragraph;
  paragraph.format("%d,%d",LF_RMOV,1);
	configfile.set_paragraph(paragraph);  
	configfile.set(RMV_IMPORTO,tot_doc.valore().string());
  TString4 strsez; strsez << tot_doc.sezione();
  configfile.set(RMV_SEZIONE, strsez);

  configfile.set_paragraph("Transaction");
  
  TString app;
  app << "cg2 -0 -i" << nomeini; 
  TExternal_app primanota(app);
  primanota.run();
}

long TImporta_spese_app::genera_movcg(const TDate& datareg)
{
  TISAM_recordset movrec("USE MOV");
  movrec.move_last();
  long numreg = movrec.get(MOV_NUMREG).as_int(); numreg++;

  TLocalisamfile mov(LF_MOV);
  mov.put(MOV_NUMREG,   numreg);
  mov.put(MOV_DATACOMP, datareg);
  mov.put(MOV_DATAREG,  datareg);
  mov.put(MOV_CODCAUS,  _msk->get(F_CODCAU));
  mov.write();

  return numreg;
}

void TImporta_spese_app::genera_movana(const long numreg, const TDate& datareg, TAssoc_array& righean)
{
  TProgind pi(righean.items(), "Importazione analitica in corso...", true, true);

  const int   anno = datareg.year();

  TToken_string key;
  key.add(_msk->get(F_CODCAU));
  key.add(1);
  key.add(1);
  const TRectype& causale = cache().get(LF_RCAUSALI, key);
  key.add(2, 1);
  const TRectype& causale1 = cache().get(LF_RCAUSALI, key);

  //instanzio il movimento di analitica
  TAnal_mov anmo(0);
  anmo.put(MOVANA_NUMREGCG, numreg);
  anmo.put(MOVANA_DATACOMP, datareg);  
  anmo.put(MOVANA_DATAREG,  datareg);
  anmo.put(MOVANA_CODCAUS,  _msk->get(F_CODCAU));
  anmo.put(MOVANA_ANNOES,   anno);

  real totdoc = ZERO;

  //per ogni oggetto dell'assoc_array, creo una riga di analitica
  FOR_EACH_ASSOC_OBJECT(righean, obj, keyar, itm)
  {
    if (!pi.addstatus(1)) 
		  break;

    TCommessa_string& row = (TCommessa_string)keyar;
    const TString& idlav  = row.idlavoro();
    const int      gruppo = row.gruppo();   TString8  grup; grup.format("%03d",  gruppo);
    const int      conto  = row.conto();    TString8  cont; cont.format("%03d",  conto);
    const int      sotco  = row.sotco();    TString16 sotc; sotc.format("%06ld", sotco);
    TString80 codconto; codconto << grup << cont << sotc;

    real& imp = *(real*)itm;  imp.round(2);
    totdoc += imp;
		
		if (!imp.is_zero())
		{
      TImporto importo('D', imp);
	    importo.normalize();

      TRectype& ranmo = anmo.new_row();
      ranmo.put(RMOVANA_ANNOES,   anno);
      ranmo.put(RMOVANA_SEZIONE,  causale1.get("SEZIONE"));
      ranmo.put(RMOVANA_CODCONTO, codconto);
      ranmo.put(RMOVANA_CODCMS,   idlav);
      ranmo.put(RMOVANA_IMPORTO,  importo.valore().string());
      ranmo.put(RMOVANA_SEZIONE,  importo.sezione());
    }
  }

  TImporto totale('D', totdoc);
  anmo.put(MOVANA_TOTDOC,  totale.valore().string());
  anmo.put(MOVANA_SEZIONE, totale.sezione());

  TLocalisamfile fmov(LF_MOVANA);
  anmo.write(fmov);
}

bool TImporta_spese_app::transfer()
{
  //genero il nome del file da caricare
  TFilename name = _msk->get(F_PATH);
  name.add(_msk->get(F_NAME));
  TVB_recset s(name, ',');

  TProgind pi(s.items(),"Importazione spese in corso ...",true,true);

  xvt_fsys_remove_file(nomeini);
  TConfig configfile (nomeini, "Transaction");  //setto il paragrafo [Transaction] del file ini
  const TConfig conf(nomeini, "Transaction");

  TDate dataold, data;

  int nriga = 2;
  TImporto tot_doc;
  TAssoc_array righean;
  long numreg;

  const TRectype& causale = cache().get(LF_CAUSALI, _msk->get(F_CODCAU));
  const bool isana = causale.get_bool("MOVIND");

  for (bool ok = s.move_first(); ok; ok = s.move_next())
  {
    if (!pi.addstatus(1)) 
      break;
    
    TString80 tmp;

    //importo
	  tmp = s.get(2).as_string();

    //evito di analizzare eventuali righe vuote
    if (tmp.blank())
      continue;

    tmp.replace(',','.');
    tmp.strip("\"");
    const real imp = tmp;

    if (!imp.is_zero())
    {
      
      //codice commessa
	    tmp = s.get(0).as_string();
      tmp.strip("\"");
      const TString80 codcms = tmp;
      const TCommessa cms(codcms);

	    //data
	    tmp = s.get(1).as_string();
      tmp.strip("\"");
	    
	    data.set_day(atoi(tmp.mid(0,2)));
	    data.set_month(atoi(tmp.mid(3,2)));
	    data.set_year(atoi(tmp.mid(6,4)));
      
      //descrizione
      tmp = s.get(3).as_string();    
      tmp.strip("\"");

	    if(data != dataold)
		  {
        if (dataold.ok())
          chiudi_movimento(configfile, tot_doc, dataold, numreg, righean);

        numreg = genera_movcg(data);
        TLocalisamfile mov(LF_MOV);
        mov.put(MOV_NUMREG,   numreg);
        mov.remove();

				TFilename filename(nomeini);
				filename.fremove();

        configfile = conf;
        configfile.set_paragraph("Transaction");
        configfile.set("Action","INSERT");
        configfile.set("Mode","AUTO");
        
        configfile.set_paragraph("23"); //setto il paragrafo [23] del file ini (testata)
        configfile.set(MOV_NUMREG, numreg);
        configfile.set(MOV_CODCAUS, _msk->get(F_CODCAU));
  
        configfile.set_paragraph("24,1");
        configfile.set(RMV_NUMRIG,1);
 
        righean.destroy();
        tot_doc.reset();
        nriga = 2;
        dataold = data;
      }

	    TImporto importo('D', imp);
	    importo.normalize();
      tot_doc -= importo;
		  
	    TString8 paragraph;
      paragraph.format("%d,%d", LF_RMOV, nriga++);
      configfile.set_paragraph(paragraph);

      configfile.set(RMV_IMPORTO, importo.valore().string());

      TString4 strsez;  strsez << importo.sezione();
      configfile.set(RMV_SEZIONE, strsez);
      configfile.set(RMV_DATAREG, data);
      
      TCommessa_string ankey(cms.cmsstr());
      const int gruppo = ankey.gruppo();
      const int conto  = ankey.conto();
      const int sotco  = ankey.sotco();

      TToken_string key;
      key.add(gruppo);
      key.add(conto);
      key.add(sotco);
      const TRectype& pcon = cache().get(LF_PCON, key);

      configfile.set(RMV_GRUPPO,     gruppo);
      configfile.set(RMV_CONTO,      conto);
      configfile.set(RMV_SOTTOCONTO, sotco);

      //se il conto � analitico, allora prepara il movimento di analitica
      if(isana && pcon.get_bool("ANALITICA"))
      {
        if(righean.is_key(ankey))
        {
          real& imponibile = *(real*)righean.objptr(ankey);
          imponibile += importo.valore();
        }
        else
          righean.add(ankey, importo.valore());
      }
    }
  }
  chiudi_movimento(configfile, tot_doc, dataold, numreg, righean);
    
  return true;
}


void TImporta_spese_app::main_loop()
{
  _msk = new TImporta_spese_msk("ps0713500a");
	
  if (_msk->run() == K_ENTER)
  {		
		if (transfer())
		{
      message_box(TR("Importazione spese completata"));
      xvt_fsys_remove_file(nomeini);
		}
  }   
}


TImporta_spese_app& app() { return (TImporta_spese_app&) main_app(); }


int ps0713500 (int argc, char* argv[])
{
  TImporta_spese_app main_app;
  main_app.run(argc, argv, TR("Importazione Spese"));
  return true;
}