#include <mask.h>
#include <msksheet.h>
#include <progind.h>
#include <recarray.h>
#include <relapp.h>
#include <tabutil.h>
#include <utility.h>

#include "at0.h"
#include "lf.h"				// se non lo metto non riesco a usare gli LF

// nomi campi maschera
#include "at0400a.h"
          
// nomi dei campi
#include "soggetti.h"
#include "convoc.h"
#include "rconvoc.h"

#define IDON_SI "SI"
#define IDON_AF "AF"
       
class TConvoc_app: public TRelation_application
{
	TMask*					_msk;
	TRelation*   		_rel;
	TRelation*			_relsog;
	TCursor*				_cur;						// cursore per selezione soggetti
	TLocalisamfile* _rconvoc;
	TLocalisamfile* _soggetti;
	TRecord_array*	_sconvocati;		// sheet convocati
	long 						_lastcod;				// progressivo convocazione da assegnare
	long						_numero;				// numero convocazione
	TDate						_data; 					// data convocazione
	TString16				_punto;					// punto di raccolta
	TString16				_tipo;					// tipo donazione
	TString16				_codsez;				// codice sezione convocata
	TString16				_codsot;				// codice sottogruppo
              
protected:
	virtual bool user_create();
	virtual bool user_destroy();
	virtual const char* get_next_key();
	virtual int scrivi(const TMask& m, bool ri);
	virtual int write(const TMask& m);
	virtual int rewrite(const TMask& m);
	virtual int read(TMask& m);
	virtual bool remove();
	virtual bool changing_mask(int mode) { return FALSE; }
	virtual TMask* get_mask( int mode = 0) { return _msk; }
	virtual TRelation* get_relation() const { return _rel; }
	
	static bool convocati_notify(TSheet_field& s, int r, KEY k);
	static bool esegui_handler(TMask_field& f, KEY k);
	
public:
	TConvoc_app() {}
	
};

HIDDEN inline TConvoc_app& app() { return (TConvoc_app&) main_app(); }

/*
bool is_idon_one(TString16 idon, const char* tipo)        
// verifica che l'idoneità "idon" sia del tipo "tipo"
// esempio: se passo PL, AF restituisce TRUE
{                      
	bool is_idon = FALSE;
	TTable ido("IDO");
	ido.put("CODTAB",idon); 		
 	if (ido.read() == NOERR)
 	{
 		TString16 tipol(2);
 		tipol = ido.get("S6");
  	if (tipol == tipo)
  		is_idon = TRUE;
	}  		
	return is_idon;
}

bool is_idon(TString16 id1, TString16 id2, TString16 id3, TString16 id4, const char* tipo)
//verifica che almeno una delle "id" sia del tipo "tipo"
{
	return (is_idon_one(id1,tipo) || is_idon_one(id2,tipo) || is_idon_one(id3,tipo) || is_idon_one(id4,tipo));
}
*/

bool TConvoc_app::esegui_handler(TMask_field& f, KEY k)
{
	if (k == K_SPACE)
	{
		TMask& m = f.mask();
		TCursor* cur = app()._cur;
		                     
		app()._numero	= m.get_long(F_NUMERO);		                     
	 	app()._data		= m.get(F_DATA);
		app()._punto	= m.get(F_PUNTO);
		app()._tipo		= m.get(F_TIPO);
		app()._codsez	= m.get(F_CODSEZ);
		app()._codsot	= m.get(F_CODSOT);
		if (app()._numero == 0 || !app()._data.ok() || app()._punto.empty() || app()._tipo.empty())
			return f.error_box("Mancano i dati fondamentali per la convocazione");
		// filtro per sezione
  	TRectype da(LF_SOGGETTI);
		if (app()._codsez.not_empty())  
			da.put(SOG_CODSEZ, app()._codsez);
  	if (app()._codsot.not_empty())
			da.put(SOG_CODSOT, app()._codsot);
		cur->setregion(da, da);
		// filtro per punto di raccolta
		cur->setfilter(format("PUNTORACC == \"%s\"",(const char*)app()._punto));
		// altri filtri piu' complicati
		//cur->set_filterfunction(filter_func_convoc);
		TSheet_field& s = (TSheet_field&)m.field(F_CONVOCATI);
		s.destroy();
    TRectype& rec = cur->curr();
    long last =  cur->items();   
    int r=0;
    TProgind prg (last, "Elaborazione in corso... Prego attendere", FALSE, TRUE, 30);
    for ( *cur=0; cur->pos() < last; ++(*cur) )
    {
      prg.addstatus(1);
			TToken_string& row = s.row(r);
			row.add(rec.get(SOG_CODICE));
			row.add(rec.get(SOG_COGNOME));
			row.add(rec.get(SOG_NOME));
			row.add(' '); // stampato
			row.add(rec.get(SOG_DATANASC));
			row.add(rec.get(SOG_CATDON));
			row.add(rec.get(SOG_TESSAVIS));
      r++;
		}
		s.force_update();
	}
	return TRUE;
}

bool TConvoc_app::user_create()
{
	_msk = new TMask("at0400a");
	_rel = new TRelation(LF_CONVOC);
	_relsog = new TRelation(LF_SOGGETTI);
  _cur = new TCursor(_relsog, "", 4);	//cursore ordinamento per sezione+sottogruppo+cognome+nome
	_rconvoc = new TLocalisamfile(LF_RCONVOC);
	_soggetti = new TLocalisamfile(LF_SOGGETTI);
	_sconvocati = new TRecord_array(LF_RCONVOC,RCV_PROGCONV);
	_msk->set_handler(F_ESEGUI,esegui_handler);
	TSheet_field& sc = (TSheet_field&)_msk->field(F_CONVOCATI);
	sc.set_notify(convocati_notify);
	//TMask& scmask = sc.sheet_mask();
	_rel->lfile().last();
	_lastcod = _rel->lfile().get_long(COV_NUMERO);
	return TRUE;
}	
	
bool TConvoc_app::user_destroy()	
{
	delete _rel;
	delete _relsog;
	delete _msk;
	delete _rconvoc;
	delete _soggetti;
	delete _sconvocati;
	return TRUE;
}

const char* TConvoc_app::get_next_key()
{
	// autonumerazione progressiva delle convocazioni
	return format("%d|%ld", F_NUMERO, _lastcod+1 );
}	

bool TConvoc_app::remove()
{
 	// cancella convocati
 	// cancella testata convocazione
 	bool ok = TRUE;
 	// cancella convocati
	int err = _sconvocati->remove();	
  if (err == _iseof || err == _isemptyfile)
		err = NOERR;
	// cancella la testata
	if (err == NOERR) ok = TRelation_application::remove();
	return (ok && err == NOERR);
}

int TConvoc_app::read(TMask& m)
{
	int err = TRelation_application::read(m);
	if (err == NOERR)
	{
		TRectype* key = new TRectype(LF_RCONVOC);
		key->put(RCV_NUMERO, m.get(F_NUMERO));
		err = _sconvocati->read(key);
		if (err == NOERR)
		{
			TLocalisamfile soggetti(LF_SOGGETTI);
			TSheet_field& s = (TSheet_field&)m.field(F_CONVOCATI);
			s.destroy();
			for (int r=1; r<=_sconvocati->rows(); r++)
			{
				TToken_string& row = s.row(r-1);
				const TRectype& riga = _sconvocati->row(r);
				const TString& codice = riga.get(RCV_CODICE);
				row.add(codice);
				soggetti.put(SOG_CODICE,codice);
				if (soggetti.read() != NOERR) 
					soggetti.zero();
				row.add(soggetti.get(SOG_COGNOME));
				row.add(soggetti.get(SOG_NOME));
				row.add(riga.get(RCV_STAMPATO));
				row.add(soggetti.get(SOG_DATANASC));
 				row.add(soggetti.get(SOG_CATDON));
				row.add(soggetti.get(SOG_TESSAVIS));
			}
		}
		else
		  if (err == _iseof || err == _isemptyfile)
		    err = NOERR;
	}
	return err;
}

int TConvoc_app::write(const TMask& m)
{  
	long curcod = m.get_long(F_NUMERO);
	if (curcod > _lastcod) _lastcod = curcod;
	return TConvoc_app::scrivi(m, FALSE);	
}

int TConvoc_app::rewrite(const TMask& m)
{
	return TConvoc_app::scrivi(m, TRUE);	
}

int TConvoc_app::scrivi(const TMask& m, bool ri)
{                             
	// questo trucco è autorizzato dal capo!
	//TMask& hmask = (TMask&) m;
	//TDate oggi(TODAY);
	//hmask.set(F_DATAULTAGG,oggi);
	//hmask.set(F_UTENULTAGG,user());
	int err = ri ? TRelation_application::rewrite(m) : TRelation_application::write(m);
	if (err == NOERR)
	{
		_sconvocati->destroy_rows();
		TSheet_field& s = (TSheet_field&)m.field(F_CONVOCATI);
		TRectype* key = new TRectype(LF_RCONVOC);
		key->put(RCV_NUMERO, m.get(F_NUMERO));
		_sconvocati->set_key(key);
		for (int r=s.items(); r>0; r--)
		{
			TToken_string& row = s.row(r-1);
			TRectype& rec = _sconvocati->row(r,TRUE);
			rec.put(RCV_CODICE, row.get(0));
			rec.put(RCV_STAMPATO, row.get(3));
		}
		err = ri ? _sconvocati->rewrite() : _sconvocati->write();
	}
	return err;
}

bool TConvoc_app::convocati_notify(TSheet_field& s, int r, KEY k)
{              
  return TRUE;  
}

/*
bool TSoggetti_app::controlli_notify(TSheet_field& s, int r, KEY k)
{
	static bool delete_l = FALSE;	// flag per cancellazione ultima riga
	static TToken_string oldrow;
	bool modified = FALSE;
	TMask& mask = s.mask();

	if (k == K_CTRL+K_DEL)	// avvenuta cancellazione riga
  {
		if (delete_l)
  		modified = TRUE;
  	delete_l = FALSE;	
 	}		
	else	
	{
		switch (k)
		{
	  	case K_SPACE:	  	// inizio modifica riga
	  		oldrow = s.row(r);
	  	break;
			case K_ENTER:			// uscita da riga modificata
			{
				TToken_string& row = s.row(r);
	 			const TDate actdata(row.get(0));
	 			const TString16 acttipo(row.get());
	 			const TDate olddata(oldrow.get(0));
	 			const TString16 oldtipo(oldrow.get());
	 			if (olddata != actdata)
	  		{
	  			ordina_sheet_data(s);
	  			app().tipocon_set_sheet(s);
	  			s.force_update();
	  		}	
				if (modstato_tcs(oldtipo) != ' ' || modstato_tcs(acttipo) != ' ')
	    		modified = TRUE;
	  	}		
	  	break;  	
	  	case K_DEL:  	  	// richiesta di cancellazione riga
	  	{	
	  		oldrow = s.row(r);
	  		const TString16 oldtipo(oldrow.get(1));
	  		if (r == (s.items()-1) && modstato_tcs(oldtipo) != ' ') 
	  			delete_l = TRUE;
	 		}		
	  	break;	
	  }
  }
  if (modified)
		c_reord(s);		
	return TRUE;  
}

bool TSoggetti_app::benemerenze_notify(TSheet_field& s, int r, KEY k)
{
  if (k == K_ENTER)
  {
  }
	return TRUE;  
}

bool TSoggetti_app::storico_notify(TSheet_field& s, int r, KEY k)
{
  if (k == K_ENTER)
  {
  }
	return TRUE;  
}

*/
int at0400(int argc, char* argv[])
{
	TConvoc_app a;
	a.run(argc, argv, "Gestione convocazione");
	return 0;
}