#include <applicat.h>
#include <automask.h>
#include <defmask.h>
#include <relation.h>
#include <cfven.h>
#include <progind.h>
#include <textset.h>
#include <utility.h>
#include "../db/dblib.h"
#include "../ve/velib.h"
#include <rdoc.h>

#include "ps0920.h"
#include "ps0920400a.h"

class TShuttle : public TObject
{
	TString _codnum;
	TString4 _provv;
	TString _impianto;
	int _anno;
	TString _codart;
	TString _codart_orig;
	long _ndoc;
	int _nriga;
	real _qta;

protected:
  virtual TObject* dup() const { return new TShuttle(*this); }
	void get_codart_orig(const TRectype & rec);
	const real qta_orig();

public:
	const TString & codnum() const { return _codnum; }
	const TString & provv() const { return _provv; }
	const int anno() const { return _anno; }
	const long ndoc() const { return _ndoc; }
	const int nriga() const { return _nriga; }
	const TString & codart() const { return  _codart; }
	const TString & codart_orig() const { return  _codart_orig; }
	const TString & impianto() const { return _impianto; }
	const real & qta() const { return _qta; }
	const real scarto();
  TShuttle(const TRectype & rec);
  TShuttle(const TShuttle & s);
  void add(const TRectype & rec);
	static const char * key(const TRectype & rec);
	const char * key(bool full = false) const;
  virtual ~TShuttle() {} 
};

const real TShuttle::scarto()
{
	real scarto = qta_orig();
	TDistinta_tree	d;
	TArray boom;

	if (_codart != _codart_orig)
	{
		d.set_root(_codart_orig);
		if (d.explode(boom, false, RAGGR_EXP_NONE, 0, "A") > 0)
		{
			const int items = boom.items();
			bool found = false;

			for (int i = 0; i < items; i++)
			{
				const TRiga_esplosione & re = (const TRiga_esplosione &) boom[i];
				
				if (re.articolo() == _codart)
				{
					if (re.curr_qta() != UNO  && re.curr_qta() != ZERO)
					{
						scarto *= re.curr_qta();
						scarto.round(3);
						found = true;
					}
					break;
				}
			}
			if (!found)
				scarto = qta();
		}
	}
	scarto -= qta();
	return scarto < ZERO ? ZERO : scarto ;
}

const real TShuttle::qta_orig()
{
	TToken_string key(_codnum);
	
	key.add(_anno);
	key.add(_provv);
	key.add(_ndoc);
	key.add(_nriga);
	
	const TRectype & r = cache().get(LF_RIGHEDOC, key);

	real qta(r.get_real(RDOC_QTA));
	
	return qta;
}

void TShuttle::get_codart_orig(const TRectype & rec)
{
	TToken_string key(rec.get("CODNUM"));
	
	key.add(rec.get("ANNO"));
	key.add(rec.get("PROVV"));
	key.add(rec.get("NDOC"));
	key.add(rec.get("NRIGA"));

	const TRectype & r = cache().get(LF_RIGHEDOC, key);
	
	_codart_orig = r.get(RDOC_CODARTMAG);
}

TShuttle::TShuttle(const TRectype & rec)
{
	_codnum = rec.get("CODNUM");
	_provv = rec.get("PROVV");
	_anno = rec.get_int("ANNO");
	_ndoc = rec.get_long("NDOC");
	_nriga = rec.get_long("NRIGA");
	_codart = rec.get("CODART");
	_impianto = rec.get("IMPIANTO");
	_qta = rec.get_real("QTA");
	get_codart_orig(rec);
}

TShuttle::TShuttle(const TShuttle & s)
{
	_codnum = s._codnum;
	_provv = s._provv;
	_anno = s._anno;
	_ndoc = s._ndoc;
	_nriga = s._nriga;
	_codart = s._codart;
	_impianto = s._impianto;
	_qta = s._qta;
	_codart_orig = s._codart_orig;
}

void TShuttle::add(const TRectype & rec)
{
	_qta += rec.get_real("QTA");
}

const char * TShuttle::key(const TRectype & rec)
{
	TString & key = get_tmp_string(60);
	
	key.format("%-4s", (const char *) rec.get("CODNUM"));
	
	key << format("%04d", rec.get_int("ANNO"));
	key << format("%07ld", rec.get_long("NDOC"));
	key << format("%04d", rec.get_int("NRIGA"));
	key << rec.get("IMPIANTO");
	return (const char *) key;
}

const char * TShuttle::key(bool full) const
{
	TString & key = get_tmp_string(60);
	
	key.format("%-4s%04d%07ld%04d", (const char *) _codnum,	_anno, _ndoc, _nriga);
	if (full)
		key << _impianto;
	return (const char *) key;
}

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

public:
  TMaskPs09204();
  virtual ~TMaskPs09204();
};

TMaskPs09204::TMaskPs09204()
            : TAutomask("ps0920400a")
{
}

TMaskPs09204::~TMaskPs09204()
{  
}             

bool TMaskPs09204::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
	const int id = o.dlg();
	switch (id)
	{
		case F_CODCLI:
			if (e == fe_modify)
			{
			}
		default:
			break;
	}
  return TRUE;
}

class TRiepilogoProduzionePs0920 : public TSkeleton_application  
{
	TAssoc_array _riepilogo;
	TAssoc_array _impianti;
  TMaskPs09204 * _mask;
	virtual bool check_autorization() const {return false;}
  virtual const char * extra_modules() const {return "ve";}


protected:
  virtual void main_loop();
  virtual bool create();

public:
	TAssoc_array & riepilogo() {return _riepilogo;}
	TAssoc_array & impianti() {return _impianti;}
  const TMaskPs09204 & mask() const {return *_mask;}
  virtual ~TRiepilogoProduzionePs0920();
};

bool build_riep(const TRelation& rel, void* pJolly)
{
	TRiepilogoProduzionePs0920 * app = (TRiepilogoProduzionePs0920 *) pJolly;
	TAssoc_array & r = app->riepilogo();
	const TString key = TShuttle::key(rel.curr());

	TShuttle * s = (TShuttle *) r.objptr(key);

	if (s == NULL)
		r.add(key, new TShuttle(rel.curr()));
	else
		s->add(rel.curr());

	const TString8 impianto = rel.curr().get("IMPIANTO");

	if (!app->impianti().is_key(impianto))
		app->impianti().add(impianto, impianto);
	return true;
}

void TRiepilogoProduzionePs0920::main_loop()
{
  while (_mask->run() == K_ENTER)
  {
		TCursor c(new TRelation(LF_RILPROD), "", 3);
		TRectype from(c.curr());

		_riepilogo.destroy();
		_impianti.destroy();
		from.put("DATA",_mask->get(F_DADATA));

		TRectype to(from);

		to.put("DATA",_mask->get(F_ADATA));
		c.setregion(from, to);
		const long codcli = _mask->get_long(F_CODCLI);

		if (codcli > 0L)
	  {
			TString filter; filter.format("CODART[1,3]==\"%03ld\"", codcli);
			c.setfilter(filter);
		}
		c.scan(build_riep, this);

		TString_array keysimp;
		TAS400_recordset out("AS400(2048)");

		_impianti.get_keys(keysimp);
		keysimp.sort();
		
		int items = keysimp.items();

		out.create_field("OR", 0, 4);
		out.create_field("AN", 4, 4);
		out.create_field("NR", 8, 7);
		out.create_field("AR", 15, 20);
		int p = 35;
		for (int i = 0; i < items;i++)
		{
			out.create_field(format("Q%1d", i), p , 10);
			p += 10;
			out.create_field(format("S%1d", i), p , 10);
			p += 10;
			out.create_field(format("P%1d", i), p , 10);
			p += 10;
		}
		out.new_rec("");
		out.set("OR", "Ordine");
		out.set("AN", "Anno");
		out.set("NR", "Numero");
		out.set("AR", "Articolo");
		for (int i = 0; i < items;i++)
		{
			out.set(format("Q%1d", i), cache().get("IMP", (TString &)keysimp[i], "S0"));
			out.set(format("S%1d", i), "");
			out.set(format("P%1d", i), "");
		}
		out.new_rec("");
		out.set("OR", "");
		out.set("AN", "");
		out.set("NR", "");
		out.set("AR", "");
		for (int i = 0; i < items;i++)
		{
			out.set(format("Q%1d", i), "Quantit�");
			out.set(format("S%1d", i), "Scarto");
			out.set(format("P%1d", i), "%");

		}
	
		TString_array keys;
		TString last_key;

		_riepilogo.get_keys(keys);
		keys.sort();
		items = keys.items();
		
		TProgind pi(items, "Esportazione");

		for (int i = 0; i < items; i++)
		{
			pi.addstatus(1L);
			TShuttle * s = (TShuttle *) _riepilogo.objptr((TString &)keys[i]);
			const TString key(s->key());

			if (last_key != key)
			{
				last_key = key;
				out.new_rec("");
				out.set("OR", s->codnum());
				out.set("AN", long(s->anno()));
				out.set("NR", s->ndoc());
				out.set("AR", s->codart_orig());
			}
		
			const int p = keysimp.find(s->impianto());

			real scarto = s->scarto();

			out.set(format("Q%1d", p), s->qta());
			out.set(format("S%1d", p), scarto);
			const real perc = scarto * CENTO / (s->qta() + scarto);
			out.set(format("P%1d", p), perc.stringa(6, 2));
		}

		TFilename f(_mask->get(F_PATH));

		if (!is_slash(f[f.len() - 1]))
			f << SLASH;
		f << _mask->get(F_NAME);
		f.ext("xls");
		out.save_as(f, fmt_html);
	}
}

bool TRiepilogoProduzionePs0920::create()
{
	_mask = new TMaskPs09204;
	return TSkeleton_application:: create();
}

TRiepilogoProduzionePs0920::~TRiepilogoProduzionePs0920()
{
	delete _mask;
}

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

int ps0920400(int argc, char* argv[])
{
  TRiepilogoProduzionePs0920 a;

  a.run(argc, argv, "Riepilogo Produzione DbService");
  return 0;
}