#ifndef __F90100H__
#define __F90100H__

#define PAR_MOD     "F9"
#define AMBIENTE_F9 "CODSOC"      // Codice ambiente (codsoc)
#define ADDRCART_F9 "ADDDOC"      // Indirizzo documenti cartacei
#define VENDEXT_F9  "VENDEXT"     // Flag no vendite con campo
#define VIEWMOV_F9  "VIEWMOVPRE"  // Flag visualizza moviementi prima di estrarre

#include "execp.h"
#include "f90100a.h"
#include "f9lib01.h"
#include "mov.h"
#include <automask.h>
#include "applicat.h"

/** class TEstrai_mask
 * \brief Piccola maschera "creata a runtime" per avviare l'estrazione.
 */
class TEstrai_mask : public TMask
{
  TString _descr;

  void        enable_fields(bool en = true);

  static bool estrai_handler(TMask_field& f, KEY key);
  static bool enable_handler(TMask_field& f, KEY key);
  static bool dataini_handler(TMask_field& f, KEY key);
  static bool dataend_handler(TMask_field& f, KEY key);
public:
  TString& get_descr() { return _descr; }
  TEstrai_mask();
};

class TEstrai_mask;
class TMonitor_mask;
class TControllo_mask;
class TF9_app : public TSkeleton_application
{
  //friend class TEstrai_mask;
  friend class TMonitor_mask;
  friend class TControllo_mask;
  friend class TEstrazione;

  struct config
  {
    TString ambiente;   // Codice ambiente (codsoc)
    TString addr_doc;   // Indirizzo documenti cartacei
    bool    vendext;
    bool    viewmovpre;
  } _config;  // todo: controllare che siano sqlsafe
  unique_ptr<TEstrai_mask>  _estr_msk;
  unique_ptr<TMonitor_mask> _msk;
  vector<movimento_t>       _movs;
  vector<TToken_string>     _esclusi;     // Vettore con i movimenti esclusi
  vector<TToken_string>     _esclusi_vect;
  TToken_string             _mov_escl;
  char                      _tipodoc_escl;
  char                      _flagprov_escl;
  TString                   _log;

  unique_ptr<TEstrazione>   _estrazione;
  TEstrazione*              _estr_escluso;

  TDate   get_dataini() const { return _estr_msk->get_date(ES_DATAINI); }
  TDate   get_dataend() const { return _estr_msk->get_date(ES_DATAEND); }
  char    get_tipodoc() const { return _estr_msk->get(ES_TIPODOC)[0]; }
  char    get_tipodoc_escl() const { return _tipodoc_escl; }
  TipoIVA get_tipoiva() const { return get_tipodoc() == 'A' ? iva_acquisti : iva_vendite; }
  TipoIVA get_tipoiva_escl() const { return get_tipodoc_escl() == 'A' ? iva_acquisti : iva_vendite; }
  TString get_descr()    const { return _estr_msk->get(ES_DESCR); }
  bool    is_provviso() const { return _estr_msk->get(ES_FLAGPROV)[0] == 'P'; }

  static const char* traduci_stato(const TString& cod);

  //void fill();

public:
  const TString&  get_ambiente()    const { return _config.ambiente; }
  const TString&  get_addr_doc()    const { return _config.addr_doc; }
  bool            get_has_vendext() const { return _config.vendext; }
  bool            get_viewmov()     const { return _config.viewmovpre; }

  void set_ambiente(const char* cod)    { _config.ambiente.cut(0) << cod; }
  void set_addr_doc(const char* add)    { _config.addr_doc.cut(0) << add; }
  void set_has_vendext(const bool flag) { _config.vendext     = flag; }
  void set_viewmov(const bool flag)     { _config.viewmovpre  = flag; }

  void run_estr_msk() const { _estr_msk->run(); }

  // Estrazione esclusi
  static bool select_escl_notify(TSheet_field& s, int row, KEY key);
  static bool controllo_escl_handler(TMask_field& field, KEY key);
  static bool year_handler(TMask_field& field, KEY key);
  void        open_esclusi();
  static void fill_esclusi();
  static movimento_t escl2mov(TToken_string* row);
  static bool estrai_escl_handler(TMask_field&, KEY key);
  static bool mov_handler(TMask_field&, KEY key);
  static bool mov_handler_escl(TMask_field&, KEY key);

  void  edit_wa(TString& old_codsoc) const;
  /** Caricamento di tutti i movimenti data un periodo di data registrazione.
   * \return See TEstrazione::estrai().
   */
  int estrai();

  // logs

  void  print_log();
  void  add_msg_log(const char* msg);
  void  add_sqlerror_msg_log(const char* query);

  bool  segna_estratti(bool escluso = false, int numreg = 0); /**< Segna su mov che il movimento e' stato estratto */
  static void  segna_in_errore();

  static bool is_autofattura(const TLocalisamfile& mov);

  void main_loop() override;

  // Controllo e aggiornamento tabelle F9

  bool create_tables() const;               /**< Creazione tabelle F9 */
  bool check_tabelle_f9() const;            /**< Controllo esistenza delle tabelle e in caso le crea */
  bool aggiorna_tab_f9(int version) const;  /**< Aggiorna modifiche alle tabelle F9 come descritto in cima al file .cpp */
  bool check_tab_version() const;           /**< Controllo della versione e in caso aggiorna le tabelle */
  bool check_table() const;
  TF9_app() : _config({ "", "", false, false }), _estr_msk(nullptr), _msk(nullptr), _mov_escl("", '|'),
    _tipodoc_escl('A'), _flagprov_escl('P'), _estrazione(nullptr), _estr_escluso(nullptr)
  {
    _config.ambiente = ini_get_string(CONFIG_DITTA, PAR_MOD, AMBIENTE_F9);
    _config.addr_doc = ini_get_string(CONFIG_DITTA, PAR_MOD, ADDRCART_F9);
  }
};
TF9_app& f9_app();

class TMonitor_mask : public TAutomask
{
  friend class TF9_app;
  vector<TToken_string> _fppro;

  static bool save_conf_handler(TMask_field& f, KEY key);

  void controllo_errori() const;
  void delete_pack(bool all = false) const;
  
  // Riempie sheet per visualizzare le estrazioni
  void fill() const;
  
  bool        on_field_event(TOperable_field& o, TField_event e, long jolly) override;
  bool        on_key(KEY key) override;
  void        open_mostra_estrazione() const;
  static void open_win_estr();
  void        open_win_conf() const;
  
  void sel() const;
public:
  TMonitor_mask() : TAutomask("f90100a") { fill(); }
};

class TControllo_mask : public TAutomask
{
  char                  _ordin;
  char                  _verso;
  int                   _selected_mov;
  bool                  _sel_esclusi;
  bool                  _is_escluso;
  TString               _cod_soc;
  TString               _id_estr;
  char                  _tipo_doc_err{};
  vector<TToken_string> _movs;

  void associa();
  void conferma_esclusi() const;

  vector<TToken_string>& import_error_list();
  void    fill();
  void    fill_fppro_sheet() const;
  TMask&  get_win_order();
  void    open_win_order();

  TToken_string* selected_mov();
  TToken_string* selected_fat() const;

  /** Gestisce la selezione multipla negli sheet di controllo movimenti */
  void selfatt(TOperable_field& o, long jolly) const;

  bool on_field_event(TOperable_field& o, TField_event e, long jolly) override;
public:
  explicit TControllo_mask(const char* codsoc, const char* id_estr, bool esclusi = false);
};

inline bool open_mov(const TRectype& mov)
{
  TFilename ininame; ininame.temp("lnk", "ini");
  {
    TConfig ini(ininame, "Transaction");
    ini.set("Action", "LINK");
    ini.set_paragraph("23");
    ini.set("NUMREG", mov.get(MOV_NUMREG));
  }
  TString app;
  app << "cg2.exe -0 -i" << ininame;
  TExternal_app a(app);
  bool ok = a.run() == 0;

  if (ok)
  {
    xvt_sys_sleep(500);
    const TString& result = ini_get_string(ininame, "Transaction", "Result");
    ok = result == "OK";
  }
  xvt_fsys_remove_file(ininame);
  return ok;
}




// Getters per semplificare i get dai TRecorset

const TString&  recset_get_string(const TRecordset& rec, const char* field, int zero_filled = -1);
int             recset_get_int(const TRecordset& rec, const char* field, int zero_filled = -1);
bool            recset_get_bool(const TRecordset& rec, const char* field);
real            recset_get_real(const TRecordset& rec, const char* field);

#endif //__F90100H__