#include <automask.h>
#include <defmask.h>
#include <execp.h>
#include <progind.h>
#include <relapp.h>

#include "lv0400.h"
#include "lvlib.h"

#include "../cg/cglib01.h"
#include "../mg/anamag.h"
#include "../mg/mglib.h"

long lv_new_contract(long cliente, int indsped)
{
  TConfig ini(CONFIG_DITTA, "lv");
  const bool unicont=ini.get_bool("UniCont");

  long codcont=0;
  if (unicont)
  {
    TISAM_recordset recset ("USE LVCONDV");
    for (bool ok=recset.move_first(); ok; ok=recset.move_next())
    {
      const long codice=recset.get("CODCONT").as_int();
      if (codice>codcont)
        codcont=codice;
    }
  }
  else
  {
   TString query; 
   query<<"USE LVCONDV \n"
        <<"FROM CODCF=#CLIENTE\n"
        <<"TO CODCF=#CLIENTE\n";
   TISAM_recordset recset (query);
   recset.set_var("#CLIENTE",cliente);
   if (recset.move_last())
     codcont=recset.get("CODCONT").as_int();
     
  }
  codcont++;
  return codcont;
}


class TContratti_msk: public TAutomask
{
  long _post_contr;

protected:
  bool on_art_select();
  virtual bool on_field_event(TOperable_field& o,TField_event e,long jolly);
  virtual void on_idle();

public:
  TContratti_msk();
};

bool TContratti_msk::on_art_select() 
{
  TSheet_field& ss = sfield(F_RIGHE);
  TMask& rowmask = ss.sheet_mask();
  TToken_string & row  = ss.row(ss.selected());
  const TString80 codart(row.get(ss.cid2index(S_CODART)));
  const long codcf = get_long(F_CODCF);
  const int indsped = get_int(F_INDSPED);
  TArticolo_lavanderie & artrec = cached_article_laundry(codart, 'C', codcf, indsped);
	TDate datasc(TODAY);
	const int annoes = esercizi().date2esc(datasc);

	int index = artrec.find_clifomag(annoes);

	if (index > 0)
	{
	  const TString4 umcont(row.get(ss.cid2index(S_UM)));
		const real dotin = artrec.convert_to_um(artrec.clifomag(annoes)[index].get_real("DOTIN"),umcont);
		rowmask.set(S_DOTIN, dotin);
		row.add(dotin.stringa(), ss.cid2index(S_DOTIN));
		const real dotod = artrec.convert_to_um(artrec.clifomag(annoes)[index].get_real("DOTOD"),umcont);
		rowmask.set(S_DOTOD, dotod);
		row.add(dotod.stringa(), ss.cid2index(S_DOTOD));
		const real dottmp = artrec.convert_to_um(artrec.clifomag(annoes)[index].get_real("DOTTM"),umcont);
		rowmask.set(S_DOTTMP, dottmp);
		row.add(dottmp.stringa(), ss.cid2index(S_DOTTMP));
		const real consyear = artrec.convert_to_um(artrec.clifomag(annoes)[index].get_real("CONSANNO"),umcont);
		rowmask.set(S_CONSANNO, consyear);
		row.add(consyear.stringa(), ss.cid2index(S_CONSANNO));
		const real consmonth = artrec.convert_to_um(artrec.clifomag(annoes)[index].get_real("CONSMESE"),umcont);
		rowmask.set(S_CONSMESE, consmonth);
		row.add(consmonth.stringa(), ss.cid2index(S_CONSMESE));
	}

  const bool varclcons = artrec.get_int(ANAMAG_PPCONF)>0;

  ss.enable_cell(ss.selected(),ss.cid2index(S_CALCCONS));

  rowmask.set(S_CALCCONS,"0"); 
  row.add("0",ss.cid2index(S_CALCCONS));

  for (short id=F_IMPFISART; id<=F_IMPFISART+30; id++)
  {
    const int pos=id2pos(id);
    if (pos>0)
      fld(pos).set(row.get(ss.cid2index(id-400)));
  }
 
	return true;
}

void TContratti_msk::on_idle()
{
  if (_post_contr > 0)
  {
    set(F_CODCONT, _post_contr);
    _post_contr = 0;
    efield(F_CODCONT).set_focus();
  }
  TAutomask::on_idle();
}

bool TContratti_msk::on_field_event(TOperable_field& o,TField_event e,long jolly)
{
  switch(o.dlg())
  {
  case F_CODCF:
    if (query_mode())
    {
      if (e == fe_modify && !o.empty() && efield(F_CODCONT).empty())
      {
        const long codcf = atol(o.get());
        const int indsped = get_int(F_INDSPED);
        const TDate oggi(TODAY);
        _post_contr = lv_find_contract(codcf, indsped, oggi);
      }
		}
    break;
  case DLG_PLANNING:
    if (e==fe_button && edit_mode())
    {
      TRelation_application& app=(TRelation_application&) main_app();
      app.get_relation()->read(_isequal,_unlock);
      TString str;
      str << "lv0 -4 " << get(F_CODCF) << " " << get(F_CODCONT);
      TExternal_app planning(str);
      planning.run();
      app.get_relation()->read(_isequal,_lock);
    }
    break;
  case S_CODART:
    if (!o.empty())
    {
      if (e==fe_modify)
      {  
        TArticolo art(o.get());
        if (art.um().rows() > 0)
        {
          TSheet_field& ss=sfield(F_RIGHE);
          TMask& m = o.mask(); // maschera di riga!
          const TString& um = art.um()[1].get(UMART_UM);
          m.set(S_UM,um);
          TToken_string& row=ss.row(ss.selected());
          row.add(o.get(),ss.cid2index(S_CODART));
          row.add(um,S_UM);
          on_art_select();

        }
      }
      else
        if (e==fe_init)
          on_art_select();
    }
    break;
  case F_RIGHE:
    if (e==se_enter)
    {
      TSheet_field& ss=(TSheet_field&)o;
      TToken_string& row=ss.row(ss.selected());
      for (short id=F_IMPFISART; id<=F_IMPFISART+30; id++)
      {
        const int pos=id2pos(id);
        if (pos>0)
          fld(pos).set(row.get(ss.cid2index(id-400)));
      }
    }
    break;
  case DLG_NEWREC:
    if (e == fe_button)
    {
      if (edit_mode())
      {
        send_key(K_ESC, 0);
        return false;
      }
      if (query_mode())
      {
        const long codcf = get_long(F_CODCF);
        if (codcf > 0)
        {
          const int indsped = get_int(F_INDSPED);
          const long codcont = lv_new_contract(codcf, indsped);
          if (codcont > 0)
            set(F_CODCONT, codcont);
        }
      }  
    }
    break;
  default:
    if (e==fe_modify && o.dlg()>500 && o.dlg() != F_CAUSLAVDESCRIG)
    {
      TSheet_field& ss = sfield(F_RIGHE);
      const short rowid = o.dlg()-400;
      const int index= ss.cid2index(rowid);
      const int sel=ss.selected();
      ss.row(sel).add(o.get(),index);
      ss.force_update(sel);

    }
    break;
  }

  return true;
}

TContratti_msk::TContratti_msk():TAutomask("lv0400a"), _post_contr(0)
{
}

class TContratti_app: public TRelation_application
{
	TContratti_msk* _msk;
	TRelation* _rel;

private:
  void save_rows(const TMask& m);
  void build_query(const TMask& m,TString& query) const;
  int find_art(TSheet_field& s,const TString& art) const;

protected:
	virtual TMask* get_mask (int mode) {return _msk; }
	virtual TRelation* get_relation() const {return _rel;}

  virtual bool user_create();
  virtual bool user_destroy();
  virtual void on_config_change();
  virtual bool get_next_key(TToken_string& key);
  virtual int read(TMask& m);
  virtual int write(const TMask& m);
  virtual int rewrite(const TMask& m);
  virtual bool protected_record(TRectype & rec);
  virtual bool remove();
  virtual void init_query_mode(TMask& m);
  virtual void init_insert_mode(TMask& m);
  bool elimina_planning(const long& codcont, const long& codcf) const;
  bool kill_planning (TISAM_recordset& selrighe) const;
};

bool TContratti_app:: user_create() 
{
  _rel=new TRelation (LF_LVCONDV);
  _msk= new TContratti_msk;

	TDate datasc(TODAY);
	if (esercizi().date2esc(datasc) == 0)
		return message_box("Attenzione non esiste l'esercizio corrispondente al %s", datasc.string());

	TSheet_field& ss=_msk->sfield(F_RIGHE);

	ss.set_auto_append();
  ss.set_append(false);

	return true;
}

bool TContratti_app:: user_destroy() 
{
   delete _msk;
   delete _rel;
   return true;
}

void TContratti_app:: on_config_change()
{
}

bool TContratti_app:: get_next_key(TToken_string& key)
{ 
  const long cliente=_msk->get_long(F_CODCF);
  if (cliente<=0) return false;
  key.add(F_CODCF);
  key.add(cliente);
  key.add(F_CODCONT);

  long codcont= lv_new_contract(cliente, _msk->get_int(F_INDSPED));
  key.add(codcont);

  return true; 
}



void TContratti_app:: build_query(const TMask& m,TString& query) const
{
  query="";
  query << "USE LVRCONDV\n"
        << "FROM CODCF="<<m.get(F_CODCF)<<" CODCONT="<<m.get(F_CODCONT)<<"\n"
        << "TO CODCF="<<m.get(F_CODCF)<<" CODCONT="<<m.get(F_CODCONT);
 
}

int TContratti_app:: read(TMask& m) 
{
  int err=TRelation_application::read(m);
  if(err==NOERR)
  {
    TString query; 
    build_query(m,query);
    TISAM_recordset righeset(query);
    const TRectype& rec=righeset.cursor()->curr();

    TSheet_field& righe=m.sfield(F_RIGHE);
    TMask& msk=righe.sheet_mask();
    righe.destroy();

    for (bool ok=righeset.move_first(); ok; ok=righeset.move_next())
    {
      TToken_string& row=righe.row(-1);
      FOR_EACH_MASK_FIELD(msk,i,f)
      {
        const TFieldref*fr=f->field();
        if (fr!= NULL)
          row.add(fr->read(rec),righe.cid2index(f->dlg()));  
      }
      righe.check_row(righe.items()-1,3);
    }
    righe.force_update();
  }
  return err;
}

int TContratti_app::find_art(TSheet_field& s,const TString& art) const
{
  int r=-1;
  for (r=s.items()-1;r>=0;r--)
  {
    const char* codart= s.row(r).get(0);
    if (art==codart)
      break;
  }
  return r;

}
void TContratti_app::save_rows(const TMask& m)
{
  TString query; 
  TSheet_field& righe=m.sfield(F_RIGHE);
  build_query(m,query);
  TISAM_recordset righeset(query);
  TLocalisamfile& file=righeset.cursor()->file();
  for (bool ok=righeset.move_first(); ok; ok=righeset.move_next())
  {
    const TString& art=righeset.get("CODART").as_string();
    if (find_art(righe,art)<0)
       file.remove();
  }

  TMask& msk=righe.sheet_mask();
  FOR_EACH_SHEET_ROW(righe,r,row)
  {
    file.zero();
    file.put("CODCF",m.get(F_CODCF));
    file.put("CODCONT",m.get(F_CODCONT));
    FOR_EACH_MASK_FIELD(msk,i,f)
    {
      const TFieldref*fr=f->field();
      if (fr!= NULL)
      {
        const int pos=righe.cid2index(f->dlg());
        fr->write(row->get(pos),file.curr());
      }
    }
    if (file.get("CODART").full()) 
      file.rewrite_write();
  }

}

void TContratti_app::init_query_mode(TMask& m)
{
  m.field(F_RAGSOC).enable(m.field(F_CODCF).enabled());

}

void TContratti_app::init_insert_mode(TMask& m)
{
  const long codcf = m.get_long(F_CODCF);
  const long indsp = m.get_int(F_INDSPED);
  const TDate oggi(TODAY);
  const long old_contr = lv_find_contract(codcf, indsp, oggi);
  const long cur_contr = m.get_long(F_CODCONT);
  if (old_contr > 0 && old_contr < cur_contr)
    m.set(F_PROPOSTA, "X");
}

int TContratti_app::write(const TMask& m)
{
  int err=TRelation_application::write(m);
  if(err==NOERR) 
  {
    save_rows(m);
    warning_box(TR("Ricordarsi di inserire i passaggi per planning"));
  }

  return err;
}
int TContratti_app::rewrite(const TMask& m)
{
  int err=TRelation_application::rewrite(m);
  if(err==NOERR) save_rows(m);
  return err;
}

bool TContratti_app::protected_record(TRectype & rec)
{
  TLaundry_contract cont(rec);
  return !cont.can_be_deleted();
}

bool TContratti_app::elimina_planning(const long& codcont, const long& codcf) const
{
  //creo il recordset
  TISAM_recordset selrighe("USE LVRCONSPLAN KEY 3\nFROM CODCF=#CODCF CODCONT=#CODCONT \nTO CODCF=#CODCF CODCONT=#CODCONT");
  
  //setto le variabili
  selrighe.set_var("#CODCF",codcf);
  selrighe.set_var("#CODCONT",codcont);
  
  //richiamo la funzione che effettivamente fa la cancellazione delle righe interessate
  kill_planning(selrighe);

  return true;
}

bool TContratti_app::kill_planning (TISAM_recordset& selrighe) const
{
  const TRecnotype righe = selrighe.items();
  if (righe > 0)
  {
    TProgind pi(righe, TR("Eliminazione planning in corso..."), true, true);
    TLocalisamfile& rplan = selrighe.cursor()->file();
    for (bool ok = selrighe.move_last(); ok; ok = selrighe.move_prev())
    {
	    if (!pi.addstatus(1))
		    break;
      rplan.remove();
    }    
  }
  return true;
}

bool TContratti_app::remove()
{
  bool ok=TRelation_application::remove();
  if(ok)
  {
    TString query; 
    build_query(*_msk,query);
    TISAM_recordset righeset(query);
    TLocalisamfile& file=righeset.cursor()->file();

    for (bool ok=righeset.move_first(); ok; ok=righeset.move_next())
    {
      file.remove();
    }

    elimina_planning(_msk->get_long(F_CODCONT),_msk->get_long(F_CODCF));
  }
  return ok;
}

int lv0400(int argc, char* argv[])
{
  TContratti_app app;
  app.run (argc,argv,TR("Gestione contratti"));
  return 0;
}