#include <applicat.h>
#include <assoc.h>
#include <automask.h>
#include <currency.h>
#include <filetext.h>
#include <msksheet.h>
#include <printer.h>
#include <recarray.h>
#include <relation.h>
#include <sort.h>
#include <utility.h>

#include "cg7.h"
#include "cg7300a.h"

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

#define ALIAS_REG		100
 
class TInvioS_file: public TFile_text
{
protected:
  virtual void validate(TCursor& cur,TRecord_text &rec, TToken_string &val, TString& str);

public:
  TInvioS_file(const TString& file_name);
  virtual ~TInvioS_file() { }
};

TInvioS_file::TInvioS_file(const TString& file_name)
          : TFile_text(file_name, "sispac.ini")
{
}

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

  TInvioS_mask();
  
  virtual ~TInvioS_mask(){};
};
  
TInvioS_mask::TInvioS_mask() :TAutomask ("cg7300a")
{
}  
  
bool TInvioS_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{ 
	switch (o.dlg())
	{
	case F_CODDITTA:                               
		if (e==fe_init && o.empty())
		{
			set(F_CODDITTA, main_app().get_firm());
			((TEdit_field&) o).check();
			disable(F_CODDITTA);
		}	
		break;
	default:
		break;	
	}
  return TRUE;
}

class TInvioS : public TSkeleton_application
{                     
	TCursor*				   _cur;
  TInvioS_mask* 		 _msk;
  TInvioS_file*			 _trasfile;
	TConfig*					 _configfile;
  TDate							 _dataini, _datafin;
  
protected:
  virtual bool create(void);
  virtual bool destroy(void);
  virtual void main_loop() ;
  void invio_sispac();
  long i_sispac_clifor(const char* tipocf, const bool invio = TRUE);
  long i_sispac_movcont(const bool invio = TRUE);
  long i_sispac_moviva(const bool invio = TRUE);

public:
	TInvioS_file* apri_file(const char* nome);
	void chiudi_file(TInvioS_file* trasfile);
	TConfig& config() {return *_configfile;};
  TInvioS() {} ;
  virtual ~TInvioS() {} ;
};  

// restituisce un riferimento all' applicazione
inline TInvioS& app() { return (TInvioS&) main_app();}

// gestione dei messaggi estesi nei campi
void TInvioS_file::validate(TCursor& cur,TRecord_text &rec, TToken_string &s, TString& str)
{
  const TString code(s.get(0));
  TString valore;
  if (code == "_FISSO")
  {
    // gestione dei campi fissi per i record delle riba
    // sintassi: _FISSO,!<valore>
    // dove: <valore> � la stringa fissa da emettere
    TString in(s.get());
    CHECK(in[0]=='!',"Macro _FISSO senza carattere '!'");
    in.ltrim(1);
    in.trim();
    valore = in;
  } 
  else if (code == "_TIPORIGA")
  {
		valore = str.empty() ? " " : "S";
  } 
  else if (code == "_CODPAG")
  {
 		valore = app().config().get(str, "PAGAMENTI");
  } 
  else if (code == "_OPZIONI")
  {
 		TString in(s.get()); 	
 		valore = app().config().get(in, "OPZIONI");
  }
  else if (code == "_IMPORTO")
  { 
		real importo(str);
		valore = importo.string(0,2);
  	valore.strip("-");
  	valore.strip("+");
  	valore.strip(".");
  }
  else if (code == "_IMPORTORIGAIVA")
  { 
		real imponibile = cur.curr(LF_RMOVIVA).get_real(RMI_IMPONIBILE);;
		real imposta = cur.curr(LF_RMOVIVA).get_real(RMI_IMPOSTA);;
		imponibile += imposta;
		valore = imposta.string(0,2);
  	valore.strip("-");
  	valore.strip("+");
  	valore.strip(".");
  }
	else if (code == "_INDIR")
	{
		valore = cur.curr(LF_CLIFO).get(CLI_INDCF);
		valore << ' ' << cur.curr(LF_CLIFO).get(CLI_CIVCF);
		valore.cut(40);
	}
	else if (code == "_GIUFIS")
	{
		const char c = str[0];
		valore = (c == 'F') ? "S" : "N";
	}
	else if (code == "_TITOLARE")
	{
		valore = (str.empty() ? "N" : "S");
	}
	else if (code == "_TIPODET")
	{
		valore = (str.empty() ? " " : "100");
	}
	else if (code == "_CONTO")
	{
		int gruppo = cur.curr(LF_CLIFO).get_int(CLI_GRUPPO);
		if (gruppo == 10)
			gruppo = 0;
		int conto = cur.curr(LF_CLIFO).get_int(CLI_CONTO);
		long codice = cur.curr(LF_CLIFO).get_int(CLI_CODCF);
		valore.format("%03d%03d%06ld", gruppo, conto, codice);
	}
	else if (code == "_CONTOMOV")
	{
		int gruppo = cur.curr(LF_RMOV).get_int(RMV_GRUPPO);
		if (gruppo == 10)
			gruppo = 0;
		int conto = cur.curr(LF_RMOV).get_int(RMV_CONTO);
		long codice = cur.curr(LF_RMOV).get_int(RMV_SOTTOCONTO);
		valore.format("%03d%03d%06ld", gruppo, conto, codice);
	}
	else if (code == "_CONTOMOVIVA")
	{
		int gruppo = cur.curr(LF_RMOVIVA).get_int(RMI_GRUPPO);
		if (gruppo == 10)
			gruppo = 0;
		int conto = cur.curr(LF_RMOVIVA).get_int(RMI_CONTO);
		long codice = cur.curr(LF_RMOVIVA).get_int(RMI_SOTTOCONTO);
		valore.format("%03d%03d%06ld", gruppo, conto, codice);
	}
  else NFCHECK("Macro non definita: %s", (const char *)code);
  str = valore;
}

TInvioS_file* TInvioS::apri_file(const char* nome)
{
	TFilename filename = _msk->get(F_DESTINAZIONE);
	filename.add(nome);
	filename.ext("txt");
	if (filename.exist())
		remove(filename);
	TInvioS_file* trasfile = new TInvioS_file(filename);
	trasfile->open(filename,'w');
	trasfile->force_record_separator();
	return trasfile;
}

void TInvioS::chiudi_file(TInvioS_file* trasfile)
{
	trasfile->close();
	delete trasfile;
}

long TInvioS::i_sispac_movcont(const bool invio)
{
  TRectype da(LF_MOV);
  TRectype a(LF_MOV);
	TDate dataini = _msk->get_date(F_DATAINI);
	TDate datafin = _msk->get_date(F_DATAFIN);
	if (dataini.ok())
		da.put(MOV_DATAREG, dataini);
	if (datafin.ok())
		a.put(MOV_DATAREG, datafin);
  TRelation rel(LF_MOV);
  rel.add(LF_RMOV, "NUMREG==NUMREG", 1);
  rel.add(LF_CLIFO, "TIPOCF==TIPO|CODCF==CODCF", 1);
  TCursor cur(&rel, "", 2, &da, &a);
  const long cur_items = cur.items();
  if (cur_items != 0) 
  {               
	  cur.freeze();
    TRectype& cur_rec = cur.curr();
    for (cur = 0; cur.pos() < cur_items; ++(cur))
    {                                                    
			const long numreg = cur.curr().get_long(MOV_NUMREG);
 			bool continua = TRUE;
 			while (continua)
 			{                                                   
 				const long numregrig = cur.curr(LF_RMOV).get_long(RMV_NUMREG);
 				if (numreg == numregrig)
 				{      
 					if (invio)
 					{
			    	TRectype& cur_rec_righe = cur.curr(LF_RMOV);
						TRecord_text recrighe;
						recrighe.set_type("R");
						_trasfile->autoload(recrighe, cur); 
						_trasfile->write(recrighe);
					}
 				}
		  	continua = cur.next_match(LF_RMOV, "NUMREG");
 			}	
    }	
  }                  
  return 0;
}


long TInvioS::i_sispac_moviva(const bool invio)
{
  TRectype da(LF_MOV);
  TRectype a(LF_MOV);
  da.put(MOV_DATAREG, _dataini);
  a.put(MOV_DATAREG, _datafin);
  TRelation rel(LF_MOV);
  rel.add(LF_RMOVIVA, "NUMREG==NUMREG", 1);
  rel.add("REG", "CODTAB[1,4]==ANNOIVA|CODTAB[5,7]==REG", 1);
  rel.add(LF_CLIFO, "TIPOCF==TIPO|CODCF==CODCF", 1);
  TCursor cur(&rel, "", 2, &da, &a);
  const long cur_items = cur.items();
  if (cur_items != 0) 

  {               
	  cur.freeze();
    TRectype& cur_rec = cur.curr();
    for (cur = 0; cur.pos() < cur_items; ++(cur))
    {                                                    
			const long numreg = cur.curr().get_long(MOV_NUMREG);
 			bool continua = TRUE;
 			while (continua)
 			{                                                   
 				const long numregrig = cur.curr(LF_RMOVIVA).get_long(RMI_NUMREG);
 				if (numreg == numregrig)
 				{      
 					if (invio)
 					{
			    	TRectype& cur_rec_righe = cur.curr(LF_RMOVIVA);
						TRecord_text recrighe;
						recrighe.set_type("I");
						_trasfile->autoload(recrighe, cur); 
						_trasfile->write(recrighe);
					}
 				}
		  	continua = cur.next_match(LF_RMOVIVA, "NUMREG");
 			}	
    }	
  }                  
  return 0;
}

long TInvioS::i_sispac_clifor(const char* tipocf, const bool invio)
{
	TString80 nomefile = "FILE";
	nomefile << tipocf;
	TInvioS_file* trasfilecf = apri_file(_configfile->get(nomefile, "OPZIONI"));
  TRelation rel(LF_CLIFO);
  rel.add(LF_COMUNI, "STATO==STATOCF|COM==COMCF", 1);
  rel.add(LF_ANAGFIS,"CODANAGR==CODANAGPER", 1);
  rel.add(LF_ANAG,"TIPOA==TIPOPERS|CODANAGR==CODANAGPER", 1);
	TString80 filtro;
	filtro = "20->TIPOCF == \"";
	filtro << tipocf;
	filtro << "\"";
  TCursor cur(&rel);
	cur.setfilter(filtro, TRUE);
  const long cur_items = cur.items();
  if (cur_items != 0 && invio) 
  {
	  cur.freeze();
    TRectype& cur_rec = cur.curr();
    for (cur = 0; cur.pos() < cur_items; ++(cur))
    {
			TRecord_text rec;
			rec.set_type(tipocf);
			trasfilecf->autoload(rec, cur); 
			trasfilecf->write(rec);
    }	
  } 
	chiudi_file(trasfilecf);
  return 0;
}

//metodone globale che chiama, come un menu, i vari sottometodi in base alle scelte sulla maschera
void TInvioS::invio_sispac()
{
	if (_msk->get_bool(F_CLIFOR))
	{
		i_sispac_clifor("C");
		i_sispac_clifor("F");
	}
	if (_msk->get_bool(F_MOVCONT))
	{
		TString80 filename = _configfile->get("FILEM", "OPZIONI");
		_trasfile = apri_file(filename);
		i_sispac_movcont();
		i_sispac_moviva();
		chiudi_file(_trasfile);
	}	
}

bool TInvioS::create()
{
  _msk = new TInvioS_mask();
	TFilename configname = "cg7300a.ini";
	configname.custom_path();
	_configfile = new TConfig(configname);
  return TSkeleton_application::create();
}

bool TInvioS::destroy()
{ 
	delete _configfile;
	delete _msk;
  return TSkeleton_application::destroy();
}

void TInvioS::main_loop()
{
	_msk->set(F_NUMEROINVIO, _configfile->get_int("NUMEROINVIO","OPZIONI")+1);
	_msk->set(F_DATAINI, _configfile->get("DATA","OPZIONI"));
	_msk->set(F_DESTINAZIONE, _configfile->get("PERCORSO","OPZIONI"));
  while (_msk->run() != K_QUIT)
  {                                  
  	_configfile->set("NUMEROINVIO", _msk->get(F_NUMEROINVIO),"OPZIONI");
  	_configfile->set("DATA", _msk->get_date(F_DATAFIN),"OPZIONI");
  	_configfile->set("PERCORSO", _msk->get(F_DESTINAZIONE),"OPZIONI");
  	_configfile->set_paragraph("PAGAMENTI");
  	_dataini = _msk->get_date(F_DATAINI);
  	_datafin = _msk->get_date(F_DATAFIN);
		const char tipoinvio = _msk->get(F_TIPOINVIO)[0];
		if (tipoinvio == 'S')
			invio_sispac();
	}	
}

int cg7300(int argc, char **argv) 
{
  TInvioS a;
  a.run(argc, argv, "Invio dati contabilit� Sispac/Cosmo");
  return 0;
}