#include "scselect.h"                    

TSelection_mask::TSelection_mask(const char* name)
               : TMask(name), _who('C'), _key(1), _clifo_rel(NULL),
                 _cli_cur_k1(NULL), _cli_cur_k2(NULL), _for_cur_k1(NULL), _for_cur_k2(NULL)
{
  // crea relazioni, cursori e cursor_sheets
  _clifo_rel  = new TRelation(LF_CLIFO);
  
  TRectype filter(LF_CLIFO);
  filter.put("TIPOCF", "C");
  _cli_cur_k1 = new TCursor(_clifo_rel, "", 1, &filter, &filter);
  _cli_cur_k2 = new TCursor(_clifo_rel, "", 2, &filter, &filter);
  
   _cli_sh_k1 = new TCursor_sheet(_cli_cur_k1, " |CODCF|RAGSOC", "Selezione clienti per codice",
                                 "@1|Codice|Ragione Sociale@50");
  _cli_sh_k2 = new TCursor_sheet(_cli_cur_k2, " |RAGSOC|CODCF", "Selezione clienti per ragione sociale",
                                 "@1|Ragione Sociale@50|Codice");
  
  if (id2pos(SC_CLIFO) >= 0)
  {
    filter.put("TIPOCF", "F");
    _for_cur_k1 = new TCursor(_clifo_rel, "", 1, &filter, &filter);
    _for_cur_k2 = new TCursor(_clifo_rel, "", 2, &filter, &filter);
    _for_sh_k1 = new TCursor_sheet(_for_cur_k1, " |CODCF|RAGSOC", "Selezione fornitori per codice",
                                   "@1|Codice|Ragione Sociale@50");
    _for_sh_k2 = new TCursor_sheet(_for_cur_k2, " |RAGSOC|CODCF", "Selezione fornitori per ragione sociale",
                                   "@1|Ragione Sociale@50|Codice");
  }
                                 
  set_handler(SC_CLIFO,   rclifo_handler); 
  set_handler(SC_SORTCF,  rsortcf_handler); 
  set_handler(SC_CFBUTFR, bfrom_handler); 
  set_handler(SC_CFBUTTO, bto_handler); 
  set_handler(SC_SELECT,  bselect_handler); 
  set_handler(SC_RESET,   breset_handler); 
  set_handler(SC_CFCODFR, ffrom_handler); 
  set_handler(SC_CFCODTO, fto_handler); 
}

TSelection_mask::~TSelection_mask()
{
  delete _for_sh_k2;
  delete _for_sh_k1;
  delete _for_cur_k2;
  delete _for_cur_k1;

  delete _cli_sh_k2;
  delete _cli_sh_k1;
  delete _cli_cur_k2;
  delete _cli_cur_k1;

  delete _clifo_rel;
}             

void TSelection_mask::set_handler(short fld_id, CONTROL_HANDLER handler)
{                              
  const int pos = id2pos(fld_id);
  if (pos >= 0)
    fld(pos).set_handler(handler);
}

TCursor_sheet& TSelection_mask::cur_sheet() const
{             
  TCursor_sheet* cs;
  if (get_key() == 1) cs = get_who() == 'C' ? _cli_sh_k1 : _for_sh_k1;
  else                cs = get_who() == 'C' ? _cli_sh_k2 : _for_sh_k2;
  
  CHECK(cs, "Can't use a NULL TCursor_sheet");
  return *cs;
}                 

void TSelection_mask::reset_sheets()
{
  _cli_sh_k1->uncheck(-1);
  _cli_sh_k2->uncheck(-1);
  if (_for_sh_k1)
  {
    _for_sh_k1->uncheck(-1);
    _for_sh_k2->uncheck(-1);
  }  
  reset(SC_CFCODFR);
  reset(SC_CFCODTO);
  reset(SC_NSEL);
}


// Seleziona tutti i clienti con codice compreso tra due estremi
void TSelection_mask::select_clifo_range(long from, long to)
{
  TCursor_sheet& c = cur_sheet();
  const long items = c.items();
  const int key = get_key();
  TString s_from(50), s_to(50);
  
  if (from > to)                    // Controlla limiti
  {
    long tmp = to;
    to = from;
    from = tmp;
  }                           

  s_from = c.row(from).get(3-key);  // Legge ragione sociale iniziale
  s_to = c.row(to).get(3-key);      // ... e finale
  
  bool cod1ok = FALSE, cod2ok = FALSE;
  long last = 0;
  long firs = 0;
  
  for (long i = 0; i < items; i++)
  {
    TToken_string& tt = c.row(i);
    const long cod = tt.get_long(key);  
    bool add;
    if (key == 2)
    {
      const char* s = tt.get(1);
      add = s_from <= s && s_to >= s;
    }  
    else
      add = cod >= from && cod <= to;
    
    if (add)
    {
      c.check(i);
      if (firs == 0) 
        firs = cod;
      last = cod; 
    }
    else 
      c.uncheck(i);
    
    if (cod == from) cod1ok = TRUE; 
    if (cod == to)   cod2ok = TRUE; 
  }     
  
  if (!cod1ok) from = firs;                     
  if (!cod2ok) to   = last;                     
  
  set(SC_CFCODFR, from);
  set(SC_CFCODTO, to);
  set(SC_NSEL, c.checked());
}

// Cerca il primo e l'ultimo cliente selezionati
void TSelection_mask::set_clifo_limits()
{  
  long first = 0, last = 0, nsel = 0;
  
  TCursor_sheet& c = cur_sheet();
  const long items = c.items();
  const int key = get_key();
  
  for (int i = 0; i < items; i++) if (c.checked(i))
  {
    TToken_string& t = c.row(i);
    const long kod = t.get_long(key);
    if (first == 0) 
    {
      first = last = kod; 
    }               
    else
    {
      if (first > kod) first = kod; 
      if (last < kod) last = kod; 
    }  

    nsel++;
  }   
  set(SC_CFCODFR, first);
  set(SC_CFCODTO, last);
  set(SC_NSEL,    nsel);
}

// handlers
bool TSelection_mask::bfrom_handler(TMask_field& f, KEY k)
{                                                
  if (k == K_SPACE)
  {  
    TSelection_mask& m = (TSelection_mask&)f.mask();
    TCursor_sheet& c = m.cur_sheet();
    
    c.disable_check();
    if (c.run() == K_ENTER)
    {      
      TToken_string& t = c.row(c.selected());
      const long cod1 = t.get_long(m.get_key());
      const long cod2 = m.get_long(SC_CFCODTO);
      m.set(SC_CFCODFR, cod1);
      m.select_clifo_range(cod1, cod2);
    }
  }
  return TRUE;
}

bool TSelection_mask::bto_handler(TMask_field& f, KEY k)
{
  if (k == K_SPACE)
  {
    TSelection_mask& m = (TSelection_mask&)f.mask();
    TCursor_sheet& c = m.cur_sheet();
    c.disable_check();
    if (c.run() == K_ENTER)
    {      
      TToken_string& t = c.row(c.selected());
      const long cod2 = t.get_long(m.get_key());
      const long cod1 = m.get_long(SC_CFCODFR); 
      m.set(SC_CFCODTO, cod2);
      m.select_clifo_range(cod1, cod2);
    }
  }
  return TRUE;
}

bool TSelection_mask::ffrom_handler(TMask_field& f, KEY k)
{    
  TSelection_mask& m = (TSelection_mask&)f.mask();

  if (k == K_TAB && f.focusdirty())
  {
    const long cod1 = atol(f.get());
    const long cod2 = m.get_long(SC_CFCODTO); 
    m.select_clifo_range(cod1, cod2);
  }
  else 
    if (k == K_F9)
    {
      TMask_field& f = m.field(SC_CFBUTFR);
      f.on_hit();
    }  
  
  return TRUE;
}

bool TSelection_mask::fto_handler(TMask_field& f, KEY k)
{                                                
  TSelection_mask& m = (TSelection_mask&)f.mask();

  if (k == K_TAB && f.focusdirty())
  {
    const long cod1 = m.get_long(SC_CFCODFR); 
    const long cod2 = atol(f.get());
    m.select_clifo_range(cod1, cod2);
  }
  else 
    if (k == K_F9)
    {
      TMask_field& f = m.field(SC_CFBUTTO);
      f.on_hit();
    }  
  return TRUE;
}

bool TSelection_mask::breset_handler(TMask_field& f, KEY k)
{
  if (k == K_SPACE)
  {
    TSelection_mask& m = (TSelection_mask&)f.mask();
    m.reset_sheets();
  }  
  return TRUE;
}

bool TSelection_mask::bselect_handler(TMask_field& f, KEY k)
{
  if (k == K_SPACE)
  {
    TSelection_mask& m = (TSelection_mask&)f.mask();
    TCursor_sheet& c = m.cur_sheet();
    c.enable_check();
    c.run();
    m.set_clifo_limits();
  }
  return TRUE;
}

bool TSelection_mask::rclifo_handler(TMask_field& f, KEY k)
{   
  if (k == K_SPACE)
  {
    TSelection_mask& m = (TSelection_mask&)f.mask();
    m.set_who(f.get()[0]);
    m.reset_sheets();
  }
  return TRUE;
}

bool TSelection_mask::rsortcf_handler(TMask_field& f, KEY k)
{   
  if (k == K_SPACE)
  {
    TSelection_mask& m = (TSelection_mask&)f.mask();
    m.set_key(atoi(f.get()));
    m.reset_sheets();
  }
  return TRUE;
}