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

#include "../ve/velib.h"

#include  "lv3500a.h"

                                 ///////////////////////////
                                 ////    TSITMAG_MSK    ////
                                 ///////////////////////////

//classe TSitmag_msk
class TSitmag_msk: public TAutomask
{
  static const int _ndep = 4;
protected:
  virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);

  void calcola_qta_magazzino() const;

public:
  TSitmag_msk();
};

//CALCOLA_QTA_MAGAZZINO: metodo che si preoccupa di riempire lo sheet
//con le quantità relative all'articolo / anno selezionati nei vari depositi
//ogni volta che viene modificato un campo dell'articolo o il campo anno
void TSitmag_msk::calcola_qta_magazzino() const
{
  //recupero le variabili di interesse
  const TString80 codart = field(F_CODART).get();
  const int anno = field(F_ANNO).get_long();
  TString4 codmag  = field(F_CODMAG).get();  codmag.trim();  

  //Instanzio l'oggetto che mi permette di recuperare le quantità riceercate
  const TArticolo_giacenza art(codart);

  //Instanzio lo sheet, e recupero le posizioni di maggior interesse
  //(vengono usate più volte all'interno del programma)
  TSheet_field& sheet = sfield(F_RIGHE);
  const int posgiac = sheet.cid2index(S_GIAC);
  const int posordf = sheet.cid2index(S_ORDFOR);
  const int posordc = sheet.cid2index(S_ORDCLI);
  const int posdisp = sheet.cid2index(S_DISP);

  //per ogni magazzino
  for(int i = 0; i < _ndep; i++)
  {
    //recupero una riga alla volta
    TToken_string& row = sheet.row(i);
    //recupero il codice del deposito
    TString4 coddep = row.get(sheet.cid2index(S_CODDEP));
    coddep.trim();

    //costruisco il codice magazzino + deposito
    TString8 deposito;
    deposito << codmag << coddep;

    //inizializzo le quantità di interesse(la giacenza a quella corrente, le altre a zero)
    const long giac = art.giacenza_anno(deposito, "", anno).integer();
    long ordf = 0L;
    long ordc = 0L;
    long disp = 0L;

    //cerco il record dell'articolo selzionato corrispondente all'anno corrente
    TRecord_array& rmag = art.mag(anno);
    int j = art.find_mag(anno, deposito, "");
    //se lo trovo ricavo i valori degli ordini fornitori e clienti
    //e poi calcolo la disponibilità seconda la formula
    //disponibilità = giacenza + ordini_fornitori - ordini_clienti
    if(j >= 0)
    {
      const TRectype& rec = rmag.row(j);

      ordf = rec.get_long(MAG_ORDF);
      ordc = rec.get_long(MAG_ORDC);

      disp = giac + ordf - ordc;      
    }

    //scrivo le varie quntità che ho ricavato
    row.add(giac, posgiac);
    row.add(ordf, posordf);
    row.add(ordc, posordc);
    row.add(disp, posdisp);
  }

  //calcolo dei totali
  long totgiac = 0L;
  long totordf = 0L;
  long totordc = 0L;
  long totdisp = 0L;

  //rileggo lo sheet e sommo le varie quantità
  for(int i = 1; i < _ndep; i++)
  {
    TToken_string& row = sheet.row(i);    
    
    totgiac += row.get_long(posgiac);
    totordf += row.get_long(posordf);
    totordc += row.get_long(posordc);
    totdisp += row.get_long(posdisp);
  }

  //scrivo i totali nelle posizioni corrette
  TToken_string& row = sheet.row(_ndep);
  row.add(totgiac, posgiac);
  row.add(totordf, posordf);
  row.add(totordc, posordc);
  row.add(totdisp, posdisp);

  sheet.force_update();
}


//ON_FIELD_EVENT: metodo che gestisce gli eventi sui campi della maschera
bool TSitmag_msk::on_field_event(TOperable_field& f, TField_event e, long jolly)
{
  switch (f.dlg())
  {
  case DLG_CANCEL:
    //alla pressione del bottone annulla azzero tutte le quantità,
    //svuoto i campi codart e desart e restituisco il focus al campo codart
    if(e == fe_button)
    {
      reset(F_CODART);
      reset(F_DESART);

      TSheet_field& sheet = sfield(F_RIGHE);
      for (int i = 1; i <= _ndep; i++)
      {
        TToken_string& row = sheet.row(i);
        row.add(0L, sheet.cid2index(S_GIAC));
        row.add(0L, sheet.cid2index(S_ORDFOR));
        row.add(0L, sheet.cid2index(S_ORDCLI));
        row.add(0L, sheet.cid2index(S_DISP));
      }
      sheet.force_update();

      field(F_CODART).set_focus();
      return false;
    }
    break;
  case F_CODART:
    if (e == fe_modify && !f.empty())
      calcola_qta_magazzino();
    break;
  case F_ANNO:
    if (e == fe_modify)
      calcola_qta_magazzino();
    break;
  case F_RIGHE:
    if (e == se_query_add)
      return false;
    break;
  default: break;
  }
  return true;
}

//metodo costruttore che precarica i campi di interesse sulla maschera
TSitmag_msk::TSitmag_msk():TAutomask("lv3500a") 
{
  //precarico i campi fissi
  const TDate oggi(TODAY);
  set(F_ANNO, esercizi().date2esc(oggi));
  set(F_CODMAG, ini_get_string(CONFIG_DITTA, "lv", "CODMAG"));

  TSheet_field& sheet = sfield(F_RIGHE);

  for(int i = 0; i <= _ndep; i++)
  {
    TString4 coddep;

    TToken_string& row = sheet.row(-1);
    switch(i)
    {
    case 0:  coddep = ini_get_string(CONFIG_DITTA, "lv", "CODMAGN");  break;  //Deposito nuovo
    case 1:  coddep = ini_get_string(CONFIG_DITTA, "lv", "CODMAGP");  break;  //Deposito pulito
    case 2:  coddep = ini_get_string(CONFIG_DITTA, "lv", "CODMAGC");  break;  //Deposito circolante
    case 3:  coddep = ini_get_string(CONFIG_DITTA, "lv", "CODMAGCL"); break;  //Deposito presso cliente
    default: row.add(TR("TOTALI"), sheet.cid2index(S_DESDEP));        break;
    }
    row.add(coddep, sheet.cid2index(S_CODDEP));

    //questo if mi permette di fare la decodifica del campo descrizione deposito
    if(i < _ndep)
      sheet.check_row(i);
  }

  sheet.force_update();
}

                                 /////////////////////////////
                                 ////    TSitmag_app    ////
                                 /////////////////////////////

//classe TSitmag_app
class TSitmag_app : public TSkeleton_application
{
  TSitmag_msk* _msk;
protected:
  virtual bool create();
  virtual bool destroy();

public:
  bool transfer();
  virtual void main_loop();  
};

//CREATE: metodo costruttore
bool TSitmag_app::create()
{
  _msk = new TSitmag_msk; 
  return TSkeleton_application::create();
}

//DESTROY: metodo distruttore
bool TSitmag_app::destroy()
{	
  delete _msk;
  return TApplication::destroy();
}

//TRANSFER: metodo principale dell'elaborazione, che non deve fare niente
//perchè viene tutto gestito nella maschera
bool TSitmag_app::transfer()
{   
  return true;
}

void TSitmag_app::main_loop()
{
  while (_msk->run() == K_ENTER)
	  transfer();
 }

int lv3500(int argc, char *argv[])
{
  TSitmag_app a;
  a.run (argc, argv, "Situazione magazzino");
  return TRUE;
}