#include <applicat.h>
#include <automask.h>
#include <browfile.h>
#include <defmask.h>
#include <execp.h>
#include <mailbox.h>
#include <printer.h>
#include <progind.h>
#include <tabutil.h>
#include <viswin.h>

#include "pd0300.h"
#include "../db/dblib.h"
#include "../mg/mglib.h"

#include "pd0300100a.h"

///////////////////////////////////////////////////////////
// TValorizzazione_mask
///////////////////////////////////////////////////////////

class TValorizzazione_mask : public TAutomask
{
  TAssoc_array _valori;
  TAssoc_array _risultati;

  TDistinta_tree _tree;
  TString4 _annoes ;
  TString8 _codmag;
	TDate _data;

protected:
  virtual bool on_field_event(TOperable_field& f, TField_event e, long jolly);

public:
  real valore(const TCodice_articolo& dis, const char* liv = NULL);
  void elabora();
  void salva();

  TValorizzazione_mask();
  virtual ~TValorizzazione_mask() { }
};

real TValorizzazione_mask::valore(const TCodice_articolo& dis, const char* liv)
{
  real total;

  if (dis.not_empty())
  {
    TString80 cod = dis;
		bool explode = true;

    if (liv && *liv)
      cod << ',' << liv;

    TString8 codmagdep; 
    add_magcode(codmagdep, get(F_CODMAG));
    add_depcode(codmagdep, get(F_CODDEP));
    _tree.set_global("_MAGDEP", codmagdep); 
    const char tipo = _tree.get_type(dis);

    if (explode &&_tree.set_root(dis))
    {
      TArray boom;
			TLocalisamfile rd(LF_RDIST);
			real peso;
			real val_mat;
			real val_lav;
			real prz_val;


			rd.setkey(2);
      // Esplosione ai materiali di base 
      // raggruppati alla unita' di misura di riferimento
      _tree.explode(boom, false, RAGGR_EXP_BASE, 1);  
      for (int r = boom.last(); r >= 0; r--)
      {
        const TRiga_esplosione& esp = (const TRiga_esplosione&)boom[r];
				const TCodice_articolo & comp  = esp.componente();
				const TCodice_articolo & dist  = esp.distinta();

				rd.put("CODCOMP", comp);
				rd.put("CODDIST", dist);
				
				if (rd.read() == NOERR)
				{
					const TRectype & rec = rd.curr();
					const TString4 tipo = rec.get("TIPO");
					if (tipo == "A")
					{
						TArticolo compd(comp);
						const TString8 um(rec.get("UM"));
						real qta = rec.get_real("EXPR");
						real calo(compd.get(ANAMAG_USER1));

						if (calo == ZERO) calo = UNO;

						TString80 strprezzo("#"); strprezzo << comp;
						real prezzo;

						if (_tree.exist(strprezzo))
							prezzo = _tree.get_real(strprezzo);
						else
							prezzo = compd.get_real(ANAMAG_ULTCOS1);
						val_mat += (prezzo * calo) * qta;
						if (um.starts_with("GR"))
									peso += qta;
					}
					else
						if (tipo == "L")
						{
							TLavorazione lav(comp);
							const TString8 um(lav.um());

							if (um.starts_with("GR"))
								prz_val += lav.prezzo();
							else
							{
								real qta = rec.get_real("EXPR");

								val_lav += lav.prezzo() * qta;

							}
						}
				}
      }
			total = val_mat + (val_lav + prz_val * peso) * (CENTO - get_real(F_SCONTO))/CENTO;
      if (!total.is_zero())
        _risultati.add(cod, total);
    }
  }  

  return total;
}

void TValorizzazione_mask::elabora()
{
  TRectype rec_from(LF_DIST), rec_to(LF_DIST);
  rec_from.put("CODDIST", get(F_DIST_FROM));
  rec_to.put  ("CODDIST", get(F_DIST_TO));
  
  _annoes = get(F_ANNOES);
	_data = get_date(F_DATA);

  
  TRelation rel(LF_DIST);
  TCursor cur(&rel);
  cur.setregion(rec_from, rec_to, 0x2);

  const long items = cur.items();
  TProgind pi(items, TR("Valorizzazione in corso..."), TRUE, TRUE);

  TBrowsefile_field& bf = (TBrowsefile_field&)field(F_PREVIEW);
  TViswin& vw = bf.vis_win();
  
  vw.destroy_lines();
  _valori.destroy();
  _risultati.destroy();

  TString line, num;
  const int dest = get_int(F_VALORIZZA);
 
//          123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
  line = FR("@b                           Valorizzazione al ");
  line << TR("Ultimo Costo");
  line << TR(" - ricalcola ");
  switch (dest) 
  {
    case 1: line << TR("l' Ultimo Costo"); break;
    case 2: line << TR("il Prezzo di Listino"); break;
    default: line << TR("il Costo Standard"); break;
  }       
  line << "     " << get(F_DATA);
  bf.add_line(line);
  line = FR("@bCodice distinta      Descrizione                                                Attuale      Precedente");
  bf.add_line(line);
  
  TString80 descr;

  cur.freeze(TRUE);
  for (cur = 0; cur.pos() < items; ++cur)
  {
    pi.addstatus(1);
    if (pi.iscancelled())
      break;

    const TCodice_articolo art = cur.curr().get("CODDIST");
    const char tipo = _tree.get_type(art);
    if (tipo != 'A')
      continue;
    
    const TPrice value(valore(art));
    line.cut(0) << "$[r,w]" << art << "$[n,w]";
    
    line.left_just(33);
    
    TArticolo_giacenza articolo(art);              
    
    descr = articolo.get(ANAMAG_DESCR);
    descr.left_just(50);
    line << descr;
    
    if (dest == 2)
    {
      const real perc = articolo.get_real(ANAMAG_PERCRIC);
      const TPrice pric(value.get_num() * (100.0 + perc) / 100.0); 
      num = pric.string(TRUE);
    } 
    else
      num = value.string(TRUE);
    num.right_just(16);
    line << num;
    
    TPrice total;                
    
    switch (dest) 
    {
      case  1: total = articolo.ultimo_costo(_annoes); break;
      case  2: total = articolo.prezzo_listino(_annoes, "", ""); break;
      default: total = articolo.costo_standard(_annoes); break;
    }
    num = total.string(TRUE);
    num.right_just(16);
    line << num;

    bf.add_line(line);
  }
  enable(DLG_SAVEREC);
  vw.goto_top();
} 

void TValorizzazione_mask::salva()
{
  const TDate oggi = get_date(F_DATA);
  const int dest = get_int(F_VALORIZZA);

  TProgind pi(_risultati.items(), TR("Registrazione in corso..."), TRUE, TRUE);

  TLocalisamfile dis(LF_DIST);
  TTable lav("LAV");

  FOR_EACH_ASSOC_OBJECT(_risultati, obj, key, item)
  {
    pi.addstatus(1);
    if (pi.iscancelled())
      break;

    const real& val = (const real&)*item;
    if (!val.is_zero())
    {
      const TPrice prezzo(val);
      const real& price = prezzo.get_num(); // val arrotondato ai decimali dei prezzi
      switch(_tree.get_type(key))
      {
      case 'A':
        {
          TArticolo_giacenza art(key);
          switch (dest)
          {
          case 1: 
            art.put_ultimo_costo(price, oggi); 
            break;
          case 2:
						{
							const real perc = art.get_real(ANAMAG_PERCRIC);
							const TPrice pric(price * (100.0 + perc) / 100.0);

							art.set_prezzo_vendita(pric.get_num()); 
						}
            break;
          default: 
            art.put_costo_standard(price); 
            break;
          }
          art.rewrite();
        }
        break;
      case 'L':
        lav.put("CODTAB", key);
        if (lav.read(_isequal, _lock) == NOERR)
        {                
          lav.put("R10", price);  // Was R0
          lav.rewrite();
        }
        break;
      case 'G':
      case 'V':
        dis.put("CODDIST", key);
        if (dis.read(_isequal, _lock) == NOERR)
        {
          dis.put("PREZZO", price);
          dis.rewrite();
        }
        break;
      default :break;
      }
    }
  }

  _valori.destroy();
  _risultati.destroy();
  disable(DLG_SAVEREC);
}

bool TValorizzazione_mask::on_field_event(TOperable_field& f, TField_event e, long jolly)
{
  switch (f.dlg())
  {
  case DLG_ELABORA:
    if (e == fe_button)
    {
      elabora();
      enable(-4);
    }
    break;
  case DLG_SAVEREC:
    if (e == fe_button)
      salva();
    break;
  case DLG_PRINT:
    if (e == fe_button)
    {
      TBrowsefile_field& b = (TBrowsefile_field&)field(F_PREVIEW);
      TViswin& w = b.vis_win();
      TTextfile& f = w.text();
      const long rows = f.lines();
      if (rows > 2)
      {                   
        TPrinter& p = printer();
        TPrintrow row; 
        
        TString line = f.line_formatted(0);      // Legge la prima riga dal line
        row.put(line);   
        p.setheaderline(0, row);  // La imposta come testata
        line = f.line_formatted(1);      // Legge la prima riga dal line
        row.reset();
        row.put(line);   
        p.setheaderline(1, row);  // La imposta come testata
        
        p.headerlen(3);           // Imposta altezza testata
      
        const TPrtype old_prtype = p.printtype();
        p.set_printtype(winprinter);  // Forza la stampa su carta
        p.open();
        for (long l = 2; l < rows; l++) 
        {
          line = f.line_formatted(l);
          row.reset();
          row.put(line, 0);
          p.print(row);
        }
        p.close();
        p.set_printtype(old_prtype);
      }
    }
    break;    
  case DLG_QUIT:
    if (e == fe_button)
    {
      if (_risultati.items() > 0)
        return yesno_box(TR("I risultati dell'ultima elaborazione\n"
                         "non sono stati registrati:\n"
                         "Si desidera uscire ugualmente?"));
    }
    break;
  default:
    break;
  }
  return TRUE;
}

static const char* link_handler(TMask&, int id, const char* str, bool)
{
  const char* app = NULL; 
  switch(id)
  {
  case  0: app = "ve2 -3"; break;
  case  1: app = "ba3 -0 LAV"; break;
  case  2: app = "db0 -4"; break;
  default: break;
  }

  if (app)
  {
    TString ss = "1|"; ss << str;
    TMessage fs(app, MSG_LN, ss);
    fs.send();

    TExternal_app prg(app);
    prg.run();
  }
  return "";
}

TValorizzazione_mask::TValorizzazione_mask() 
                    : TAutomask("pd0300100a") 
{ 
  TBrowsefile_field& bf = (TBrowsefile_field&)field(F_PREVIEW);
  bf.enable_link("Articolo ", 'r');
  bf.enable_link("Lavorazione ", 'v');
  bf.enable_link("Distinta ", 'b');
  bf.set_link_handler(link_handler);

  disable(DLG_SAVEREC);
}


///////////////////////////////////////////////////////////
// TValorizzazione
///////////////////////////////////////////////////////////

class TValorizzazione : public TSkeleton_application
{
protected:  
  virtual bool create();
	virtual const char * extra_modules() const {return "ba";}

public:
  virtual void main_loop();
};

bool TValorizzazione::create()
{
  open_files(LF_MAG,LF_STOMAG,0);
  return TSkeleton_application::create();
}

void TValorizzazione::main_loop()
{
  TValorizzazione_mask m;
  
  m.run();
}

int pd0300100(int argc, char* argv[])
{
  TValorizzazione app;
  app.run(argc, argv, TR("Valorizzazione Dassi"));
  return 0;
}