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

#include "cg0.h"
#include "cg0100.h"

#include <pconti.h>
#include <saldi.h>

#define ATTIVITA 1
#define PASSIVITA 2
#define COSTI 3
#define RICAVI 4
#define ORDINE 5

class TPianoconti_app : public TRelation_application
{
  TMask* _msk;
  TRelation *_rel;
  bool _pcon_com;

  bool user_create();
  bool user_destroy();
  virtual TMask* get_mask(int mode) {return _msk;}
  virtual bool changing_mask(int mode) {return FALSE;}
  virtual bool protected_record(TRectype &rec);
  virtual void init_query_mode(TMask& m);
  virtual void init_insert_mode(TMask& m);
  virtual void init_modify_mode(TMask& m) {init_insert_mode(m);}
  virtual int write(const TMask& m);
  virtual int rewrite(const TMask & m);
  virtual int read(TMask& m);
  virtual void on_firm_change();

public:
  // @cmember Disabilita la verifica del modulo : essendo una anagrafica, va sempre abilitata
  virtual bool check_autorization() const 
  {return FALSE;}
  virtual TRelation* get_relation() const {return _rel;}
  TPianoconti_app() : _pcon_com(FALSE) {}
};
HIDDEN inline TPianoconti_app & app() { return (TPianoconti_app &) main_app();}


int TPianoconti_app::read(TMask& m) 

{
  const TRelation *r = get_relation();
  m.autoload(*r);
  if (m.get(FLD_CM1_LETTIVD).empty())
  {
    int sezivd = m.get_int(FLD_CM1_SEZIVD);
    if (sezivd == 1 || sezivd == 2)
      m.set(FLD_CM1_SEZIVD, sezivd + 5);
  }
  if (m.get(FLD_CM1_LETTIVDOPP).empty())
  {
    int sezivd = m.get_int(FLD_CM1_SEZIVDOPP);
    if (sezivd == 1 || sezivd == 2)
      m.set(FLD_CM1_SEZIVDOPP, sezivd + 5);
  }
  return NOERR;
}

int TPianoconti_app::rewrite(const TMask& m) 
{
  TString16 sez;

  TRelation *r = get_relation();
  m.autosave(*r);

  if (!m.field(FLD_CM1_CODTABANALISI).enabled())
    r->curr().zero(PCN_CODCBL);

  int sezivd = m.get_int(FLD_CM1_SEZIVD);
  if (sezivd == 6 || sezivd == 7)
  {
    sez.format("%d", sezivd - 5);
    r->lfile().put(PCN_SEZIVD, sez);
  }         
  sezivd = m.get_int(FLD_CM1_SEZIVDOPP);
  if (sezivd == 6 || sezivd == 7)
  {
    sez.format("%d", sezivd - 5);
    r->lfile().put(PCN_SEZIVDOPP, sez);
  }         
  const int err = r->rewrite();
  return err;
}

int TPianoconti_app::write(const TMask& m) 
{
  TString16 sez;

  TRelation *r = get_relation();
  m.autosave(*r);

  if (!m.field(FLD_CM1_CODTABANALISI).enabled())
    r->curr().zero(PCN_CODCBL);

  int sezivd = m.get_int(FLD_CM1_SEZIVD);
  if (sezivd == 6 || sezivd == 7)
  {
    sez.format("%d", sezivd - 5);
    r->lfile().put(PCN_SEZIVD, sez);
  }
  sezivd = m.get_int(FLD_CM1_SEZIVDOPP);
  if (sezivd == 6 || sezivd == 7)
  {
    sez.format("%d", sezivd - 5);
    r->lfile().put(PCN_SEZIVDOPP, sez);
  }
  
  return r->write();
}

// Controlla se puo' essere effettuata la cancellazione di un conto
void TPianoconti_app::on_firm_change()
{
  TDir d;
  d.get(LF_PCON, _nolock, _nordir, _sysdirop);
  _pcon_com = d.is_com();
}

bool TPianoconti_app::protected_record(TRectype &rec)
{                           
  if (!_pcon_com )
  {
    TMask* m = get_mask(MODE_MOD);
    const int gruppo = m->get_int(FLD_CM1_GRUPPO);
    const int conto = m->get_int(FLD_CM1_CONTO);
    const long sottoc = m->get_long(FLD_CM1_SOTTOCONTO);
  
    // Se e' un sottoconto posso cancellarlo se non esistono saldi
    if ((gruppo != 0) && (conto != 0) && (sottoc != 0))
    {
			TLocalisamfile saldi(LF_SALDI);
      
      saldi.setkey(2);
			saldi.put(PCN_GRUPPO, gruppo);
      saldi.put(PCN_CONTO, conto);
      saldi.put(PCN_SOTTOCONTO, sottoc);
      saldi.read(_isgteq);
      return saldi.good() &&
             gruppo == saldi.get_int(PCN_GRUPPO) && conto == saldi.get_int(PCN_CONTO) && sottoc == saldi.get_long(PCN_SOTTOCONTO) &&
             (saldi.get_real(SLD_SALDO) != ZERO || saldi.get_real(SLD_PDARE) != ZERO ||
              saldi.get_real(SLD_PAVERE) != ZERO || saldi.get_real(SLD_SALDOFIN) != ZERO ||
              saldi.get_real(SLD_PDAREPRO) != ZERO || saldi.get_real(SLD_PAVEREPRO) != ZERO);
    }
    else
    {
	    TLocalisamfile& pconti = _rel->lfile();
  
			get_relation()->save_status();
      pconti.zero() ;
      pconti.put(PCN_GRUPPO, gruppo);
      // Se e' un conto controllo se ha dei sottoconti
      if (conto != 0)
        pconti.put(PCN_CONTO, conto);
      TRectype rec1(pconti.curr());
    
      pconti.setkey(1) ;
      pconti.read();
      pconti.next();
      bool  prot = (pconti.good() && (pconti.curr() == rec1));
      get_relation()->restore_status();
      return prot;
    }
  }
  return FALSE;
}

void TPianoconti_app::init_query_mode(TMask& m)
{
  m.show_default();
  m.hide(-3);
}

HIDDEN bool tmcf_handler(TMask_field& f, KEY key)
{     
  if (f.active() && key == K_SPACE)
  {
    TMask& m = f.mask();
    const int conto = atoi(m.get(FLD_CM1_CONTO));
    const long sottoc = atol(m.get(FLD_CM1_SOTTOCONTO));
    const bool enable_sezsaldi = (sottoc != 0) || (sottoc == 0 && conto != 0 && m.get(FLD_CM1_TMCF).not_empty());

    m.show(FLD_CM2_SEZSALDI, enable_sezsaldi);
  }
  return TRUE;
}

void TPianoconti_app::init_insert_mode(TMask& m)
{
  const int gruppo = m.get_int(FLD_CM1_GRUPPO);
  const int conto = m.get_int(FLD_CM1_CONTO);
  const long sottoc = m.get_long(FLD_CM1_SOTTOCONTO);
  bool ivd_enable = TRUE;

  m.show_default();
  if (conto == 0 && sottoc == 0)  
    m.hide(-1);
  else
    if (sottoc == 0)
      m.hide(-2);
    else           
      m.hide(-3);

  TString s, s2, s5;
  TString8 s3, s4;
  int s1 = 0;
  int indbil = 0;

  if (sottoc != 0)
  {
    TToken_string key; key.add(gruppo); key.add(conto);
    const TRectype& pconti = cache().get(LF_PCON, key);
    if (!pconti.empty())
    {
      s = pconti.get(PCN_CODCBL);
      s1 = pconti.get_int(PCN_SEZIVD);
      s2 = pconti.get(PCN_LETTIVD);
      s3 = pconti.get(PCN_NUMRIVD);
      s4 = pconti.get(PCN_NUMIVD);
      if (s3.empty())
        s3.spaces(4);

      key.format("%1d%1s%s%s", s1, (const char*) s2,(const char*) s3, (const char*) s4);
      s5 = cache().get("%IVD", key, "S0");
      indbil = pconti.get_int(PCN_INDBIL);
    }
    ivd_enable =  (s1 == 0) && s2.blank() && s3.blank() && s4.blank();
    m.show(FLD_CM1_IVACOMP, indbil == RICAVI);
    m.show(FLD_CM1_DESCIVACOMP, indbil == RICAVI);
  }
  m.show(FLD_CM1_RICSER, indbil == PASSIVITA || indbil == RICAVI);
  if (conto != 0)
  {
    m.enable(FLD_CM1_SEZIVD, ivd_enable);
    m.show(FLD_CM1_LETTIVD, ivd_enable);
    m.show(FLD_CM1_NUMRIVD, ivd_enable);
    m.show(FLD_CM1_NUMIVD, ivd_enable);
    m.show(F_SUB, ivd_enable);
    m.show(FLD_CM1_DESCIVD, ivd_enable); //
    if (!ivd_enable)
    {
      m.set(FLD_CM1_SEZIVD, s1);
      m.set(FLD_CM1_LETTIVDH, s2);
      m.set(FLD_CM1_NUMRIVDH, s3);
      m.set(FLD_CM1_NUMIVDH, s4.left(2));
      m.set(F_SUBH, s4.mid(2));
      m.set(FLD_CM1_DESCIVDH, s5); //
      m.enable(FLD_CM1_SEZIVDOPP);
      m.disable(FLD_CM1_LETTIVDH);
      m.disable(FLD_CM1_NUMRIVDH);
      m.disable(FLD_CM1_NUMIVDH);
      m.disable(FLD_CM1_DESCIVDH); //
    }
    m.show(FLD_CM1_LETTIVDH, !ivd_enable);
    m.show(FLD_CM1_NUMRIVDH, !ivd_enable);
    m.show(FLD_CM1_NUMIVDH, !ivd_enable);
    m.show(F_SUBH, !ivd_enable);
    m.show(FLD_CM1_DESCIVDH, !ivd_enable); //

    if (s.empty())
    {
      TToken_string key; key.add(gruppo);
      const TRectype& pconti = cache().get(LF_PCON, key);
      s = pconti.get(PCN_CODCBL);
    }
  }
  if (s.not_empty())
  {
    m.set(FLD_CM1_CODTABANALISI, s);
    m.check_field(FLD_CM1_CODTABANALISI);
    m.disable(FLD_CM1_CODTABANALISI);
    m.disable(FLD_CM1_DESCRANALISI);
  }
  else
  {
    m.enable(FLD_CM1_CODTABANALISI);
    m.enable(FLD_CM1_DESCRANALISI);
  }
  const bool enable_sezsaldi = (sottoc != 0) || (sottoc == 0 && conto != 0 && m.get(FLD_CM1_TMCF).not_empty());
  m.show(FLD_CM2_SEZSALDI, enable_sezsaldi);
}


HIDDEN bool gruppo_handler(TMask_field& f, KEY key)
{
  TMask& m = f.mask();
  const int gruppo  = m.get_int(FLD_CM1_GRUPPO);
  const int conto   = m.get_int(FLD_CM1_CONTO);
//  const long sottoc = m.get_long(FLD_CM1_SOTTOCONTO);

  if (key == K_ENTER)
  {
    TLocalisamfile& pconti = app().get_relation()->lfile();
    if (gruppo != 0 && conto != 0)
    {
      pconti.zero() ;
      pconti.put(PCN_GRUPPO, gruppo) ;
      pconti.setkey(1) ;
      pconti.read();
      if (pconti.bad())
        return f.warning_box (TR("Il gruppo non esiste"));
    }
  }
  
  return TRUE;
}

HIDDEN bool conto_handler(TMask_field& f, KEY key)
{
  TMask& m    = f.mask();
  const int gruppo  = m.get_int(FLD_CM1_GRUPPO);
  const int conto   = m.get_int(FLD_CM1_CONTO);
  const long sottoc = m.get_long(FLD_CM1_SOTTOCONTO);

  if (key == K_ENTER)
  {
    TLocalisamfile& pconti = app().get_relation()->lfile();

    if (gruppo != 0 && conto != 0 && sottoc != 0)
    {
      pconti.zero() ;
      pconti.put(PCN_GRUPPO, gruppo) ;
      pconti.put(PCN_CONTO, conto) ;
      pconti.setkey(1) ;
      pconti.read();
      if (pconti.bad())
        return m.field(FLD_CM1_CONTO).warning_box (TR("Il conto non esiste"));
      else
      {
        if (pconti.get(PCN_TMCF).not_empty())
          return m.field(FLD_CM1_SOTTOCONTO).warning_box (TR("Non e' possibile inserire un sottoconto di un conto relativo ad un cliente/fornitore"));
      }
    }
  } 
  return TRUE;
}

HIDDEN bool sottoc_handler(TMask_field& f, KEY key)
{
  TMask& m    = f.mask();
  if (m.query_mode() && key == K_TAB)
  {                     
    const int gruppo  = m.get_int(FLD_CM1_GRUPPO);
//    const int conto   = m.get_int(FLD_CM1_CONTO);
//    const long sottoc = m.get_long(FLD_CM1_SOTTOCONTO);
    if (gruppo == 0) return TRUE;
  }
  return TRUE;
}

bool TPianoconti_app::user_create()
{
  open_files(LF_PCON, LF_SALDI, LF_TABCOM, LF_ABPCON, 0);

  _msk = new TMask("cg0100a") ;
  _msk->set_handler(FLD_CM1_GRUPPO, gruppo_handler);
  _msk->set_handler(FLD_CM1_CONTO, conto_handler);
  _msk->set_handler(FLD_CM1_SOTTOCONTO, sottoc_handler);
  _msk->set_handler(FLD_CM1_TMCF, tmcf_handler);
  _rel = new TRelation(LF_PCON);
  // set_search_field(FH_SOTTOCONTO); // Ottima trovata, ma non funziona
  set_search_field(FLD_CM1_SOTTOCONTO);

  return TRUE;
}

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

int cg0100(int argc, char* argv[])
{
  TPianoconti_app a ;
  a.run(argc, argv, TR("Piano dei conti"));
  return 0;
}