#include <applicat.h>
#include <automask.h>
#include <progind.h>

#include "pg0001.h"
#include "pg0001500a.h"
#include "../cg/cglib01.h"
#include "../mg/mglib.h"
#include "../mg/movmag.h"
#include "../mg/rmovmag.h"

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

public:
  TMaskpg00015() : TAutomask("pg0001500a") { }
  virtual ~TMaskpg00015() { }
};

bool TMaskpg00015::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
  return true;
}

class TCopiaMovMg : public TSkeleton_application  
{
	virtual bool check_autorization() const {return false;}
  virtual const char * extra_modules() const {return "ba";}

protected:
  virtual void main_loop();

public:
};

void TCopiaMovMg::main_loop()
{
  TMaskpg00015 m;

  while (m.run() != K_QUIT)
  {
		TEsercizi_contabili es;
		TArray movs;
		const long damov = m.get_long(F_DANUM);
		const long amov = m.get_long(F_ANUM);
		const TDate newdate  = m.get_date(F_DATAMOV);
		TMov_mag mov;
		TRectype rec(LF_MOVMAG);
		long newnmov = atol(mov.get_next_key()); 
		const real valtot = m.get_real(F_VALTOT);
		const int qmax = m.get_int(F_QMAX);
		const real minval = m.get_real(F_VMIN);
		const int cmax = m.get_int(F_CMAX);
		real actval;

		{
			TProgind rd(amov - damov + 1, "Lettura");

			for (long n = damov; n <= amov; n++)
			{
				rec.zero();
				rec.put(MOVMAG_NUMREG, n),

				mov.read(rec);
				mov.body();
				mov.renum_mov(newnmov++);
				mov.put(MOVMAG_DATAREG, newdate);
				mov.put(MOVMAG_DATACOMP, newdate);
				mov.put(MOVMAG_ANNOES, es.date2esc(newdate));

				const int nrows = mov.body().rows();

				for (int r = 1; r <= nrows; r++)
				{
					const TRectype & row = mov.body().row(r);
					const real qta = row.get_int(RMOVMAG_QUANT);
					const real prezzo = row.get_real(RMOVMAG_PREZZO);
					real val = prezzo * qta;

					val.round(2);
					actval += val;
				}
				movs.add(mov);
				if (!rd.iscancelled())
					rd.addstatus(1L);
			}
		}

		real varp = valtot / actval;

		varp.round(6);

		const real sign = varp > UNO ? UNO : -UNO;
		int cnt = 0;
		int loops = 0;
		{
			TProgind c(100, "Calcolo");

			while (sign * actval < sign * valtot && loops < 100)
			{
				const int nmov = movs.items();

				actval = ZERO;
				for (int i = 0; i < nmov; i++)
				{
					TMov_mag &mov = (TMov_mag &) movs[i];
					const int nrows = mov.body().rows();
					int r;

					for (r = 1; r <= nrows; r++)
					{
						TRectype & row = (TRectype &) mov.body().row(r);
						const real qta = row.get_real(RMOVMAG_QUANT);
						const real prezzo = row.get_real(RMOVMAG_PREZZO);
						
						real v = varp * qta;
						 
						v.round(0);
						int newqta = v.integer();

						if (prezzo >= minval && newqta > qmax)
							newqta = qmax;
						else
							if (qta.integer() == newqta)
							{
								cnt++;
								if (cnt == cmax)
								{
									cnt = 0;
									if (sign > ZERO)
										newqta++;
									else 
										newqta--;
								}
							}

						if (sign > ZERO)
						{
							if (newqta < qta.integer())
								newqta = qta.integer();
						}
						else
						{
							if (newqta > qta.integer())
								newqta = qta.integer();
						}

						if (newqta < 0)
							newqta = 0;

						real val = prezzo * newqta;

						val.round(2);
						actval += val;
						row.put(RMOVMAG_QUANT, newqta);
					}
					for (r = nrows; r > 0; r--)
					{
						const TRectype & row = mov.body().row(r);
						const int qta = row.get_int(RMOVMAG_QUANT);
						if (qta == 0)
							mov.body().destroy_row(r, true);
					}
				}
				varp = valtot / actval;
				varp.round(6);
				loops++;
				if (!c.iscancelled())
					c.addstatus(1L);
			}
		}

		TString msg;

		msg.format("Valore totale %s, devo registrare", (const char *) actval.stringa());

		if (yesno_box(msg))
		{
			const int nmov = movs.items();
			TProgind w(nmov, "Scrittura");
			TLocalisamfile movmag(LF_MOVMAG);

			for (int i = 0; i < nmov; i++)
			{
				TMov_mag &mov = (TMov_mag &) movs[i];
				mov.write(movmag);
				if (!w.iscancelled())
					w.addstatus(1L);
			}
		}
  }
}

int pg0001500(int argc, char* argv[])
{
  TCopiaMovMg a;
  a.run(argc, argv, "Copia Movimenti di magazzino");
  return 0;
}