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

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


#include "pi0001.h"
#include "pi0001100.h"
#include "pi0001100a.h"
#include "pi0001200.h"

#include <pconti.h>
#include <mov.h>
#include <rmov.h>
#include <rmoviva.h>

	#define AT01CM   0 // Record attivo/sospeso/annullato                       DIZSMAS    - ATTI
	#define DT01CM   1 // Data stampa per G.Gen.le                              DIZSMAS    - DATS
	#define NR01CM   2 // Numero azione di aggiornamento                        DIZSMAS    - NRAZ
	#define TPMVCM   3 // Flag IVA I=IVA   =no IVA                              DIZSMAS    - TPMV
	#define CDDTCM   4 // Codice Ditta                                          DIZSMAS    - CDDT
	#define AAPRCM   5 // Anno Operazione                                       DIZSMAS    - AAPR
	#define ANNPCM   6 // Anno Reg.DA GESTIRE                                   DIZSMAS    - ANNP
	#define TPGICM	 7 // Giornale IVA  TB=GI                                   DIZSMAS    - TPGI
	#define DTOPCM	 8 // Data operazione                                       DIZSMAS    - DATS
	#define NONPCM	 9 // Nr. Operaz./Nr. Prot.                                 DIZSMAS    - NONP
	#define NRRGCM	10 // Numero Riga 2                                         DIZSMAS    - NRR2
	#define NRGICM	11 // Nr Riga Giornale                                      DIZSMAS    - NRGI
	#define CONTCM	12 // Gr. Conto Sottoconto                                  DIZSMAS    - CONT
	#define DIVICM	13 // Divisione  TB=DI                                      DIZSMAS    - DIVI
	#define NPARCM	14 // Nr Partita                                            DIZSMAS    - NPAR
	#define AAOPCM	15 // Anno partita                                          DIZSMAS    - ANNO
	#define DTRGCM	16 // Data registrazione                                    DIZSMAS    - DATS
	#define CAUSCM	17 // Causale  TB=CA                                        DIZSMAS    - CAUS
	#define DSUPCM	18 // Descrizione Supplementare                             DIZSMAS    - DSUP
	#define IMPOCM	19 // Importo  "-"=Avere                                    DIZSMAS    - IMPO
	#define CDVACM	20 // Codice Valuta  TB=VA                                  DIZSMAS    - CDVA
	#define CAMBCM	21 // Cambio                                                DIZSMAS    - CAMB
	#define IMVACM	22 // Importo Valuta                                        DIZSMAS    - IMVA
	#define CDPGCM	23 // Codice di Pagamento TB=CP                             DIZSMAS    - CDPG
	#define DT1SCM	24 // Data I^ scadenza                                      DIZSMAS    - DATS
	#define DTDOCM	25 // Data documento                                        DIZSMAS    - DATS
	#define NRDOCM	26 // N� Documento                                          DIZSMAS    - NUDO
	#define CCTPCM	27 // Centri Costo Tipico TB=CC                             DIZSMAS    - CCTP
	#define NCOMCM	28 // Numero Commessa                                       DIZSMAS    - NCOM
	#define CDSCCM	29 // Codice Sottocommessa                                  DIZSMAS    - CDSC
	#define INDECM	30 // Indetraibilit� %                                      DIZSMAS    - INDE
	#define CDIVCM	31 // Codice IVA                                            DIZSMAS    - CDIV
	#define IMPSCM	32 // Imposta                                               DIZSMAS    - IMPS
	#define CDAGCM	33 // Codice Agente                                         DIZSMAS    - CDAG
	#define DTVBCM	34 // Data Liquidazione Iva Sospesa                         DIZSMAS    - DATS
	#define FLSBCM	35 // Flag *=Stampato Bollato                               DIZSMAS    - FLSB
	#define FSBICM	36 // Flag *=Stampato Boll.IVA                              DIZSMAS    - FSBI
	#define FLVZCM	37 // V=Var.S=Storno P=Liq.prec. E=Esig.Sosp.               DIZSMAS    - FLVZ
	#define FLIICM	38 // Flag IVA Irrecup. " "=I irr.                          DIZSMAS    - FLII
	#define FLTSCM	39 // Flag Tipo Sollecito                                   DIZSMAS    - FLTS
	#define FLEPCM	40 // *=Est.EP Non � pi� usato                              DIZSMAS    - FLEP
	#define DPERCM	41 // Dati Personalizzabili                                 DIZSMAS    - DPER
	#define CONSCM	42 // Gr.Co.Sottoc.Sostitutivo                              DIZSMAS    - CONS
	#define DTSTCM	43 // Nr.progr. rateo/risconto                                         -
	#define USERCM	44 // Utente                                                DIZSMAS    - NOMU
	#define DTUMCM	45 // Data ultima manutenzione                              DIZSMAS    - DATS
	#define TPUMCM	46 // Tipo ultima manutenzione                              DIZSMAS    - FLAG
	#define FL01CM	47 // Flag Generico                                         DIZSMAS    - FLAG
	#define FL02CM	48 // Flag Generico                                         DIZSMAS    - FLAG
	#define FL03CM	49 // Flag Generico                                         DIZSMAS    - FLAG
	#define FL04CM	50 // Flag Generico                                         DIZSMAS    - FLAG
	#define FL05CM	51 // Flag Generico                                         DIZSMAS    - FLAG
	#define CMBECM	52 // Cambio EURO                                           DIZSMAS    - CAME
	#define IMVACM2	53 // Importo Val 2                                         DIZSMAS    - IMPO
	#define IMPSCM2	54 // Imposta 2                                             DIZSMAS    - IMPS

const TVariant& TImporta_galileo_recset::get(unsigned int column) const
{
	TString str = TCSV_recordset::get(column).as_string();
  TVariant& var = get_tmp_var();
	int len = str.len();
			
	if (len == 0)
		return NULL_VARIANT;
	if (str[len -1] == '"')
		str.rtrim(1);
	if (str[0] == '"')
		str.ltrim(1);
	var.set(str);
	return var;
}
///////////////////////////////////////////////////////////
// TAutomask
///////////////////////////////////////////////////////////

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

public:
  TImporta_mov_mask();
};
  
TImporta_mov_mask::TImporta_mov_mask() :TAutomask ("pi0001100a")
{
}  

bool TImporta_mov_mask::on_field_event(TOperable_field& f, TField_event e, long jolly)
{ 
	switch (f.dlg())
	{
	//giochetto per avere la lista dei files validi nella directory di trasferimento!
	case F_NAME:
		if (e == fe_button)
		{
			TArray_sheet as(-1, -1, 72, 20, TR("Selezione file"), "File@32");
			TFilename path = get(F_PATH);	path.add("*.txt");	//files delle testate
			list_files(path, as.rows_array());
			TFilename name;
			FOR_EACH_ARRAY_ROW(as.rows_array(), i, row)
			{
				name = *row;
				*row = name.name();
			}
			if (as.run() == K_ENTER)
				f.set(as.row(as.selected()));
		}
		break;
	default:
		break;
	}
  return true;
}


///////////////////////////////////////
// TSkeleton_application
///////////////////////////////////////
class TImporta_mov : public TSkeleton_application
{
protected:
  virtual const char* extra_modules() const { return "cg"; }
	void build_IVA(TConfig & conf, TArray & rows, TString_array & concg, TArray & impcg, int nrigai);

public:           
  virtual void main_loop();
	void transfer(const TMask& msk);
};

void TImporta_mov::build_IVA(TConfig& conf, TArray& rows, TString_array& concg, TArray& impcg, int nrigai)
{
	const int items = rows.items();
  if (items > 0)
	{
   	TString paragraph;
  	TToken_string key;

    int icg = 0;
		
    TString4 gruppo, conto;
    TString8 sottoconto;

    if (icg < concg.items())
    {
      const TString& gcs = concg.row(icg);
		  gruppo     = gcs.left(2);
		  conto      = gcs.mid(2, 2);
		  sottoconto = gcs.right(6);
    }
    else
    {
      // Non so come inventare il conto
    }
   
    real imptot;
    if (icg < impcg.items())
      imptot = (const real&)impcg[icg];

		int i = 0;
		while (i < items)
		{
			TRectype& rec = (TRectype&)rows[i];
			real imp = rec.get(RMI_IMPONIBILE);
			real iva = rec.get(RMI_IMPOSTA);
			if (imp <= imptot)
				i++;
			else
			{
				const TCodiceIVA codiva(rec.get(RMI_CODIVA));
				
				imp -= imptot;
				rec.put(RMI_IMPONIBILE, imp);
				imp = imptot;
				real iv = codiva.imposta(imptot);
				iva -= iv;
				rec.put(RMI_IMPOSTA, iva);
				iva = iv;
			}
			imptot -= imp;
			paragraph.format("%d,%d",LF_RMOVIVA,nrigai++);
			key.add(gruppo);
			key.add(conto);
			const TString4 tipocf = cache().get(LF_PCON, key, PCN_TMCF);
			conf.set_paragraph(paragraph);
			conf.set(RMI_CODIVA, rec.get(RMI_CODIVA));
			conf.set(RMI_TIPODET, rec.get(RMI_TIPODET));
			conf.set(RMI_IMPONIBILE, imp.string());
			conf.set(RMI_IMPOSTA, iva.string());
			conf.set(RMI_TIPOC, tipocf);
			conf.set(RMI_GRUPPO, gruppo);
			conf.set(RMI_CONTO, conto);
			conf.set(RMI_SOTTOCONTO, sottoconto);
			if (imptot <= ZERO)
			{
        if (++icg >= concg.items())
          break;
				const TString& gcs = concg.row(icg);
				gruppo = gcs.left(2);
				conto = gcs.mid(2, 2);
				sottoconto = gcs.right(6);
        
        if (icg < impcg.items())
				  imptot = (const real&)impcg[icg];
        else
          imptot = ZERO;
			}
    }
	}
}

void TImporta_mov::transfer(const TMask& msk)
{
  TFilename filename = msk.get(F_PATH); filename.add(msk.get(F_NAME));
	TFilename outdir(msk.get(F_PATHOUT));

  TImporta_galileo_recset s(filename);

  TProgind pi(s.items(), TR("Importazione movimenti in corso..."));
	TConfig * conf = NULL;
	long nmov = - 1;
	int anno = 0;
	TString8 reg;
	TDate dataop;
	int nrigac = 1;
	int nrigai = 1;
	long ntran = 1L;
	bool iva = false;
	TString4 gruppo;
	TString4 conto;
	TString8 sottoconto;
	TString descr(50);
	const int codes = msk.get_int(F_ANNOES);
	const long ditta = msk.get_long(F_CODITTA);
	const TEsercizi_contabili esc;
	TArray rows;
	TArray impcg;
	TString_array concg;
	TCausali_cache cache_causali;

  for (bool ok=s.move_first();ok;ok=s.move_next())
  {
    if (!pi.addstatus(1)) 
      break;
		
		const long dt = s.get(CDDTCM).as_int();
		if (ditta != dt)
			continue;

    const TDate datareg(s.get(DTRGCM).as_int());
    const int es = esc.date2esc(datareg);

		if (codes != es)
			continue;
		const int a = s.get(AAPRCM).as_int();
	  const TString8 r = s.get(TPGICM).as_string();
		const TDate d(s.get(DTOPCM).as_int());
		const long n = s.get(NONPCM).as_int();

		if (anno != a || reg != r || dataop != d || n != nmov )
		{
			if (iva && conf != NULL)
				build_IVA(*conf, rows, concg, impcg, nrigai);
			anno = a;
			reg = r;
			dataop = d;
			nmov = n;

			if (conf != NULL)
				delete conf;
			conf = NULL;
			TFilename temp(outdir);

			temp << '/' << format("%05ld", ntran++);
			temp.ext("ini");
			if (temp.exist())
				remove_file(temp);
			conf = new TConfig(temp);
			conf->set_paragraph("Transaction"); //setto il paragrafo [Transaction] del file ini
			conf->set("Action","INSERT");
			conf->set("Mode", "AUTO");

			conf->set_paragraph("23"); //setto il paragrafo [23] del file ini (testata)

			TString4 codcaus = s.get(CAUSCM).as_string();
			iva = s.get(TPMVCM).as_string() == "I";
			if (atoi(codcaus) != 0)
			{
				codcaus << '0';
				const TCausale& c = cache_causali.causale(codcaus, codes);
				if (!iva && c.iva() != nessuna_iva)
					codcaus.cut(0);
			}
			conf->set(MOV_CODCAUS, codcaus);
			conf->set(MOV_DATAREG, datareg.string());
			const int codpag = s.get(CDPGCM).as_int();
			if (codpag != 0)
				conf->set(MOV_CODPAG, format("%03d", codpag));
			
			TDate datadoc(s.get(DTDOCM).as_int());
			
			conf->set(MOV_DATADOC,	datadoc.string());

			TString16 ndoc = s.get(NRDOCM).as_string();
			
			if (ndoc == "0")
				ndoc.cut(0);
			conf->set(MOV_NUMDOC, ndoc);
			conf->set(MOV_STAMPATO, "X");
			conf->set(MOV_REGST, "X");

			descr = s.get(DSUPCM).as_string();

			if (iva)
			{
				TToken_string key(25, ',');

				key.add(s.get(NPARCM).as_int());
				key.add(s.get(AAOPCM).as_int());
				descr << " Part. " << key;
				conf->set(MOV_REG, s.get(TPGICM).as_string());
				conf->set(MOV_PROTIVA, n);
			}
			descr << '-' <<	anno << '/' <<	reg <<  '/' << dataop << '/' << nmov;
			conf->set(MOV_DESCR, descr);
			nrigac = 1;
			nrigai = 1;
			rows.destroy();
			impcg.destroy();
			concg.destroy();
		}

		const TString gcs = s.get(CONTCM).as_string();
		TString4 sez("D");
		const TString4 codiva = s.get(CDIVCM).as_string();

		gruppo = gcs.left(2);
		conto = gcs.mid(2, 2);
		sottoconto = gcs.right(6);
		if (gcs.full() && codiva.blank())
		{
	    TString8 paragraph;
			real importo = s.get(IMPOCM).as_real();

			if (importo < ZERO)
			{
				importo = -importo;
				sez = "A";
			}
			TToken_string key;

			key.add(gruppo);
			key.add(conto);

			const char tipocf = cache().get(LF_PCON, key, PCN_TMCF)[0];
			if (iva)
			{
				if (tipocf > ' ')
				{
					conf->set_paragraph("23"); //setto il paragrafo [23] del file ini (testata)
					conf->set(MOV_TIPO, tipocf);  
					conf->set(MOV_CODCF, sottoconto);
					conf->set(MOV_TOTDOC, importo.string());
					paragraph.format("%d,%d",LF_RMOV,nrigac++);
					conf->set_paragraph(paragraph);
					conf->set(RMV_SEZIONE, sez);
					conf->set(RMV_TIPOC, tipocf); 
					conf->set(RMV_IMPORTO, importo.string());
					conf->set(RMV_GRUPPO, gruppo);
					conf->set(RMV_CONTO, conto);
					conf->set(RMV_SOTTOCONTO, sottoconto);
					conf->set(RMV_ROWTYPE, "T");
				}
				else
				{
					concg.add(gcs);
					impcg.add(importo);
				}
			}
			else
			{
				paragraph.format("%d,%d",LF_RMOV,nrigac++);
				conf->set_paragraph(paragraph);
				conf->set(RMV_SEZIONE, sez);
				conf->set(RMV_IMPORTO, importo.string());
				conf->set(RMV_GRUPPO, gruppo);
				conf->set(RMV_CONTO, conto);
				conf->set(RMV_SOTTOCONTO, sottoconto);
				conf->set(RMV_TIPOC, tipocf); 
			}
		}
		else
			if (iva)
			{
				TString8 paragraph;
				real importo = s.get(IMPOCM).as_real();
				real imposta = s.get(IMPSCM).as_real();

				if (importo < ZERO)
				{
					importo = -importo;
					sez = "A";
				}
				if (imposta < ZERO)  // giusto ?
					imposta = -imposta;

				const real ind = s.get(INDECM).as_real();
				const TString4 codiva = s.get(CDIVCM).as_string();

				if (ind > ZERO && ind < CENTO)
				{
					real impind = importo * ind / CENTO;
					real ivaind = imposta * ind / CENTO;
					impind.round(2);
					ivaind.round(2);
					importo -= impind;
					imposta -= ivaind;
					if (gcs.blank())
					{
						TRectype rec(LF_RMOVIVA);

						rec.put(RMI_CODIVA, codiva);
						rec.put(RMI_TIPODET, "9");
						rec.put(RMI_IMPONIBILE, impind.string());
						rec.put(RMI_IMPOSTA, ivaind.string());
						rec.put(RMI_GRUPPO, gruppo);
						rec.put(RMI_CONTO, conto);
						rec.put(RMI_SOTTOCONTO, sottoconto);
						rows.add(rec);
					}
					else
					{
						paragraph.format("%d,%d",LF_RMOVIVA,nrigai++);
						conf->set_paragraph(paragraph);
						conf->set(RMI_CODIVA, codiva);
						conf->set(RMI_TIPODET, "9");
						conf->set(RMI_IMPONIBILE, impind.string());
						conf->set(RMI_IMPOSTA, ivaind.string());
						conf->set(RMI_GRUPPO, gruppo);
						conf->set(RMI_CONTO, conto);
						conf->set(RMI_SOTTOCONTO, sottoconto);
					}
				}
				if (gcs.blank())
				{
					TRectype rec(LF_RMOVIVA);

					rec.put(RMI_CODIVA, codiva);
					if (ind >= CENTO)
						rec.put(RMI_TIPODET, "9");
					rec.put(RMI_IMPONIBILE, importo.string());
					rec.put(RMI_IMPOSTA, imposta.string());
					rec.put(RMI_GRUPPO, gruppo);
					rec.put(RMI_CONTO, conto);
					rec.put(RMI_SOTTOCONTO, sottoconto);
					rows.add(rec);
				}
				else
				{
					paragraph.format("%d,%d",LF_RMOVIVA,nrigai++);
					conf->set_paragraph(paragraph);
					conf->set(RMI_CODIVA, codiva);
					if (ind >= CENTO)
						conf->set(RMI_TIPODET, "9");
					conf->set(RMI_IMPONIBILE, importo.string());
					conf->set(RMI_IMPOSTA, imposta.string());
					conf->set(RMI_GRUPPO, gruppo);
					conf->set(RMI_CONTO, conto);
					conf->set(RMI_SOTTOCONTO, sottoconto);
				}
			}
	}
	if (conf != NULL)
		delete conf;

	if (yesno_box(FR("Si desidera confermare l'importazione di %ld movimenti"), ntran -1))
	{
		TString app;
		app << "cg2 -0 -i" << outdir << "/*.ini"; 
		TExternal_app primanota(app);
		primanota.run(true);
	}
}

void TImporta_mov::main_loop()
{
  TImporta_mov_mask msk;
  while (msk.run() == K_ENTER)
  {
    TWait_cursor hourglass;
		transfer(msk);
  }
}

int pi0001100 (int argc, char* argv[])
{
  TImporta_mov main_app;
  main_app.run(argc, argv, TR("Importazione contabilit� Galileo"));
  return true;
}