#include <applicat.h>
#include <filetext.h>
#include <form.h>
#include <mask.h>
#include <relation.h>
#include <tabutil.h>
#include <printer.h>
#include <progind.h>
#include <recarray.h>
#include <utility.h>

#include "at8.h"
#include "at8700a.h"
#include "soggetti.h"
#include "donaz.h"
#include "contsan.h"

#define CTBOFILENAME "at2ctbo.dat"

class TCtbo_file;

class TAt2ctbo: public TSkeleton_application
{
  TMask* 				  _msk;
  TRelation* 		  _rel;
  TCursor* 			  _cur;
  TCtbo_file* 	  _trasfile;
  TRecord_array*  _donazioni;
	TLocalisamfile* _donaz;
	TDate						_data;
  
protected:
  virtual bool create(void);
  virtual void main_loop();
  virtual bool destroy(void) ;
  void transfer(void);
  void inizializza_cur(void);
  void inizializza_file(void);
  void record(THash_object& lavoro);
  static bool annulla_handler(TMask_field& f, KEY k);
public:
  
  const TMask& msk() const { return *_msk; }
  const TRecord_array& donazioni() { return *_donazioni;}
  const TDate data() { return _data;}
  
  TAt2ctbo() {}
  virtual ~TAt2ctbo() {}
};

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

/////////////////////////////////////////////////////
// Classe TCtbo_file customizzata dalla TFile_text //
/////////////////////////////////////////////////////
class TCtbo_file: public TFile_text
{ 
protected:
  virtual void validate(TCursor& cur,TRecord_text &rec, TToken_string &val, TString& str);

public:
  TCtbo_file(const TString& file_name, const TString& config_name);
  virtual ~TCtbo_file() { }
};

TCtbo_file::TCtbo_file(const TString& file_name, const TString& config_name)
          : TFile_text(file_name, config_name)
{
}

// creazione dell'applicazione
bool TAt2ctbo::create()
{
  _msk = new TMask("at8700a");
  _rel = new TRelation(LF_SOGGETTI);
  _cur = NULL;
  _msk->set(F_FILENAME,CTBOFILENAME);
	_donaz = new TLocalisamfile(LF_DONAZ);
 	_donazioni = new TRecord_array(LF_DONAZ,DON_PROGDON);

  //_msk->set_handler(DLG_CANCEL, annulla_handler);
  _trasfile = NULL;
  return TSkeleton_application::create();
}

// distruzione dell'applicazione
bool TAt2ctbo::destroy()
{
  delete _donazioni;
  delete _donaz;
  delete _cur;
  delete _rel;
  delete _msk;

  if (_trasfile)
    delete _trasfile;
  return TSkeleton_application::destroy();
}

// carica la maschera 
void TAt2ctbo::main_loop()
{ 
  // Preimposta gli eventuali valori specificati sulla riga di comando            
  if (argc() >= 3)    
    _msk->set(F_DATAINI, argv(2));
  KEY key = K_ENTER;
  while (key != K_QUIT)
  {
    key = _msk->run();
    if (key == K_ENTER)
      transfer();
  }
}

// trasferimento dati su file per ct bo
void TAt2ctbo::transfer()
{
  inizializza_cur();
   
  TFilename ctboini = "at2ctbo.ini";
  
  _trasfile = new TCtbo_file(_msk->get(F_FILENAME), ctboini);
  inizializza_file();
  
  long n_sog = _cur->items();
  if (n_sog > 0)
  {
   TProgind pi(n_sog,"Trasferimento dati soggetti per CT Bologna...",FALSE,TRUE);
             
   TAssoc_array& tracciati = _trasfile->tracciati();
   //scandisco tutti i soggetti
   for (*_cur = 0; _cur->pos() < n_sog; ++(*_cur))
   {
      pi.addstatus(1L);
      
			TRectype* key = new TRectype(LF_DONAZ);
			key->put(DON_CODICE,_cur->file().get(SOG_CODICE));
			_donazioni->read(key);
      
      THash_object* lavoro =  tracciati.get_hashobj();
      //scandisco tutti i record  di un effetto
      for (int i = 0; lavoro != NULL; i++)
      {
        record(*lavoro);//emetto il record
        lavoro =  tracciati.get_hashobj();
      }
   }
  }
  _trasfile->close();
  delete _trasfile;
  _trasfile = NULL;
	message_box("Operazione terminata");
}

//inizializza il cursore
void TAt2ctbo::inizializza_cur()
{            
  TProgind prg (1,"Preparazione archivio soggetti da trasferire\nPrego attendere...",FALSE, FALSE);
  _data = _msk->get_date(F_DATAINI);
  TString80 filtro = "";
  const TDate nulla(NULLDATE);
  if (_data != nulla)
		filtro << "(ANSI(" << SOG_DATAULTAGG << ")>=\"" << _data.string(ANSI) << "\")";
	else
		_data = TODAY;	
  _cur = new TCursor(_rel,filtro,1);
  _cur->freeze();
}

//inizializza il file di testo su cui emettere gli effetti
void TAt2ctbo::inizializza_file()
{
	TFilename fileriba = _msk->get(F_FILENAME);
  _trasfile->open(fileriba,'w');
	//_trasfile->force_record_separator(TRUE);
      
}

//emetto un record del flusso di effetti
void TAt2ctbo::record(THash_object& lavoro)
{
  TTracciato_record&  oggetto = (TTracciato_record&)lavoro.obj();
  const TString& tipo = oggetto.type();
  TRecord_text rec(tipo);
  //carico il record da emettere
  _trasfile->autoload(rec, *_cur, &tipo);
  _trasfile->write(rec);//emetto i dati su file
}

// handler per gestire la conferma dell'annullamento dei dati inseriti
// nella maschera
bool TAt2ctbo::annulla_handler(TMask_field& f, KEY k)
{
  TMask &m = f.mask();
  if (k == K_SPACE)
  {
    if (yesno_box("Vuoi veramente annullare i dati inseriti"))
       m.reset();
  }
  return TRUE;
}

// gestione dei messaggi estesi nei campi
void TCtbo_file::validate(TCursor& cur,TRecord_text &rec, TToken_string &s, TString& str)
{
  const TString code(s.get(0));
  TString valore;
  if (code == "_TOTALE")
  {
  	int totale = 0;
    TString16 tipodon(s.get());
    CHECK(tipodon[0]=='!',"Macro _TOTALE senza carattere '!'");
    tipodon.ltrim(1);
		for (int r=1; r<=app().donazioni().rows(); r++)
		{
			const TRectype& riga = app().donazioni().row(r);                
			const TDate datadon = riga.get(DON_DATADON);
			if ((riga.get(DON_TIPODON)==tipodon) && (app().data().year() == datadon.year()))
				totale++;
    }
    valore.cut(0);
    valore << totale;
  }
  else if (code == "_ULTIMA")
  {
    valore.cut(0);
  	TString16 tipodon(s.get());
    CHECK(tipodon[0]=='!',"Macro _ULTIMA senza carattere '!'");
    tipodon.ltrim(1);
		for (int r=1; r<=app().donazioni().rows(); r++)
		{
			const TRectype& riga = app().donazioni().row(r);
			const TDate datadon = riga.get(DON_DATADON);
			if ((riga.get(DON_TIPODON)==tipodon) && (app().data().year() == datadon.year()))
				valore = riga.get(DON_DATADON);
    }
  }
  else if (code == "_MOTIVO")
  {

		const TDate datacon = cur.curr().get(SOG_DATASTATO);
		const long codsog = cur.curr().get_long(SOG_CODICE);
		TLocalisamfile controlli(LF_CONTSAN);
		controlli.setkey(2); 
		controlli.put(CON_DATACON,datacon);
		controlli.put(CON_CODICE,codsog);
		if (controlli.read() == NOERR)
			valore = controlli.get(CON_MOTIVO);
		else
			valore.cut(0);
  }
  
  
  else NFCHECK("Macro non definita: %s", (const char *)code);
  
  str = valore;
}

int at8700(int argc, char* argv[])
{
  TAt2ctbo a ;
  a.run(argc, argv, "Trasferimento dati a CT Bologna");
  return 0;
}