#include "scselect.h"                    

///////////////////////////////////////////////////////////////////////////////
// TCursor_sheet_recno                                                       //
///////////////////////////////////////////////////////////////////////////////

TCursor_sheet_recno::TCursor_sheet_recno(TCursor * cursor, const char* fields,
            const char * title, const char * head, byte buttons)
: TCursor_sheet(cursor, fields, title, head, buttons)
{
  _recnos.reset();
} 

bool TCursor_sheet_recno::on_key(KEY k)
{
    switch(k)
    {
    case K_SPACE: 
    {
      *cursor() = selected(); // Posiziona il cursore 
      rec_check(cursor()->file().recno(), !checked(selected()));
      break;
    }
    case K_F2: 
      rec_uncheck(-1); 
      break;
    case K_F3:   
      rec_check(-1);
      break;
    default: 
      break;
    }
  return TCursor_sheet::on_key(k);
}

void TCursor_sheet_recno::rec_check(long n, bool on)
{
  if (n < 0)
  {
    if (on)
    {
      _recnos.set(cursor()->size()); // Force the size of Bit_array
      _recnos.set();
    } 
    else
      _recnos.reset();
  }     
  else           
      _recnos.set(n, on);
}

///////////////////////////////////////////////////////////////////////////////
// TSelection_mask                                                           //
///////////////////////////////////////////////////////////////////////////////

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);
  
  _cli_cur_k1 = new TCursor(_clifo_rel, "TIPOCF=\"C\"", 1);
  _cli_cur_k2 = new TCursor(_clifo_rel, "TIPOCF=\"C\"", 2);
  
  
  _cli_sh_k1 = new TCursor_sheet_recno(_cli_cur_k1, " |CODCF|RAGSOC", "Selezione clienti per codice",
                                 "@1|Codice|Ragione Sociale@50");
  _cli_sh_k2 = new TCursor_sheet_recno(_cli_cur_k2, " |RAGSOC|CODCF", "Selezione clienti per ragione sociale",
                                 "@1|Ragione Sociale@50|Codice");
  
  if (id2pos(SC_CLIFO) >= 0)
  {
    _for_cur_k1 = new TCursor(_clifo_rel, "TIPOCF=\"F\"", 1);
    _for_cur_k2 = new TCursor(_clifo_rel, "TIPOCF=\"F\"", 2);
    _for_sh_k1 = new TCursor_sheet_recno(_for_cur_k1, " |CODCF|RAGSOC", "Selezione fornitori per codice",
                                   "@1|Codice|Ragione Sociale@50");
    _for_sh_k2 = new TCursor_sheet_recno(_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_recno& TSelection_mask::cur_sheet()
{             
  TCursor_sheet_recno* 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_recno");
  return *cs;
}                 

void TSelection_mask::reset_sheets()
{
  _cli_sh_k1->uncheck(-1);
  _cli_sh_k1->rec_uncheck(-1);
  _cli_sh_k2->uncheck(-1);
  _cli_sh_k2->rec_uncheck(-1);
  if (_for_sh_k1)
  {
    _for_sh_k1->uncheck(-1);
    _for_sh_k1->rec_uncheck(-1);
    _for_sh_k2->uncheck(-1);
    _for_sh_k2->rec_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_recno& c = cur_sheet();
  const long items = c.items();
  const int key = get_key();
  
  long nsel = 0;                                   
  
  if (to == 0l)
    to = c.row(items-1).get_long(key);
  if (from == 0l)
    from = c.row(0).get_long(key);

  if (from > to)
  {
    long tmp = to;
    to = from;
    from = tmp;
  }                           
  
  bool go = FALSE;  
  bool cod1ok = FALSE, cod2ok = FALSE;
  long last = 0l;
  long firs = 0l;
  
  for (long i = 0; i < items; i++)
  {
    TToken_string& tt = c.row(i);
    long cod = tt.get_long(key);  
    if (cod >= from && cod <= to)
    {
      c.check(i);
      c.rec_check(i);
      nsel ++;         
      if (firs == 0l) firs = cod;
      last = cod; 
    }
    else 
    {
      c.uncheck(i);
      c.rec_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,    nsel);
}

// Cerca il primo e l'ultimo cliente selezionati
void TSelection_mask::set_clifo_limits()
{  
  long first = 0, last = 0, nsel = 0;
  
  TCursor_sheet_recno& 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_recno& 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_recno& 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_recno& 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;
}