#include <execp.h>
#include <mask.h>
#include <mailbox.h>
#include <relapp.h>
#include <tabutil.h>
#include <utility.h>
#include <validate.h>

#include "ba4.h"
#include "ba4200.h"

#define FLD_GD1_TIPOA     126
#define FLD_GD1_CODANAGR  127
#define FLD_GD1_CODDITTAH 627


class BA4200_application : public TRelation_application
{
  char _tip_ana ;
  TString       _cod_ana ;
  TMask*        _msk[2] ;
  TRelation*    _rel[2];
  TLocalisamfile* _comuni;
  TLocalisamfile* _tabcom;

protected:
  virtual bool user_create() ;
  virtual bool user_destroy() ;
  virtual int read(TMask& m);
  virtual int rewrite(const TMask& m);
  virtual void  init_query_mode(TMask& m);
  virtual void  init_insert_mode(TMask& m);
  virtual void  init_modify_mode(TMask& m);
  virtual bool changing_mask(int mode) {return _msk[tip_msk()] == NULL;}
  virtual const char* get_next_key();
  virtual TMask* get_mask(int mode) ;
  virtual void write_enable(const bool on = TRUE);
  
  static bool ba4200_handler(TMask& m, KEY k);
  
public:
  virtual int write(const TMask& m);
  virtual TRelation* get_relation() const { return _rel[tip_msk()];}
  void manual_save(const TMask& m);
  int tip_msk() const { return _tip_ana == TFIS ? MSKF : MSKG;}
  bool ana_fis() const { return _tip_ana == TFIS;}
  bool ana_giu() const { return _tip_ana == TGIU;}
  void set_tip_ana(char tip) { _tip_ana = toupper(tip);}
  void set_cod_ana(const char* cod) { _cod_ana = cod;}
  const char* cod_ana() { return _cod_ana;}
  char tip_ana() { return _tip_ana;}
  virtual bool force_cursor_usage() const { return TRUE;}

  BA4200_application(char ta) { set_tip_ana(ta); }
  virtual ~BA4200_application() {}
};

bool BA4200_application::ba4200_handler(TMask& m, KEY k)
{
  BA4200_application& app = (BA4200_application&)main_app();

  if (k == K_F10)
  {
    if (app.ana_fis()) app.set_tip_ana(TGIU);
    else app.set_tip_ana(TFIS);
    m.stop_run(K_ESC);
    return FALSE;
  }
  if (k != K_F5 || m.mode() != MODE_MOD) return TRUE;
  TToken_string body(16);

  body.add(format("%d", FLD_GD1_CODDITTAH));
  if ( app.tip_ana() == TFIS )
  {
    body.add(format("%d=F", FLD_GD1_TIPOA));
    body.add(format("%d=%s", FLD_GD1_CODANAGR, (const char*) app.cod_ana()));
  }
  else
  {
    body.add(format("%d=G", FLD_GD1_TIPOA));
    body.add(format("%d=%s", FLD_GD1_CODANAGR, (const char*) app.cod_ana()));
  }
#if XVT_OS == XVT_OS_WIN
  TString16 cmd("ba4b -2");
#else
  TString16 cmd("ba4 -2");
#endif
  TMessage  msg(cmd2name(cmd), MSG_FS, (const char*) body);
  TMailbox mb;
  mb.send(msg);
  TLocalisamfile& d = app.get_relation()->lfile();

  d.setkey(1);
  d.zero();
  d.put(N_TIPOA, app.ana_fis() ? "F" : "G");
  d.put(N_CODANAGR,  m.get(FLD_CODANAGR));
  d.read(_isequal, _unlock) ;
  TExternal_app a(cmd);
  a.run();
  d.read(_iscurr, _lock) ;
  m.set_focus();
  return FALSE;
}

void  BA4200_application::init_query_mode(TMask& m)

{
  m.disable(DLG_DITTE);
  m.enable(DLG_CHGTIP);
}

const char* BA4200_application::get_next_key()

{
  TLocalisamfile&       anag = get_relation()->lfile() ;
  long cod_anagr = 1;

  if (!anag.empty() )
  {
    anag.zero() ;
    anag.setkey(1) ;
    if (ana_fis())
    {
      anag.put(N_TIPOA, TGIU);
      anag.read(_isgteq) ;
      if (anag.good()) anag.prev();
      const char t_ret = anag.get_char(N_TIPOA);
      if ( t_ret == TFIS ) 
        cod_anagr = anag.get_long(N_CODANAGR)+1;
    }
    else
    {
      anag.last( ) ;
      if (anag.good())
      {
        const char t_ret = anag.get_char(N_TIPOA);
        if ( t_ret == TGIU ) 
          cod_anagr = anag.get_long(N_CODANAGR)+1;
      }
    }
  }
  _cod_ana.format("%ld", cod_anagr);
  return format("%d|%ld", FLD_CODANAGR, cod_anagr);
}


void  BA4200_application::init_insert_mode(TMask& m)
{
  m.disable(DLG_DITTE);
  m.disable(DLG_CHGTIP);
}


void  BA4200_application::init_modify_mode(TMask& m)
{
  m.enable(DLG_DITTE);
  m.disable(DLG_CHGTIP);
}


bool gest_nazionalita(TMask_field& f, KEY key)
{
  if (f.mask().query_mode() || key == K_SPACE) return TRUE;
  TMask&                                msk = f.mask() ;
  TString                               nazionalita = (const char*)msk.get(FLD_AF1_STATONASC_TABSTE_S0) ;   

  if (f.to_check(key) || nazionalita.empty())
  {
    TString                             cod_stato = (const char* ) f.get() ;

    if ( cod_stato.empty() )
      msk.set(FLD_AF1_STATONASC_TABSTE_S0,"italiana") ;
    else
    {
      TTable                                    t_stati("%STA");
      TRectype&                         rectab = t_stati.curr() ;
      rectab.zero() ;
      rectab.put(N_CODTAB, cod_stato);
      t_stati.read() ;
      if ( t_stati.good() )
        msk.set( FLD_AF1_STATONASC_TABSTE_S0 ,  rectab.get(N_NAZIONALITA) ) ;
    }
  }
  return TRUE ;
}

bool clear_cap(TMask_field& f, KEY key)
{                     
  if (f.mask().query_mode() || !f.to_check(key, TRUE)) 
    return TRUE;

  TMask& msk = f.mask() ;
  const short   dlg = f.dlg();
  const bool giuridica = ((BA4200_application&)main_app()).ana_giu();
  const TString16 val(f.get());

  if ( giuridica )
  {
    if (val.empty())
    {
      if (dlg == FLD_AG1_COMRF)
        msk.set(FLD_AG1_CAPRF, "");
      else
        if (dlg == FLD_AG2_COMRES)
          msk.set(FLD_AG2_CAPRES, "");
        else
          if (dlg == FLD_AG2_COMCORR)
            msk.set(FLD_AG2_CAPCORR, "");
    }
  }
  else
  {
    if (val.empty())
    {
      if (dlg == FLD_AF2_COMRF)
        msk.set(FLD_AF2_CAPRF, "");
      else
        if (dlg == FLD_AF1_COMRES)
          msk.set(FLD_ANAG_CAPRES, "");
        else
          if (dlg == FLD_AF2_COMCORR)
            msk.set(FLD_AF2_CAPCORR, "");
    }
  }  
  return TRUE; 
} 


// Handler del comunde di residenza e residenza fiscale                                            
bool gest_uff_imp(TMask_field& f, KEY key)
{
  if (f.mask().query_mode() || !f.to_check(key, TRUE)) 
    return TRUE;

  TString       cod_sta, cod_com;
  TMask& msk = f.mask() ;
  const short   dlg = f.dlg();
  const bool giuridica = ((BA4200_application&)main_app()).ana_giu();

  if ( giuridica )
  {
    cod_com = msk.get(FLD_AG1_COMRF);
    if ((dlg == FLD_AG2_COMRES) || (dlg == FLD_AG2_STATORES))
      if (cod_com.not_empty()) return TRUE;
    cod_sta = msk.get(FLD_AG1_STATORF);
  }
  else
  {
    cod_com = msk.get(FLD_AF2_COMRF);
    if ((dlg == FLD_AF1_COMRES) || (dlg == FLD_AF1_STATORES))
      if (cod_com.not_empty()) return TRUE;
    cod_sta = msk.get(FLD_AF2_STATORF);
  }
  clear_cap(f,key);
  if (cod_com.empty())
  {
    cod_com = msk.get(giuridica ? FLD_AG2_COMRES : FLD_AF1_COMRES) ;
    cod_sta = msk.get(giuridica ? FLD_AG2_STATORES : FLD_AF1_STATORES) ;
  }     
  
  if (cod_com.empty())
    return TRUE;
  
  TLocalisamfile        comuni(LF_COMUNI) ;
  comuni.setkey(1) ;
  comuni.zero() ;
  comuni.put(N_STATO, cod_sta);
  comuni.put(N_COM, cod_com );
  if (comuni.read() == NOERR)
  {
    msk.set(F_IMP_DENCOM, comuni.get("DENCOM"));
    msk.set(F_IMP_PROVCOM, comuni.get("PROVCOM"));

    TString s(comuni.get(N_IMPDIR1)) ; 
    if (s.empty()) s = comuni.get(N_IMPDIR2) ; 
    if (s.empty()) s = comuni.get(N_IMPDIR3) ; 
    msk.set(F_UFFIIDD, s) ; msk.field(F_UFFIIDD).on_key(K_TAB);
    s = comuni.get(N_IVA1); 
    if (s.empty()) s = comuni.get(N_IVA2) ; 
    if (s.empty()) s = comuni.get(N_IVA3) ; 
    msk.set(F_UFFIVA, s) ; msk.field(F_UFFIVA).on_key(K_TAB);
    msk.set(F_UFFREG, comuni.get("UFFREG")); msk.field(F_UFFREG).on_key(K_TAB);
    msk.set(F_UFFCONC, comuni.get("UFFCONC")); msk.field(F_UFFCONC).on_key(K_TAB);
    msk.set(F_UFFSERV, comuni.get("UFFCSERV")); msk.field(F_UFFSERV).on_key(K_TAB);

    msk.set(F_CODCONTR_EP, comuni.get("UFFESPROV").mid(1, 2));
    msk.set(F_CODCONTR_EC, comuni.get("UFFESCOM"));
  }     
  
  return TRUE;
}

bool no_dup_fis(TMask_field& f, KEY key)
{
  if (f.mask().query_mode() || !f.to_check(key)) return TRUE;
  BA4200_application& app = (BA4200_application&)main_app();
  TLocalisamfile&       anag = app.get_relation()->lfile(LF_ANAG) ;
  
  const TString16 cofi(f.get());                     
  if ( cofi.not_empty() )
  {              
    anag.zero() ;
    anag.put(N_TIPOA, app.tip_ana());
    anag.put(N_COFI, cofi ) ;
    anag.setkey(3) ;
    anag.read() ;
    anag.setkey(1) ;
    const char t = anag.get_char(N_TIPOA), t1 = app.tip_ana();
    const TString16     s = anag.get(N_CODANAGR), s1 = app.cod_ana();

    if (anag.good() && (t1 != t || s1 != s))
    {
      f.error_box("Codice fiscale gia' utilizzato per il codice %c/%s",
                  t, (const char*)s);
      return FALSE;
    }
  }
  return TRUE ;
}

bool gest_iva(TMask_field& f, KEY key , short   fd_sta ,short fd_iva )
{
  if (f.mask().query_mode() || !f.to_check(key)) return TRUE;
  
  BA4200_application& app = (BA4200_application&)main_app();
  TLocalisamfile&       anag = app.get_relation()->lfile(LF_ANAG) ;
  TMask& msk = f.mask() ;

  if ( f.get().not_empty() && !anag.empty() )
  {
    anag.zero() ;        
    anag.put(N_TIPOA, app.tip_ana());
    anag.put(N_STATOPAIV, msk.get(fd_sta) ) ;
    anag.put(N_PAIV, msk.get(fd_iva) ) ;
    anag.setkey(4) ;
    anag.read() ;
    anag.setkey(1) ;
    const char t  = anag.get_char(N_TIPOA), t1 = app.tip_ana();
    const TFixed_string s(anag.get(N_CODANAGR)),        s1(app.cod_ana());
    if (anag.good() && (t1 != t || s1 != s))
    {
      f.error_box("Partita iva gia' definita per il codice : %c/%s",
                  t, (const char*) s);
      return FALSE ;
    }
  }
  return TRUE ;
}

bool no_dup_iva_f(TMask_field& f, KEY key)

{
  if (f.mask().query_mode() || !f.to_check(key)) return TRUE;
  return ( gest_iva(f , key , FLD_AF1_STATOPAIV ,FLD_AF1_PAIV ) ) ;
}

bool no_dup_iva_g(TMask_field& f, KEY key)
{ 
  if (key == K_ENTER && !f.mask().query_mode() && f.get().empty())
  {                                    
    bool ok = FALSE;   
    if (!f.mask().get_bool(CHK_AG1_ENTENCOMM))
    {
      const TString cofi(f.mask().get(FLD_AG1_COFI));
      if (pi_check("IT", cofi)) 
      {
        f.set(cofi);
        ok = TRUE;
      }  
    }
    if (!ok) return error_box("Partita IVA obbligatoria!");
  }

  return gest_iva(f , key , FLD_AG1_STATOPAIV ,FLD_AG1_PAIV ) ;
}

TMask* BA4200_application::get_mask(int mode)
{ 
  if (!changing_mask(mode)) return _msk[tip_msk()];
  if (ana_fis())
  {
    if (_msk[MSKG] != NULL) delete _msk[MSKG];
    _msk[MSKG] = NULL;
    _msk[MSKF] = new TMask("ba4200b") ;
    _msk[MSKF]->set_handler(FLD_AF1_PAIV, no_dup_iva_f);
    _msk[MSKF]->set_handler(FLD_AF1_COFI, no_dup_fis);
    _msk[MSKF]->set_handler(FLD_AF1_COMRES, gest_uff_imp);
    _msk[MSKF]->set_handler(FLD_AF2_COMRF, gest_uff_imp);
    _msk[MSKF]->set_handler(FLD_AF2_COMCORR, clear_cap);
    _msk[MSKF]->set_handler(FLD_AF1_STATORES, gest_nazionalita);
    _msk[MSKF]->set_handler(FLD_AF1_PAIV, no_dup_iva_f);
    _msk[MSKF]->set_handler(FLD_AF1_COFI, no_dup_fis);
    _msk[MSKF]->set_handler(ba4200_handler);
  }
  else
  {
    if (_msk[MSKF] != NULL) delete _msk[MSKF];
    _msk[MSKF] = NULL;
    _msk[MSKG] = new TMask("ba4200c") ;
    _msk[MSKG]->set_handler(FLD_AG2_COMRES, gest_uff_imp);
    _msk[MSKG]->set_handler(FLD_AG1_COMRF, gest_uff_imp);
    _msk[MSKG]->set_handler(FLD_AG2_COMCORR, clear_cap);
    _msk[MSKG]->set_handler(FLD_AG1_COFI, no_dup_fis);
    _msk[MSKG]->set_handler(FLD_AG1_PAIV, no_dup_iva_g);
    _msk[MSKG]->set_handler(ba4200_handler);
  }
  return _msk[tip_msk()];
}

bool BA4200_application::user_create() 

{
  _msk[MSKF] = NULL;
  _rel[MSKF] = new TRelation(LF_ANAG);
  _rel[MSKF]->add(LF_ANAGFIS, "CODANAGR=CODANAGR", 1, 0, 0);

  _msk[MSKG] = NULL;
  _rel[MSKG] = new TRelation(LF_ANAG);
  _rel[MSKG]->add(LF_ANAGGIU, "CODANAGR=CODANAGR", 1, 0, 0);
  
  _comuni = new TLocalisamfile(LF_COMUNI) ;
  _tabcom = new TLocalisamfile(LF_TABCOM) ;

  if (argc() > 3)
  {
    get_mask(MODE_QUERY);
    TString16 s("1|");

    s << argv(3);
    set_link(*_msk[tip_msk()], s);
  }
  return TRUE;
}

void BA4200_application::write_enable(const bool on)

{
  _rel[MSKF]->write_enable(-1, on);
  _rel[MSKG]->write_enable(-1, on);
}

bool BA4200_application::user_destroy() 
{
  for ( int j = 0 ; j < 2 ; j++ )
  {
    if (_msk[j]) delete _msk[j] ;
    if (_rel[j]) delete _rel[j] ;
  }
  delete _comuni;
  delete _tabcom;

  return TRUE;
}

void BA4200_application::manual_save(const TMask& m)

{
  TRelation *r = get_relation();
  TLocalisamfile& anag = r->lfile(LF_ANAG) ;

  if (ana_fis())
  {
    TLocalisamfile&     anafis = r->lfile(LF_ANAGFIS) ;

    anafis.put(N_CODANAGR, _cod_ana);
  }
  else
  {
    TLocalisamfile&     anagiu = r->lfile(LF_ANAGGIU) ;
    anagiu.put(N_CODANAGR, _cod_ana);
  }

  const TDate   oggi(TODAY) ;
  anag.put(N_DATAAGG, oggi.string());
}

int BA4200_application::read(TMask& m) 

{
  const TRelation *r = get_relation();
  m.autoload(r);
  _cod_ana = r->lfile().get(N_CODANAGR);
  return NOERR;
}

int BA4200_application::write(const TMask& m) 

{
  TRelation *r = get_relation();
  m.autosave(r);
  set_cod_ana(r->lfile().get(N_CODANAGR));
  manual_save(m);
  return r->write();
}

int BA4200_application::rewrite(const TMask& m) 

{
  TRelation *r = get_relation();

  m.autosave(r);
  manual_save(m);
  return r->rewrite();
}

int ba4200(int argc, char* argv[])
{                         
  char ta = 'F';
  
  TApplication::check_parameters(argc, argv);
  if (argc > 2 && toupper(*argv[2]) == 'G') ta = 'G';

  BA4200_application a(ta);

  TString80 titolo("Anagrafica Persone ");
  titolo << (ta == 'F' ? "Fisiche" : "Giuridiche");
  
  a.run(argc, argv, titolo);
  return 0;
}
