// 776300.cpp - Selezione dichiarazioni per menu' stampe
#include <confapp.h>
#include <mask.h>
#include <isam.h>
#include <sheet.h>
#include <prefix.h>  
#include <progind.h>  
#include <lffiles.h>  
#include <utility.h>  

#include "776300a.h"
#include "77lib.h"     

class TSelezioneDich : public TConfig_application
{
    TString16       _section;
    TBit_array      _selected;
    TArray_sheet*   _ditte, * _ditte_sel;  
    TArray          _nomiditte;
    TArray          _old_ditte;
    TConfig*        _user_cnf, * _studio_cnf;
    int             _n_ditte;
    int             _anno_dic;
    TLocalisamfile* _nditte;
    long            _da_cod, _a_cod;
    bool			_builded_nomiditte;

    void    build_nomiditte();
    void    build_ditte_sheet();
    void    build_ditte_sel_sheet();
    bool    is_in (long codditta);
    void    init_sheet();
    void    check_all_dic();
    
  public:
    void        set_choice_limits(TMask& m);
    long        select_firm_range(long from, long to);
    long        set_previous_firm_range();
// handlers & handlers
    static bool to_ditt_handler  (TMask_field&, KEY);
    static bool fr_ditt_handler  (TMask_field&, KEY);
    static bool to_butt_handler  (TMask_field&, KEY);
    static bool fr_butt_handler  (TMask_field&, KEY);
    static bool mask_select      (TMask_field&, KEY);
    static bool mask_azzera      (TMask_field&, KEY);
// Seleziona tutte le dic
    static bool tutte_handler    (TMask_field&, KEY);
// Mostra solo le selezionate
    static bool dicsel_handler   (TMask_field&, KEY);
        
    virtual bool preprocess_config  (TMask& mask, TConfig& config);
    virtual bool postprocess_config (TMask& mask, TConfig& config);
//  virtual bool postprocess_config_changed(const char* par, const char* var,const char* oldv, const char* newv);

    virtual bool user_create(); 
    virtual bool user_destroy();

    TSelezioneDich() : TConfig_application(CONFIG_USER) ,
                       _a_cod(0L), _da_cod(0L) {}
    virtual ~TSelezioneDich() {}
};

HIDDEN TSelezioneDich& app() { return (TSelezioneDich&) main_app(); }

bool TSelezioneDich::user_create()
{
  const char*   edit_mask = "776300a";
  _section = name(); 
  _section.cut(2); 

// Forza la scrittura del file in partenza
// (onde evitare di vedere il messaggio "Nessun parametro da configurare" e di dover
// rientrare).
  TConfig* tmp = new TConfig(CONFIG_USER, _section);
  tmp->get("EdMask", _section, -1, edit_mask);
  delete tmp;

  _user_cnf = new TConfig(CONFIG_USER, _section);
  _user_cnf->get("EdMask", _section, -1, edit_mask);

  _studio_cnf = new TConfig(CONFIG_STUDIO);  

  _nditte   = new TLocalisamfile(LF_NDITTE);
  _ditte    = new TArray_sheet(-1, -1, 0, 0, "Selezione Ditte",
                             "@1|Cod.@5|Ragione Sociale@50");

  _ditte_sel = new TArray_sheet(-1, -1, 0, 0, "Selezione Ditte",
                               "@1|Cod.@5|Ragione Sociale@50", 0);
 
  _builded_nomiditte = FALSE;
  
  return TRUE;
}

bool TSelezioneDich::user_destroy()
{
  delete _ditte;
  delete _ditte_sel;
  delete _nditte;   
  delete _user_cnf;
  delete _studio_cnf;
  return TRUE;
}
 
void TSelezioneDich::init_sheet() 
{ 
  _n_ditte  = 0l;
  _old_ditte.destroy();

  if (!_builded_nomiditte)    
  {
    build_nomiditte();            
    _builded_nomiditte = TRUE;
  }

// Legge ditte selezionate dal CONFIG_USER e mette nell'array _old_ditte
  long  codditta = 0L;
  int   i = 0;
  TString16 cods;
  while ((codditta = _user_cnf->get_long(DITTE_SEL, _section, i++)) != 0L) 
  {
// Salvo il primo e l'ultimo codice ditta per settare i campi in maschera  
    if (_da_cod == 0L) _da_cod = codditta;
    _a_cod = codditta;
     
    cods.format("%5ld", codditta);
    _old_ditte.add(cods);
  }  

  build_ditte_sheet();
}

bool TSelezioneDich::preprocess_config (TMask& m, TConfig& config)
{ 
  init_sheet();

// Setto l'anno dichiarazione con quello preso dai parametri di studio
// ma SOLO SE non gia' compilato nei par. utente           
  _anno_dic = (int)_user_cnf->get_long(ANNO_SEL, _section);
  if (_anno_dic == 0)
    _anno_dic = (int)_studio_cnf->get_long(ANNO_SEL, _section);

  m.set(F_ANNODIC, _anno_dic);    

//  const long l = select_firm_range(_da_cod, _a_cod); 
// Evidenzia le ditte precedentemente selezionate. Legge _old_ditte
  const long l = set_previous_firm_range();
  
  set_choice_limits(m);
  m.field(F_SELECT).set(format("%ld", l));

  m.set_handler (DLG_SELECT_2, mask_select);
  m.set_handler (F_ANNULLA,  mask_azzera);
  m.set_handler (A_CODICE,   to_ditt_handler);
  m.set_handler (DA_CODICE,  fr_ditt_handler);
  m.set_handler (BUT_DTO,    to_butt_handler);
  m.set_handler (BUT_DFR,    fr_butt_handler);

  m.set_handler (F_TUTTE,    tutte_handler);
  m.set_handler (F_DICSEL,   dicsel_handler);  
  
  return TRUE; 
}

bool TSelezioneDich::is_in (long codditta)
{
  for (int i=0; i<_old_ditte.items(); i++)
    if (codditta == atol((TString&)_old_ditte[i])) 
      return TRUE;
  return FALSE;
}

bool TSelezioneDich::postprocess_config (TMask& m, TConfig& config)
{ 
  if (m.last_key() == K_ENTER)
  { 
    const int anno_dic = m.get_int(F_ANNODIC);  
    const long selec    = _ditte->checked();
    const long items    = _ditte->items();
    
    TProgind prg(items, "Registrazione in corso\nAttendere prego...", FALSE, TRUE);
    
// Registro l'anno dic. nei parametri utente
    _user_cnf->set(ANNO_SEL, anno_dic);

// Compatto l'array delle ditte nel .ini  
    int ditte_in_ini = 0;  

    long  codditta = 0L;
    for (int i = 0; i < items; i++)
    {
      if (_selected[i])
      {
        TToken_string& d  = (TToken_string&)_nomiditte[i];      
        codditta          = d.get_long(1);
        _user_cnf->set(DITTE_SEL, codditta, _section, TRUE, ditte_in_ini);
        ditte_in_ini++ ;
      }
      prg.addstatus(1);
    }

// Segno l'ultima ditta nel .ini
    _user_cnf->set(DITTE_SEL, "", _section, TRUE, ditte_in_ini);
// Reset dei due codici ditta "Da" "A"
    _a_cod  = _da_cod = 0L;
  }
  return TRUE;
}

bool TSelezioneDich::mask_select (TMask_field& f, KEY k)
{
  if (k == K_SPACE)
  {
    app()._ditte->enable_check();
    // seleziona e aggiungi alle gia' selezionate 
    if (app()._ditte->run() == K_ENTER)
    {
      for (long j = 0l; j < app()._ditte->items(); j++)
          app()._selected.set(j, app()._ditte->checked(j));
      app().set_choice_limits(f.mask());
    }
  }
  return TRUE;
}    
  
bool TSelezioneDich::mask_azzera (TMask_field& f, KEY k)
{
  if (k == K_SPACE)
  {
    app()._selected.reset();  
    f.mask().reset(F_SELECT);
    f.mask().reset(DA_CODICE);
    f.mask().reset(A_CODICE);
    app()._ditte->check(-1, FALSE);
  }
  return TRUE;
}

// --------------------------- handlers per selezione ditte

bool TSelezioneDich::to_ditt_handler(TMask_field& f, KEY key)
{
  TMask& m = f.mask();
  if (key == K_F9)
  {
    app().to_butt_handler(m.field(BUT_DTO), K_SPACE);
  }
  if (key == K_TAB && f.focusdirty())
  {
    const long l = app().select_firm_range(m.get_long(DA_CODICE), m.get_long(A_CODICE)); 
    app().set_choice_limits(m);
    m.field(F_SELECT).set(format("%ld", l));
  }
  return TRUE;
}

bool TSelezioneDich::fr_ditt_handler(TMask_field& f, KEY key)
{                          
  TMask& m = f.mask();
  if (key == K_F9)
  {
    app().fr_butt_handler(m.field(BUT_DFR), K_SPACE);
  }
  else if (key == K_TAB && f.focusdirty())
  {
    const long l = app().select_firm_range(m.get_long(DA_CODICE), m.get_long(A_CODICE)); 
    app().set_choice_limits(m);
    m.field(F_SELECT).set(format("%ld", l));
  }
  return TRUE;
}

bool TSelezioneDich::to_butt_handler(TMask_field& f, KEY key)
{
  if (key == K_SPACE)
  {
    TArray_sheet* sh = app()._ditte;
    TMask& m = f.mask();
    
    sh->disable_check();    
    if (sh->run() == K_ENTER)
    {
      app().select_firm_range(m.get_long(DA_CODICE),sh->row(sh->selected()).get_long(1)); 
      app().set_choice_limits(m);
    }
  }
  return TRUE;
}

bool TSelezioneDich::fr_butt_handler(TMask_field& f, KEY key)
{
  if (key == K_SPACE)
  {
    TMask& m = f.mask();
    TArray_sheet* sh = app()._ditte;

     sh->disable_check();    
    if (sh->run() == K_ENTER)
    {
      app().select_firm_range(sh->row(sh->selected()).get_long(1), m.get_long(A_CODICE)); 
      app().set_choice_limits(m);
    }
  }
  return TRUE;
}

void TSelezioneDich::check_all_dic()
{  
  for (int i = 0; i < _ditte->items(); i++)
    _ditte->check(i);
}
  
bool TSelezioneDich::tutte_handler(TMask_field& f, KEY key)
{
  if (key == K_SPACE)     
  {
    const bool checked = (f.get() == "X");
    
    if (checked)
    {
      app().check_all_dic();
      app().select_firm_range(0L,0L);
      app().set_choice_limits(f.mask());
    }
  }
  return TRUE;
}

bool TSelezioneDich::dicsel_handler(TMask_field& f, KEY key)
{
  if (key == K_SPACE)     
  {
    app().build_ditte_sel_sheet();
    app()._ditte_sel->run();
  }
  return TRUE;
}

void TSelezioneDich::set_choice_limits(TMask& m)
{     
  long first = -1l, last = -1l;
  for (int i = 0; i < _ditte->items(); i++)
  {
    if (_selected[i])
    {
      long dit = _ditte->row(i).get_long(1);
      if (first == -1l) first = dit;
      if (last < dit)   last  = dit;
    }
  }
  if (first != -1) m.field(DA_CODICE).set(format("%ld",first));                        
  if (last  != -1) m.field(A_CODICE).set(format("%ld",last));                        
  m.set(F_SELECT, _selected.ones());
}
                                        
// Legge da _old_ditte le ditte selezionate e le evidenzia
long TSelezioneDich::set_previous_firm_range()
{                
  const long items = _old_ditte.items();
  for (int i=0; i < items; i++)
  {
    const long codditta = atol((TString&)_old_ditte[i]);
      
    for (int dit=0; dit < _ditte->items(); dit++)
    {
      TToken_string& d    = _ditte->row(dit);
      const long   cod    = d.get_long(1);
    
      if (codditta == cod)
      {
        _selected.set(dit); 
        _ditte->check(dit);
        break;
      }
/************************
      else 
      {
        _selected.set(dit,FALSE);
        _ditte->uncheck(dit);
      }
**************************/
    }
  } 
  return _selected.ones();
}

long TSelezioneDich::select_firm_range(long from, long to)
{
  if (to == 0l) to = 99999L;                              
  for (int i = 0; i < _ditte->items(); i++)
  {
    if (_ditte->row_disabled(i))
      continue;

    TToken_string& d = _ditte->row(i);

    const long cod = d.get_long(1);
    if (cod >= from && cod <= to)
    {
      _selected.set(i); 
      _ditte->check(i);
    }
    else 
    {
      _selected.set(i,FALSE);
      _ditte->uncheck(i);
    }
  } 
  return _selected.ones();
}

// 23/6/95 - Scelta ditte solo tra quelle che hanno dichiarazione
void TSelezioneDich::build_nomiditte()
{                 
  _nomiditte.destroy();
  // ricostruire _nomiditte e rifare build_ditte_sheet
  TLocalisamfile& dt = *_nditte;
  TProgind prg(dt.items(), "Lettura ditte in corso\nAttendere prego...", FALSE, TRUE);

  for (dt.first(); !dt.eof(); dt.next())
  {     
    prg.addstatus(1);
    bool good = exist_dichiar_770(dt.get_long("CODDITTA"));
    if (!good) continue;

    _n_ditte++;
    TToken_string* d = new TToken_string(64);

    d->add(" ");                    // spazio per la selezione
    d->add(dt.get("CODDITTA"));
    d->add(dt.get("RAGSOC"));
     
    _nomiditte.add(d);  
  }
}

void TSelezioneDich::build_ditte_sheet()
{
  long codditta = 0L;
  // build sheet
  _ditte->destroy();
  for (int i = 0; i < _nomiditte.items(); i++)
  {
    TToken_string* d = new TToken_string(64);
    *d = (TToken_string&)_nomiditte[i];
    codditta = d->get_long(1);
    
    const long pos = _ditte->add(d);     
// Metto check se selezionata o era nei parametri precedenti
    if (_selected[i] || is_in(codditta)) 
      _ditte->check(pos);
  }     
}

// Costruisce un array sheet copiando da nomiditte solo quelle 
// gia' selezionate
void TSelezioneDich::build_ditte_sel_sheet()
{
  long codditta = 0L;
  // build sheet
  _ditte_sel->destroy();
  for (int i = 0; i < _nomiditte.items(); i++)
  {
    TToken_string* d = new TToken_string(64);
    *d = (TToken_string&)_nomiditte[i];
    codditta = d->get_long(1);

//  se selezionata o era nei parametri precedenti
    if (_selected[i]) 
    {
      const long pos = _ditte_sel->add(d);     
//      _ditte_sel->check(pos);
    }
  }     
}

int SelezioneDichiarazioni(int argc, char* argv[])
{
  TSelezioneDich   app;
  app.run(argc, argv, "Selezione dichiarazione");
  return 0;
}