#ifndef __UTILITY_H
#include <utility.h>
#endif

#ifndef __PCONTI_H
#include <pconti.h>
#endif


#include "sc2201.h"

///////////////////////////////////////////////////////////////////////////////
// TSelection_ext_mask                                                       //
///////////////////////////////////////////////////////////////////////////////

TSelection_ext_mask::TSelection_ext_mask(const char* name) : TSelection_mask(name),
           _pcon_rel(NULL), _pcon_cur_k1(NULL), _pcon_cur_k2(NULL), _pcon_sh_k1(NULL), _pcon_sh_k2(NULL)
{     
  _pcon_rel  = new TRelation(LF_PCON);
  
  _pcon_cur_k1 = new TCursor(_pcon_rel, "", 1);
  _pcon_cur_k2 = new TCursor(_pcon_rel, "", 2);
  
  
  _pcon_sh_k1 = new TCursor_sheet(_pcon_cur_k1, " |GRUPPO|CONTO|SOTTOCONTO|DESCR", "Selezione conti per gruppo/conto/sottoconto",
                                 "@1|Gruppo|Conto|Sottoconto|Descrizione@50");
  _pcon_sh_k2 = new TCursor_sheet(_pcon_cur_k2, " |DESCR|GRUPPO|CONTO|SOTTOCONTO", "Selezione conti per descrizione",
                                 "@1|Descrizione@50|Gruppo|Conto|Sottoconto");

  set_handler(SC_CLIFO,   rpcon_handler);  // Redefined handler...
  set_handler(SC_SORTCFPCON,rsortpcon_handler); // Redefined handler...
  set_handler(SC_PCONBUTFR, bfrompcon_handler); // New handler...
  set_handler(SC_PCONBUTTO, btopcon_handler);   // New handler...
  set_handler(SC_SELECT,  bselectpcon_handler); // Redefined handler...
  set_handler(SC_RESET,   bresetpcon_handler);  // Redefined handler...
  set_handler(SC_PCONCODFR3, ffrompcon_handler); // New handler...
  set_handler(SC_PCONCODTO3, ftopcon_handler);   // New handler...
}

TSelection_ext_mask::~TSelection_ext_mask()
{
  delete _pcon_sh_k2;
  delete _pcon_sh_k1;
  delete _pcon_cur_k2;
  delete _pcon_cur_k1;
  delete _pcon_rel;
}             

TCursor_sheet& TSelection_ext_mask::cur_sheet()
{             
  TCursor_sheet* cs;
  if (get_key() == 1) cs = get_who() == 'P' ? _pcon_sh_k1 : NULL;
  else                cs = get_who() == 'P' ? _pcon_sh_k2 : NULL;
  
  if (get_who() != 'P')
    return TSelection_mask::cur_sheet();
  CHECK(cs, "Can't use a NULL TCursor_sheet");
  return *cs;
}                 

void TSelection_ext_mask::reset_sheets()
{
  _pcon_sh_k1->uncheck(-1);
  _pcon_sh_k2->uncheck(-1);
  TSelection_mask::reset_sheets();
  reset(SC_PCONCODFR1);
  reset(SC_PCONCODFR2);
  reset(SC_PCONCODFR3);
  reset(SC_PCONCODTO1);
  reset(SC_PCONCODTO2);
  reset(SC_PCONCODTO3);
}

void TSelection_ext_mask::select_pcon_range(TString& desfr, TString& desto)
{
  TCursor_sheet& c = cur_sheet();
  const long items = c.items();
  const int key = get_key();
  
  TCursor* crs = c.cursor();
  TRectype& rec = crs->file().curr();
  rec.zero();
  rec.put(PCN_DESCR,desfr);
  
  const TRecnotype start = crs->read(_isgteq);
  int grf = rec.get_int(PCN_GRUPPO);
  int cof = rec.get_int(PCN_CONTO);
  long sof = rec.get_long(PCN_SOTTOCONTO);
  int grt, cot;
  long sot;
  rec.zero();
  rec.put(PCN_DESCR,desto);
  TRectype recx(rec);
  TRecnotype end = crs->read(_isgteq);
  if (rec != recx) 
  {
    end--;
    (*crs)-=1;
  }
  grt = rec.get_int(PCN_GRUPPO);
  cot = rec.get_int(PCN_CONTO);
  sot = rec.get_long(PCN_SOTTOCONTO);
  c.uncheck(-1);
  for (long i = start; i <= end; i++)
    //if (!c.checked(i))
      c.check(i);
  set(SC_PCONCODFR1, grf);
  set(SC_PCONCODFR2, cof);
  set(SC_PCONCODFR3, sof);
  set(SC_PCONCODTO1, grt);
  set(SC_PCONCODTO2, cot);
  set(SC_PCONCODTO3, sot);
  set(SC_NSEL,    c.checked());
}

void TSelection_ext_mask::select_pcon_range(int grf, int cof,long sof,int grt,int cot, long sot)
{
  TCursor_sheet& c = cur_sheet();
  const long items = c.items();
  const int key = get_key();
  TString desfr,desto;
  
  TCursor* crs = c.cursor();
  TRectype& rec = crs->file().curr();
  rec.zero();
  rec.put(PCN_GRUPPO,grf);
  rec.put(PCN_CONTO,cof);
  rec.put(PCN_SOTTOCONTO,sof);
  
  const TRecnotype start = crs->read(_isgteq);
  grf = rec.get_int(PCN_GRUPPO);
  cof = rec.get_int(PCN_CONTO);
  sof = rec.get_long(PCN_SOTTOCONTO);
  rec.zero();
  if (grt==0 && cot==0 && sot==0)      
  { 
     TToken_string& t = c.row(items-1);
     grt = t.get_int(key);
     cot = t.get_int(key+1);
     sot = t.get_long(key+2);
  }
  rec.put(PCN_GRUPPO,grt);
  rec.put(PCN_CONTO,cot);
  rec.put(PCN_SOTTOCONTO,sot);
  TRectype recx(rec);
  TRecnotype end = crs->read(_isgteq);
  if (rec != recx) 
  {
    end--;
    (*crs)-=1;
  }
  grt = rec.get_int(PCN_GRUPPO);
  cot = rec.get_int(PCN_CONTO);
  sot = rec.get_long(PCN_SOTTOCONTO);
  c.uncheck(-1);
  for (long i = start; i <= end; i++)
    //if (!c.checked(i))
      c.check(i);
  set(SC_PCONCODFR1, grf);
  set(SC_PCONCODFR2, cof);
  set(SC_PCONCODFR3, sof);
  set(SC_PCONCODTO1, grt);
  set(SC_PCONCODTO2, cot);
  set(SC_PCONCODTO3, sot);
  set(SC_NSEL,    c.checked());
}

void TSelection_ext_mask::set_pcon_limits()
{  
  int gf=0,gl=0,cf=0,cl=0;
  long sf=0L,sl=0L;
  
  TCursor_sheet& c = cur_sheet();
  const long items = c.items();
  const int key = get_key();
  long first = -1, last = -1;
  long nsel = 0L;
  
  // Ricerca veloce di estremi (vale solo su GR/CO/SO)
  for (long i = 0; i < items; i++) 
    if (c.checked(i))
    {
      if (first == -1)
        first = i;
      nsel ++;
    }
  if (first != -1)  //Optimization... If nothing was found previously skip this test.
    for (long j = (items-1); j >= 0 ; j--)
      if (c.checked(j))
        if (last == -1)
        {
          last = j;
          break;
        }
  if (first!= -1 && last != -1) // Something selected?
  {
    TToken_string fitem(c.row(first));
    TToken_string litem(c.row(last));
    gf = fitem.get_int(key);
    cf = fitem.get_int(key+1);
    sf = fitem.get_long(key+2);
    gl = litem.get_int(key);
    cl = litem.get_int(key+1);
    sl = litem.get_long(key+2);
    if (gf > gl || (gf==gl && cf > cl) || (gf==gl && cf==cl && sf>sl))
    {     // Swap them...
      int t1 = gf,t2 = cf;long t3 = sf;
      gf=gl;cf=cl;sf=sl; 
      gl=t1;cl=t2;sl=t3;
    }
  }
  set(SC_PCONCODFR1, gf);
  set(SC_PCONCODFR2, cf);
  set(SC_PCONCODFR3, sf);
  set(SC_PCONCODTO1, gl);
  set(SC_PCONCODTO2, cl);
  set(SC_PCONCODTO3, sl);
  set(SC_NSEL,    nsel);
}

bool TSelection_ext_mask::bfrompcon_handler(TMask_field& f, KEY k)
{                                                
  if (k == K_SPACE)
  {  
    TSelection_ext_mask& m = (TSelection_ext_mask&)f.mask();
    TCursor_sheet& c = m.cur_sheet();
    const int key = m.get_key();
    c.disable_check();
    if (c.run() == K_ENTER)
    {      
      TToken_string& t = c.row(c.selected());
      int grf,grt,cof,cot;
      long sof,sot;
      grf =t.get_int(key);
      cof =t.get_int(key+1);
      sof =t.get_long(key+2);
      grt = m.get_int(SC_PCONCODTO1);
      cot = m.get_int(SC_PCONCODTO2);
      sot = m.get_long(SC_PCONCODTO3);
      m.set(SC_PCONCODFR1, grf);
      m.set(SC_PCONCODFR2, cof);
      m.set(SC_PCONCODFR3, sof);
      if (m.get_key() == 2)
      {                     
        TLocalisamfile pcon(LF_PCON);
        pcon.zero();
        pcon.put(PCN_GRUPPO,grf);
        pcon.put(PCN_CONTO,cof);
        pcon.put(PCN_SOTTOCONTO,sof);
        pcon.read();
        TString d1(t.get(1)),d2(pcon.get(PCN_DESCR));
        m.select_pcon_range(d1,d2);
      }
      else
        m.select_pcon_range(grf,cof,sof,grt,cot,sot);
    }
  }
  return TRUE;
}

bool TSelection_ext_mask::btopcon_handler(TMask_field& f, KEY k)
{
  if (k == K_SPACE)
  {
    TSelection_ext_mask& m = (TSelection_ext_mask&)f.mask();
    TCursor_sheet& c = m.cur_sheet();
    const int key = m.get_key();
    c.disable_check();
    if (c.run() == K_ENTER)
    {      
      TToken_string& t = c.row(c.selected());
      int grf,grt,cof,cot;
      long sof,sot;
      grt =t.get_int(key);
      cot =t.get_int(key+1);
      sot =t.get_long(key+2);
      grf = m.get_int(SC_PCONCODFR1);
      cof = m.get_int(SC_PCONCODFR2);
      sof = m.get_long(SC_PCONCODFR3);
      m.set(SC_PCONCODTO1, grt);
      m.set(SC_PCONCODTO2, cot);
      m.set(SC_PCONCODTO3, sot);
      if (m.get_key() == 2)  
      {                            
        TLocalisamfile pcon(LF_PCON);
        pcon.zero();
        pcon.put(PCN_GRUPPO,grf);
        pcon.put(PCN_CONTO,cof);
        pcon.put(PCN_SOTTOCONTO,sof);
        pcon.read();
        TString d1(pcon.get(PCN_DESCR)),d2(t.get(1));
        m.select_pcon_range(d1,d2);
      }
      else
        m.select_pcon_range(grf,cof,sof,grt,cot,sot);
    }
  }
  return TRUE;
}

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

  if (k == K_TAB && f.focusdirty())
  {
    int grf,grt,cof,cot;
    long sof,sot;
    grf = m.get_int(SC_PCONCODFR1);
    cof = m.get_int(SC_PCONCODFR2);
    sof = m.get_long(SC_PCONCODFR3);
    grt = m.get_int(SC_PCONCODTO1);
    cot = m.get_int(SC_PCONCODTO2);
    sot = m.get_long(SC_PCONCODTO3);
    if (m.get_key() == 2)
    {
      TLocalisamfile pcon(LF_PCON);
      TString dfr,dto;
      pcon.zero();
      pcon.put(PCN_GRUPPO,grf);
      pcon.put(PCN_CONTO,cof);
      pcon.put(PCN_SOTTOCONTO,sof);
      pcon.read();    
      dfr = pcon.get(PCN_DESCR);
      pcon.put(PCN_GRUPPO,grf);
      pcon.put(PCN_CONTO,cof);
      pcon.put(PCN_SOTTOCONTO,sof);
      pcon.read();    
      dto = pcon.get(PCN_DESCR);
      m.select_pcon_range(dfr,dto);
    }
    else
      m.select_pcon_range(grf,cof,sof,grt,cot,sot);
  }
  else 
    if (k == K_F9)
    {
      TMask_field& f = m.field(SC_PCONBUTFR);
      f.on_hit();
    }  
  
  return TRUE;
}

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

  if (k == K_TAB && f.focusdirty())
  {
    int grf,grt,cof,cot;
    long sof,sot;
    grf = m.get_int(SC_PCONCODFR1);
    cof = m.get_int(SC_PCONCODFR2);
    sof = m.get_long(SC_PCONCODFR3);
    grt = m.get_int(SC_PCONCODTO1);
    cot = m.get_int(SC_PCONCODTO2);
    sot = m.get_long(SC_PCONCODTO3);
    if (m.get_key() == 2)
    {
      TLocalisamfile pcon(LF_PCON);
      TString dfr,dto;
      pcon.zero();
      pcon.put(PCN_GRUPPO,grf);
      pcon.put(PCN_CONTO,cof);
      pcon.put(PCN_SOTTOCONTO,sof);
      pcon.read();    
      dfr = pcon.get(PCN_DESCR);
      pcon.put(PCN_GRUPPO,grf);
      pcon.put(PCN_CONTO,cof);
      pcon.put(PCN_SOTTOCONTO,sof);
      pcon.read();    
      dto = pcon.get(PCN_DESCR);
      m.select_pcon_range(dfr,dto);
    }
    else
      m.select_pcon_range(grf,cof,sof,grt,cot,sot);
  }
  else 
    if (k == K_F9)
    {
      TMask_field& f = m.field(SC_PCONBUTTO);
      f.on_hit();
    }  
  return TRUE;
}

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

bool TSelection_ext_mask::bselectpcon_handler(TMask_field& f, KEY k)
{
  if (k == K_SPACE)
  {
    TSelection_ext_mask& m = (TSelection_ext_mask&)f.mask();
    TCursor_sheet& c = m.cur_sheet();
    c.enable_check();
    c.run();
    if (m.get_who() =='P')
      m.set_pcon_limits();
    else
      m.set_clifo_limits();
  }
  return TRUE;
}

bool TSelection_ext_mask::rpcon_handler(TMask_field& f, KEY k)
{   
  if (k == K_SPACE)
  {
    TSelection_ext_mask& m = (TSelection_ext_mask&)f.mask();
    char who = f.get()[0];
    m.set_who(who);
    if (who == 'P')
      m.set_key(1);
    m.reset_sheets();
  }
  return TRUE;
}

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