#include <currency.h>
#include <defmask.h>
#include <modaut.h>
#include <recarray.h>
#include <relapp.h>

#include "in0.h"
#include "in0500a.h"
#include "inlib01.h"
#include "../cg/cg2103.h"

#include <mov.h>

///////////////////////////////////////////////////////////
// TImmissione_mask
///////////////////////////////////////////////////////////

class TImmissione_mask : public TIntra_mask
{
private:
  bool _caus_valintra;

protected:
  virtual short type_field() const { return F_TIPO_MOV; }
  virtual int anno() const { return get_date(F_DATA_REG).year(); }

protected:
  virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
  bool on_sheet_event(TSheet_field& s, TField_event e, int row);
  bool on_sheet_field_event(TOperable_field& o, TField_event e, long jolly);
  virtual bool on_key(KEY k);

  void enable_valuta();

public:
  TImmissione_mask();
  virtual ~TImmissione_mask() { }
};

///////////////////////////////////////////////////////////
// Applicazione principale
///////////////////////////////////////////////////////////

class TImmissione_intra : public TRelation_application
{
  TRelation* _rel;
  TImmissione_mask* _msk;

protected:
  virtual bool user_create();
  virtual TRelation* get_relation() const { return _rel; }
  virtual TMask* get_mask(int) { return _msk; }
  virtual bool changing_mask(int mode) { return FALSE; }
  virtual bool user_destroy();
  virtual bool protected_record(TRectype & rec);

public:
};

TImmissione_intra& app() { return (TImmissione_intra&)main_app(); }

///////////////////////////////////////////////////////////
// TImmissione_mask
///////////////////////////////////////////////////////////

void TImmissione_mask::enable_valuta()
{
  const bool gestval = _caus_valintra || tipo() == 'A';
  enable(F_VALUTA, gestval);
  enable(F_CAMBIO, gestval);
}

bool TImmissione_mask::on_key(KEY k)
{
  if (k == K_CTRL + '+')
  {
    TSheet_field& s = sfield(F_RIGHE);
  }
  return TMask::on_key(k);
}

bool TImmissione_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
  const short id = o.dlg();
  switch (id)
  {
  case F_NUM_REG:
    if (e == fe_modify || e == fe_init)
    { 
      _caus_valintra = TRUE; // Default value
      if (app().has_module(CGAUT, CHK_DONGLE))
      {
        const TString& numreg = o.get();
        if (numreg.not_empty())
        {
          const TRectype& mov = cache().get(LF_MOV, numreg);   
          if (mov.empty())
          {
            if (e == fe_modify && !app().is_transaction())
              warning_box(FR("Il movimento contabile %s non esiste"), (const char*)numreg);
          }
          else
          {   
            set(F_NUM_DOC, mov.get(MOV_NUMDOC));
            set(F_DATA_DOC, mov.get(MOV_DATADOC));
            set(F_DATA_INT, mov.get(MOV_DATACOMPI));

            const TString& caus = mov.get(MOV_CODCAUS);
            const TCausale c(caus);
            if (!c.intra())
              return error_box(FR("La causale %s del movimento contabile %s non e' intracomunitaria"), 
                               (const char*)caus, (const char*)numreg);
            _caus_valintra = c.valintra();
          }
        }
      }
      enable_valuta();
    }
    break;
  case F_TIPO_MOV:
    if (e == fe_init || e == fe_modify)
    {
      TSheet_field& s = sfield(F_RIGHE);
      TMask& m = s.sheet_mask();
      const bool acq = tipo() == 'A';
      m.show(-GR_ACQUISTI, acq);    // Mostra i gruppi di campi
      m.show(-GR_CESSIONI, !acq);   // consoni al tipo movimento
      s.enable_column(F_PAESE_ORIG, acq);
      s.set_column_header(F_PAESE, acq ? TR("Paese\nProv.") : TR("Paese\nDest."));
      s.set_column_header(F_PROV, acq ? TR("Provincia\nDest.") : TR("Provincia\nOrig."));
      
      TString key ; key << main_app().get_firm();
      const bool req = frequenza(anno()) == 'M' && !cache().get(LF_NDITTE, key).get_bool("NONOBBSTAT");
      CheckType chk = req ? CHECK_REQUIRED : CHECK_NORMAL;
      
      m.field(F_VALORE_STAT).check_type(chk);
      m.field(F_CONSEGNA).check_type(chk);
      m.field(F_TRASPORTO).check_type(chk);
      
      chk = frequenza(anno()) == 'M' ? CHECK_REQUIRED : CHECK_NORMAL;
      m.field(F_PAESE).check_type(chk);
      m.field(F_PAESE_ORIG).check_type(chk);
      m.field(F_PROV).check_type(chk);
      
      s.force_update();
      if (e == fe_modify)
        enable_valuta();
    }                                                                      
    break;
  case F_CLIFO:
    if (e == fe_modify)
    {
      TEdit_field& valu = efield(F_VALUTA);
      if (valu.active())
      {
        const TRectype& curr = efield(F_CLIFO).browse()->cursor()->curr();
        TString16 codval = curr.get("VALINTRA");
        if (codval.empty())
          codval = curr.get("CODVAL");
        set(F_VALUTA, codval, TRUE);
      }
    }  
    break;
  case F_VALUTA:
    if (e == fe_init || e == fe_modify)
    {
      TEdit_field& cambio = efield(F_CAMBIO);
      if (o.empty())
        cambio.reset();
      else
      {
        const TString& s = cache().get("%VAL", o.get(), "S4");
        cambio.set(s);
      }
      TSheet_field& s = sfield(F_RIGHE);
      const bool enable_val = is_true_value(get(F_VALUTA));
      const int col = s.cid2index(F_AMM_VALUTA);

      s.enable_column(col, enable_val);
      const int rows = s.items();
      for (int i = 0; i < rows; i++)
      {
        s.enable_cell(i, col, enable_val);
        TToken_string & r = s.row(i);
        if (!enable_val)
          r.add("", col);
      }                                              
      s.force_update();
    }
    break;
  case F_TOT_DOC:
    if (e == fe_close)
    {      
      const real totdoc = get_real(F_TOT_DOC);
      const real totdocimm = get_real(F_TOT_IMM);
      
      if (totdoc != totdocimm)                                                                                           
      {
        const TString str_totdoc(totdoc.string());
        return error_box(FR("Totale documento (%s) diverso dal totale documento immesso(%s)"), (const char *)str_totdoc, (const char *)totdocimm.string());
      }
    }
    break;
  case F_AMM_LIRE:
    if (e == fe_modify)
    {
      TMask& m = o.mask();     
      TSheet_field& s = sfield(F_RIGHE);
      TCurrency curr(real(o.get()));

      const bool enable_val = is_true_value(get(F_VALUTA));
      m.enable(F_AMM_VALUTA, enable_val);
      if (!enable_val)
        m.reset(F_AMM_VALUTA);
      else
        if (!o.empty() && m.get_real(F_AMM_VALUTA).is_zero())
        {
          curr.change_value(get(F_VALUTA), get_real(F_CAMBIO));
          m.set(F_AMM_VALUTA, curr, TRUE);
        }
      s.update_row(s.selected());
      s.force_update(s.selected());
    }
    break;
  case F_AMM_VALUTA:
    if (e == fe_modify)
    {
      TMask& m = o.mask();
      if (!o.empty() && m.get_real(F_AMM_LIRE).is_zero())
      {
        TCurrency curr(real(o.get()), get(F_VALUTA), get_real(F_CAMBIO));
        curr.change_to_firm_val();
        m.set(F_AMM_LIRE, curr, TRUE);
      }
    }
    break;
  case F_RIGHE:
    return on_sheet_event((TSheet_field&)o, e, int(jolly));
  case R_RIEPILOGHI:
    if (e == fe_button)                  
      ::genera_riepiloghi(tipo(), anno(), date2periodo(get_date(F_DATA_REG)));
    break;
  default:
    if (id < F_DITTA && jolly == 1)
      return on_sheet_field_event(o, e, jolly);
    break;
  }
  return TIntra_mask::on_field_event(o, e, jolly);
}

bool TImmissione_mask::on_sheet_event(TSheet_field& s, TField_event e, int row)
{ 
  if (e == se_notify_add)
  {
    const bool enable_val = is_true_value(get(F_VALUTA)); 
    if (!enable_val)
    {
      const int col = s.cid2index(F_AMM_VALUTA); 
      row = s.items()-1;
      s.enable_cell(row, col, enable_val);
      s.force_update(row);
    }
  }
  else
    if (e == se_notify_modify)
    {
      real amm_lire;
      int rows = s.items();
      
      for (int i = 0; i < rows; i++)
      {
        TToken_string & r = s.row(i);
        const real val = r.get(s.cid2index(F_AMM_LIRE));
        
        amm_lire += val;
      }                                              
      s.mask().set(F_TOT_IMM, amm_lire);
    }
  return TRUE;
}

bool TImmissione_mask::on_sheet_field_event(TOperable_field& o, TField_event e, long jolly)
{
  switch (o.dlg())
  {
  case F_NOMENCLATURA2:
    if (e == fe_modify)
    {
      TString4 str; str = o.get();
      if (str.len() != 2)
      {
        str.format("%02d", atoi(str));
        o.set(str);
      }
    }
  case F_NOMENCLATURA1:
  case F_NOMENCLATURA3:
    if (e == fe_close)
    {
      if (frequenza() != 'A')
      {
        TMask& m = o.mask();
        TString16 key; key << m.get(F_NOMENCLATURA1) << m.get(F_NOMENCLATURA2) << m.get(F_NOMENCLATURA3);
        if (key.empty())
          return error_box(TR("La nomenclatura combinata e' obbligatoria"));
      }
    }   
    else
      if (e == fe_modify)
      {    
        TMask& m = o.mask();
        if (!o.empty())
        {
          TString16 key; key << m.get(F_NOMENCLATURA1) << m.get(F_NOMENCLATURA2) << m.get(F_NOMENCLATURA3);
          const TRectype& nom = cache().get("%NOC", key);
          
          m.set(F_UMS, nom.get("S5"), TRUE);
          
          bool req = frequenza(anno()) == 'M'; 
          if (req) // Solo la frequenza mensile puo' obbligare
          {
            const char obb = nom.get_char("S4");
            req = obb == 'E' || obb == tipo();
          }              
          const CheckType chk = req ? CHECK_REQUIRED : CHECK_NORMAL;
          m.field(F_MASSA_KG).check_type(chk);
          m.field(F_UMS).check_type(chk);
          m.field(F_MASSA_UMS).check_type(chk);
        }
        else
        { 
          m.set(F_UMS, "", TRUE);
        }
      }
    break;
  default:
    break;
  }
  return TRUE;
}

TImmissione_mask::TImmissione_mask() 
                : TIntra_mask("in0500a") 
{ }


///////////////////////////////////////////////////////////
// Applicazione principale
///////////////////////////////////////////////////////////

bool TImmissione_intra::protected_record(TRectype & rec)
{                                                    
  const char tipo = rec.get_char("TIPOMOV");
  const TDate d(rec.get("DATAREG"));
  const int periodo = _msk->date2periodo(d);
  
  bool prot = is_riepilogo(tipo, d.year(), periodo) &&
              !yesno_box(TR("Attenzione: il movimento appartiene ad un riepilogo esistente,:\nSi desidera poterlo modificare ugualmente?"));
  _msk->enable(DLG_SAVEREC, !prot);
  return prot;
}

bool TImmissione_intra::user_create()
{
  open_files(LF_TABCOM, LF_TAB, LF_CLIFO, LF_MOV, 
             LF_INTRA, LF_RINTRA, 0);
  _rel = new TRelation(LF_INTRA);
  _msk = new TImmissione_mask;
  return TRUE;
}

bool TImmissione_intra::user_destroy()
{
  delete _msk;
  delete _rel;
  return TRUE;
}

int in0500(int argc, char* argv[])
{
  TImmissione_intra a;
  a.run(argc, argv, TR("Movimenti INTRA"));
  return 0;
}