#include <prefix.h>
#include <recarray.h>
#include <sheet.h>
#include <diction.h>

#include "celib.h"

#include "../cg/cglib01.h"

///////////////////////////////////////////////////////////
// Ditta cespiti
///////////////////////////////////////////////////////////

// Carica i dati relativi alla ditta corrente dei cespiti
void TDitta_cespiti::load_default()
{
  _ditta = prefix().get_codditta();
  
  TConfig dit(CONFIG_DITTA);
  _esercizio = dit.get_int("CODESCORR");
  if (_esercizio <= 0)
  {
    const TDate oggi(TODAY);
    _esercizio = oggi.year();
  }
  
  _gruppo = dit.get("GRUPPOCORR");
  
  TString16 str = dit.get("SPECIECORR"); 
  str.strip("\"");
  _specie = str;

  _data_primi_ricavi = dit.get("CADTR");
  _anno_tuir = dit.get_int("CATSU");  
  if (_anno_tuir == 0 || _anno_tuir == 1) // Demenzialmente può essere memorizzato come 0 o 1
    _anno_tuir += 1988;
  _amm_prop = dit.get_bool("AMMPROP");  

  load_records();
}

void TDitta_cespiti::update_when_needed()
{
  if (_ditta != prefix().get_codditta())
    load_default();
}

void TDitta_cespiti::load_records()
{ 
  TString16 str;
  str.format("%04d", _esercizio);
  _cce = cache().get("CCE", str);
  
  str.format("%04d%2s%4s", _esercizio, (const char*)_gruppo, (const char*)_specie);
  _ccb = cache().get("CCB", str);
}

void TDitta_cespiti::set_attivita(int esercizio, int gruppo, const char* specie)
{
  if (esercizio <= 0)
  {
    const TDate oggi(TODAY);
    _esercizio = oggi.year();
  }
  else
    _esercizio = esercizio;
  
  if (gruppo > 0)  
    _gruppo.format("%02d", gruppo);
  if (specie && *specie)  
    _specie.format("%-4s", (const char*)specie);
  
  TConfig dit(CONFIG_DITTA, "ce");
  dit.set("CODESCORR", _esercizio);
  dit.set("GRUPPOCORR", _gruppo);
  TString16 str; str << '"' << _specie << '"';
  dit.set("SPECIECORR", str);

  _data_primi_ricavi = dit.get("CADTR");
  _anno_tuir = dit.get_int("CATSU");
  if (_anno_tuir == 0 || _anno_tuir == 1) // Demenzialmente può essere memorizzato come 0 o 1
    _anno_tuir += 1988;
  
  _ditta = prefix().get_codditta();
  
  load_records();
}

const TRectype& TDitta_cespiti::get_attivita() const
{                       
  return _ccb;
}

const TRectype& TDitta_cespiti::get_attivita(int& esercizio, TString& gruppo, TString& specie) const
{                       
  esercizio = _esercizio;
  gruppo = _gruppo;
  specie = _specie;
  return get_attivita();
}

bool TDitta_cespiti::bollato_stampato() const
{
  return _ccb.get_bool("B1");
}

int TDitta_cespiti::esercizio_corrente(TDate& inies, TDate& fines) const
{
  TEsercizi_contabili esc;
  const TEsercizio& e = esc[_esercizio];
  inies = e.inizio();
  fines = e.fine();
  return _esercizio;
}

void TDitta_cespiti::init_mask(TMask& m)
{   
  update_when_needed();

  TBit_array found;
  bool started = FALSE;
  bool finished = FALSE;
  for (int i = 0; !finished && i < 20 && i < m.fields(); i++)
  {
    TMask_field& f = m.fld(i);
    if (started)
    {
      switch (f.size())
      {
      case 4:
        if (f.is_kind_of(CLASS_REAL_FIELD))
        {   
          if (!found[1]) // Non ho ancora trovato l'esercizio 
          {
            f.set(_esercizio);
            f.check();
            found.set(1, TRUE);
          }
        } else
        if (f.is_edit())
        {
          if (found[4] && !found[5])  // Ho trovato gruppo ma non specie
          {
            f.set(_specie);
            f.check();
            found.set(5); 
            finished = TRUE;
          }
        }
        break;
      case 2:
        if (!found[4] && f.is_kind_of(CLASS_REAL_FIELD)) // Non ho ancora trovato il gruppo
        {     
          f.set(_gruppo);
          found.set(4);
        }
        break;
      default:
        if (f.is_kind_of(CLASS_GROUPBOX_FIELD))
          finished = TRUE;
        break;
      }
    }
    else
      started = f.dlg() <= 0 && f.class_id() == CLASS_GROUPBOX_FIELD;
  }
  CHECK(started && found.ones(), "Maschera in formato scandaloso");
}

// Arrotonda un numero in base ai parametri ditta
void TDitta_cespiti::arrotonda(real& n) const
{
  const char tipo = _cce.get_char("S6");
  const int dec = TCurrency::get_firm_dec();
  switch (tipo)
  {
  case '+': n.ceil(dec); break;
  case '-': n.floor(dec); break;
  default : n.round(dec); break;
  }
} 

bool TDitta_cespiti::professionista() const
{
  return _cce.get_bool("B0");
}

bool TDitta_cespiti::esercizio_costituzione() const
{
  return _cce.get_bool("B1");
}

real TDitta_cespiti::coefficiente_durata_esercizio() const
{
  return _cce.get_real("S5");
}


bool TDitta_cespiti::rinvio_ammortamento_ai_primi_ricavi() const
{
  return _cce.get_bool("B2");
}

bool TDitta_cespiti::ammortamento_parti_vendute() const
{
  return _cce.get_bool("B3");
}

bool TDitta_cespiti::ragguaglio_ammortamenti_parti_vendute() const
{
  return _cce.get_bool("B4");
}

bool TDitta_cespiti::esente_art14() const
{
  return _cce.get_bool("B7");
}

const TRectype& TDitta_cespiti::categoria(int gr, const char* sp, int ca) const
{
  TString16 key;
  if (ca >= 41)
    key.format("      %02d", ca);    
  else
  {
    if (gr <= 0) 
      gr = atoi(_gruppo);
    if (sp == NULL || *sp < ' ')
      sp = _specie;
    key.format("%02d%-4s%02d", gr, sp, ca);    
  }
  const TRectype& cac = cache().get("%CAC", key);
  return cac;
}

static TString8 _cac_filter;
static bool cac_filter_func(const TRelation* rel)
{
  const TString& grsp = rel->curr().get("CODTAB");
  if (grsp[0] == ' ')
    return TRUE;
  return _cac_filter.compare(grsp, 6) == 0;
}

bool TDitta_cespiti::on_category_event(TOperable_field& o, TField_event e, long jolly)
{
  if (e != fe_init && e != fe_modify && e != fe_button && e != fe_close)
    return TRUE;

  TEdit_field& fld = (TEdit_field&)o;
  const bool by_code = fld.is_kind_of(CLASS_REAL_FIELD);

  TOperable_field* fgrp = fld.driver(0);
  TOperable_field* fspe = fld.driver(1);
  
  int gruppo = fgrp ? atoi(fgrp->get()) : 0;
  TString4 specie = fspe ? (const char*)fspe->get() : "";
  if (gruppo <= 0 || specie.blank())
  {                
    int anno;
    TString4 sg, ss;
    get_attivita(anno, sg, ss);
    if (gruppo <= 0) gruppo = atoi(sg);
    if (specie.blank()) specie = ss;
  }
  
  if (e == fe_button)
  {
    const char* fields = by_code ? "CODTAB[7,8]|S0|I0" : "S0|CODTAB[7,8]|I0";
    const char* header = by_code ? HR("Categoria|Descrizione@60|Tipo beni") : HR("Descrizione@60|Categoria|Tipo beni");
    const char* sorter = by_code ? "CODTAB[7,8]" : "S0";
    
    TRelation rel("%CAC");  
    TSorted_cursor cur(&rel, sorter, "", by_code ? 1 : 2);
    _cac_filter.format("%02d%-4s", gruppo, (const char*)specie);
    cur.set_filterfunction(cac_filter_func);
    
    long recno = 0L;
    if (!fld.empty())
    {
      TRectype& rec = rel.curr();
      rec.zero();
      if (by_code)
      {
        TString8 key = fld.get();  
        key.right_just(8);
        rec.put("CODTAB", key);
      }
      else  
        rec.put("S0", fld.get());
      recno = cur.read();
    }
    TCursor_sheet sht(&cur, fields, TR("Categorie dei cespiti"), header, 0, 1);
    sht.select(recno);
    if (sht.run() == K_ENTER)
    {
      TMask& m = fld.mask();
      const int pos = m.id2pos(fld.dlg());
      TMask_field& fout = m.fld(pos + (by_code ? +1 : -1));
      TToken_string& row = sht.row();
      fld.set(row.get(0));
      fout.set(row.get(1));
    }
  } else
  if ((e == fe_init || e == fe_modify) && by_code)
  {               
    const int cat = atoi(fld.get());
    TString desc;
    if (cat > 0)
    {
      const TRectype& cac = categoria(gruppo, specie, cat);
      if (!cac.empty())
        desc = cac.get("S0");
    }
    TMask& m = fld.mask();
    const int pos = m.id2pos(fld.dlg());
    TMask_field& fout = m.fld(pos + (by_code ? +1 : -1));
    fout.set(desc);
    fout.on_hit();
  } else
  if (e == fe_close && by_code && !o.empty())
  {
    const int cat = atoi(o.get());
    const TRectype& cac = categoria(gruppo, specie, cat);
    if (cac.empty())
      return fld.error_box(fld.get_warning());
  }
  
  return TRUE;
}
                     
// Inizializza una ditta cespiti vuota
TDitta_cespiti::TDitta_cespiti() : _cce(LF_TAB), _ccb(LF_TAB)
{
  load_default();
}

// Ritorna la ditta cespiti corrente 
// Creandola la prima volta
TDitta_cespiti& ditta_cespiti()
{  
  static TDitta_cespiti* _firm = NULL;
  if (_firm == NULL)
    _firm = new TDitta_cespiti;
  return *_firm;  
}

///////////////////////////////////////////////////////////
// Form cespiti
///////////////////////////////////////////////////////////

bool TForm_cespiti::validate(TForm_item& fld, TToken_string& val)
{ 
  const TString16 code = val.get(0);
  if (code == "_DESCAT")
  {
    const TString8 fgr = val.get();
    const TString8 fsp = val.get();
    const TString8 fca = val.get();
    
    const int gruppo = atoi(fld.find_field(fgr).get());
    const char* specie = fld.find_field(fsp).get();
    const int categoria = atoi(fld.find_field(fca).get());
    const TRectype& cac = ditta_cespiti().categoria(gruppo, specie, categoria);
    fld.set(cac.get("S0"));
    return TRUE;
  }
  return TForm::validate(fld,val);
}

TForm_cespiti::TForm_cespiti(const char* name) : TForm(name)
{
}

///////////////////////////////////////////////////////////
// Utility varie
///////////////////////////////////////////////////////////

// Controlla se i campi sono tutti vuoti
// Cerified 99%
bool null_fields(const TRectype& rec, const char* fld0, const char* fld1, const char* fld2,
                 const char* fld3, const char* fld4, const char* fld5,
                 const char* fld6, const char* fld7, const char* fld8)
{   
  if (!rec.get_real(fld0).is_zero())
    return FALSE;
  if (!rec.get_real(fld1).is_zero())
    return FALSE;
  if (fld2 && *fld2 && !rec.get_real(fld2).is_zero()) 
    return FALSE;
  if (fld3 && *fld3 && !rec.get_real(fld3).is_zero()) 
    return FALSE;
  if (fld4 && *fld4 && !rec.get_real(fld4).is_zero()) 
    return FALSE;
  if (fld5 && *fld5 && !rec.get_real(fld5).is_zero()) 
    return FALSE;
  if (fld6 && *fld6 && !rec.get_real(fld6).is_zero()) 
    return FALSE;
  if (fld7 && *fld7 && !rec.get_real(fld7).is_zero()) 
    return FALSE;
  if (fld8 && *fld8 && !rec.get_real(fld8).is_zero()) 
    return FALSE;

  return TRUE;
}