#include <automask.h>
#include <modaut.h>
#include <recarray.h>
#include <relapp.h>
#include <sheet.h>

#include "cespi.h"

#include "celib.h"
#include "collces.h"

#include "ce2300a.h"

/////////////////////////////////////////////////
// Ricerca per categoria su collces
/////////////////////////////////////////////////

class TCollces_sheet : public TBrowse_sheet
{ 
protected:
  virtual void get_row(long n, TToken_string& row);

public:
  TCollces_sheet(TCursor* cursor, TEdit_field& ef);
};

void TCollces_sheet::get_row(long n, TToken_string& row)
{
  TBrowse_sheet::get_row(n, row);
  const int gru = row.get_int(0);
  TString8 spe = row.get();
  switch(spe.len())
  {       
  case  1: spe.right_just(2); break;
  case  3: spe.insert(" "); break;
  default: break;
  }
  const int cat = row.get_int();
  const TString& desc = ditta_cespiti().categoria(gru, spe, cat).get("S0");
  row.add(desc, 3);
}

TCollces_sheet::TCollces_sheet(TCursor* cursor, TEdit_field& ef)
              : TBrowse_sheet(cursor, "CODGRUPPO|CODSPECIE|CODCAT|CODCAT", TR("Categorie"), 
                              HR("Gruppo|Specie|Categoria|Descrizione@70"), 0, ef, TToken_string())
{
}

/////////////////////////////////////////////////
// Maschera query
/////////////////////////////////////////////////

class TCesp2cg_qmask : public TAutomask
{ 
  TCursor* _curcoll;

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

public:
  TCesp2cg_qmask(TRelation* rel);
  virtual ~TCesp2cg_qmask();
};

bool TCesp2cg_qmask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
  switch (o.dlg())
  {
  case F_CODCAT:
   if (e == fe_button)
   {              
     TEdit_field& ef = (TEdit_field&)o;
     TCollces_sheet sht(_curcoll, ef);
     if (!o.empty())
     {
       TRectype& rec = _curcoll->curr();
       rec.zero();
       rec.put(COLLCES_CODGRUPPO, get(F_GRUPPO));
       rec.put(COLLCES_CODSPECIE, get(F_SPECIE));
       rec.put(COLLCES_CODCAT, o.get());
       long sel = _curcoll->read();
       sht.select(sel);
     }
     if (sht.run() == K_ENTER)
     { 
       TToken_string row = sht.row();
       o.set(row.get(2));
       set(F_DESCAT, row.get(3));
       send_key(K_ENTER, 0);
     }
   }
   break;
  case F_CODCAT2:
	case F_DESCAT:
    return ditta_cespiti().on_category_event(o, e, jolly);
  case F_IDCESPITE:
    if (e == fe_close)
    {
      const TRectype& cesp = cache().get(LF_CESPI, o.get());
      if (cesp.empty())
        return error_box(TR("Inserire un cespite valido"));
    }
    break;
 default:
   break;  
 }

  return TRUE;
}

TCesp2cg_qmask::TCesp2cg_qmask(TRelation* rel) : TAutomask("ce2300a")
{ 
  _curcoll = new TCursor(rel, "IDCESPITE=\"\"");
}

TCesp2cg_qmask::~TCesp2cg_qmask()
{
  delete _curcoll;
}

/////////////////////////////////////////////////
// Maschera principale
/////////////////////////////////////////////////

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

  void test_duplication(short g1, short g2);

public:
  TCesp2cg_emask() : TAutomask("ce2300b") { }
};

// Se i due gruppi-conti-sottoconti sono uguali azzera il primo
void TCesp2cg_emask::test_duplication(short g1, short g2)
{          
  TString16 s1, s2;
  for (int i = 0; i < 3; i++)
  {
    s1 << get(g1+i) << ' ';
    s2 << get(g2+i) << ' ';
  }
  if (!s1.blank() && s1 == s2)
  {
    warning_box(TR("Non si deve specificare lo stesso conto della riga precedente"));
    for (int i = 0; i < 4; i++)
      reset(g1+i);
  }
}

bool TCesp2cg_emask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
  switch (o.dlg())
  {
  case F_CODCAT:
  case F_CODCAT2:
    if (e == fe_init)
      return ditta_cespiti().on_category_event(o, e, jolly);
    break;
  case F_TIPO:
    if (e == fe_modify || e == fe_close)
    {
      const int tipo = field(F_IDCESPITE).empty() ? 1 : 2;
      set(F_COMPL, tipo == get_int(F_TIPO) ? "X" : "");
    }
    break;
  case F_QANT_S:  
    if (e == fe_modify || e == fe_close)
      test_duplication(F_QANT_G, F_QNOR_G);
    break;
  case F_QACC_S:
    if (e == fe_modify || e == fe_close)
    {
      test_duplication(F_QACC_G, F_QANT_G);
      test_duplication(F_QACC_G, F_QNOR_G);
    }
    break;
  case F_FANT_S:  
    if (e == fe_modify || e == fe_close)
      test_duplication(F_FANT_G, F_FNOR_G);
    break;
  case F_FACC_S:
    if (e == fe_modify || e == fe_close)
    {
      test_duplication(F_FACC_G, F_FANT_G);
      test_duplication(F_FACC_G, F_FNOR_G);
    }
    break;
  default:
    break;
  }
  return TRUE;
}

/////////////////////////////////////////////////
// Programma principale
/////////////////////////////////////////////////

class TCesp2cg : public TRelation_application
{ 
  TRelation* _rel;
  TMask* _qmsk;
  TMask* _emsk;

protected:
  virtual bool changing_mask(int mode) { return TRUE; }
  virtual TMask* get_mask(int mode);
  virtual TRelation* get_relation() const { return _rel; }
  
  virtual void init_query_mode(TMask& m);
  virtual void init_query_insert_mode(TMask& m);
  virtual void init_insert_mode(TMask& m);
  virtual void init_modify_mode(TMask& m);
  
  virtual bool user_create();
  virtual bool user_destroy();

public:                       
  const TRectype& curr_cat(const TMask& m) const;
  void init_mask(TMask& m) const;
  void copy_cat(TMask& m, const TRectype& cat) const;

  TCesp2cg() : _rel(NULL), _qmsk(NULL), _emsk(NULL) { }
};

bool TCesp2cg::user_create()
{  
  if (!has_module(CGAUT))
  {        
    error_box(TR("� necessario attivare il modulo contabilit�"));
    return FALSE;
  }
  _rel = new TRelation(LF_COLLCES);
  _qmsk = new TCesp2cg_qmask(_rel);
  _emsk = new TCesp2cg_emask;
  
  return TRUE;
}

TMask* TCesp2cg::get_mask(int mode)
{  
  return (mode == MODE_QUERY || mode == MODE_QUERYINS) ? _qmsk : _emsk;
}

void TCesp2cg::init_query_mode(TMask& m)
{
  ditta_cespiti().init_mask(m);
  m.show(-1);
  m.hide(-2);
}

void TCesp2cg::init_query_insert_mode(TMask& m)
{
  m.hide(-1);
  m.show(-2);
}

// Compia nella maschera corrente i dati prelevati dalla categoria 
// sovrascrivendo quelli del cespite.
void TCesp2cg::copy_cat(TMask& m, const TRectype& cat) const
{
  const TRectype saverec = _rel->curr();  // Salvo record principale e ...
  _rel->curr() = cat;                     // ... gli scrivo sopra i dati della categoria
  // Carico tutti i campi a partire dalla quota normale in poi
  for (int i = m.id2pos(F_QNOR_G); i < m.fields(); i++)
  {
    TMask_field& f = m.fld(i);
    if (f.is_edit())
      ((TLoadable_field&)f).autoload(*_rel);
  }
  _rel->curr() = saverec;                 // Ripristino record principale
}

const TRectype& TCesp2cg::curr_cat(const TMask& m) const
{
  const int gru = m.get_int(F_GRUPPO);
  const char* spe = m.get(F_SPECIE);
  int cat = m.get_int(F_CODCAT);
  if (cat == 0)
    cat = cache().get(LF_CESPI, m.get(F_IDCESPITE)).get_int(CESPI_CODCAT);
  return ditta_cespiti().categoria(gru, spe, cat);
}

void TCesp2cg::init_mask(TMask& m) const
{
  const int ese = m.get_int(F_ESERCIZIO);
  const int gru = m.get_int(F_GRUPPO);
  const char* spe = m.get(F_SPECIE);
  ditta_cespiti().set_attivita(ese, gru, spe);

  const TRectype& cac = curr_cat(m);
  const bool materiali = cac.get_int("I0") == 0;
  m.field(F_FNOR_S).check_type(materiali ? CHECK_REQUIRED : CHECK_NORMAL);
  m.field(F_FNOR_D).check_type(materiali ? CHECK_REQUIRED : CHECK_NORMAL);
  m.enable(-3, materiali);
}


void TCesp2cg::init_insert_mode(TMask& m)
{ 
  init_mask(m);
  
  // Valori preimpostati "quasi" sempre buoni :-)
  m.set(F_TIPO, 1);
  
  const TString& idcespite = m.get(F_IDCESPITE);
  if (!idcespite.blank())
  {
    const int gru = m.get_int(F_GRUPPO);
    const char* spe = m.get(F_SPECIE);
    const int cat = cache().get(LF_CESPI, idcespite).get_int(CESPI_CODCAT);
    TToken_string key; key.add(gru); key.add(spe); key.add(cat);
    const TRectype& coll = cache().get(LF_COLLCES, key);
    if (coll.get_bool(COLLCES_COMPL))
    {
      m.set(F_TIPO, 1);
      copy_cat(m, coll);
    }
    else
      m.set(F_TIPO, 2);
  }
}

void TCesp2cg::init_modify_mode(TMask& m)
{
  init_mask(m);
  
  const TString& idcespite = m.get(F_IDCESPITE);
  if (!idcespite.blank())
  {  
    if (!m.get_bool(F_COMPL))
    {
      const int gru = m.get_int(F_GRUPPO);
      const char* spe = m.get(F_SPECIE);
      const int cat = cache().get(LF_CESPI, idcespite).get_int(CESPI_CODCAT);
      TToken_string key; key.add(gru); key.add(spe); key.add(cat);
      const TRectype& coll = cache().get(LF_COLLCES, key);
      if (coll.get_bool(COLLCES_COMPL))
      {      
        m.set(F_TIPO, 1);
        copy_cat(m, coll);
      }
      else
        m.set(F_TIPO, 2);
    }
  }
}

bool TCesp2cg::user_destroy()
{             
  delete _emsk;
  delete _qmsk;
  delete _rel;
  return TRUE;
}

int ce2300(int argc, char* argv[])
{
  TCesp2cg a;
  a.run(argc, argv, TR("Collegamenti contabili"));
  return 0;
}