#ifndef __SCONTI_H
#include "sconti.h"
#endif

#ifndef __VEUML_H
#include "veuml.h"
#endif             

#ifndef __VERIG_H
#include "verig.h"
#endif             

#ifndef __TCLIFOR_H
#include "tclifor.h"
#endif

#ifndef __CONFIG_H
#include "config.h"
#endif

#ifndef __VECONF_H
#include "veconf.h"
#endif

#ifndef __TABUTIL_H
#include <tabutil.h>
#endif

HIDDEN const real CENTO(100.0);

bool TCond_vendita::set_sconto( const char * exp, bool signal  )
{
  TString80 goodexp;
  bool valid = TRUE;
  
  // Elimina gli spazi molesti
//  work.strip_spaces( );
  if (exp && *exp)
  {
    TString80 num;
    bool dec = FALSE;      // Flag che indica se si attende l'inizio di un numero
    bool startnum = TRUE;  // Flag che indica se siamo all'inizio di un numero   
    int errorchar = ' ';
    
    _molt_sconto = 1.0;
    // Flag che indica se sono nella parte decimale di un numero
    for (const char * s  = exp; *s  && errorchar == ' '; s++)
    { 
      const char c = *s;
      switch(c)
      {
      case '+': 
      case '-':
        // Se ero in in numero ...
        if( !startnum )
        {
          // Aggiunge il numero alla sequenza
          real newval( num );
          _molt_sconto *= ( CENTO - newval ) / CENTO;
          goodexp << num;
        }
        // Inizia il nuovo numero
        num = (c == '-') ? "-" : "+";  
        startnum = TRUE;
        dec = FALSE;
        break;         
      case '0':  
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':
        num << c;
        startnum = FALSE;
        break;
      case '.':
      case ',':
        if(!dec)
        {
          if( startnum )
            num << '0';        // Se occorreva un numero ci metto lo 0
          num << '.';          // Interpreto la virgola come punto
          dec = TRUE;       
          startnum = TRUE;
        }
        else
          errorchar = c;        // Se siamo gi` nella parte decimale segnala un errore
        break;
      case ' ':
        break;
      default:
        errorchar = c;
        break;         
      }
    }
    // Controlla la validita`
    valid = errorchar == ' ';
    
    if (valid)
    {
      // Aggiunge l'ultimo numero preso
      real lastval( num ); 
      _molt_sconto *= ( CENTO - lastval ) / CENTO;
      goodexp << num; // Assegna la nuova espressione formattata bene     
    }
    else
    {
      if (signal)          // Se richiesto segnala l'errore
        warning_box( "Espressione di sconto non valida. Errore sul carattere %c.", errorchar);
      _molt_sconto = 1.0;  // Azzera la sequenza di percentuali
      goodexp = "";
    }
  }
  _sconto = goodexp;
  if (_load_mask && _riga && _riga->id2pos(FR_SCONTO) >= 0 && _riga->field(FR_SCONTO).active())
    _riga->set(FR_SCONTO, _sconto);
  return valid;
}

void TCond_vendita::set_prezzo(const real & prezzo, const char * val_rif)

{                                  
  _prezzo = prezzo;

  if (_prezzo != ZERO)
  {
    TString16 valuta(_testa->get(F_CODVAL));
    TString16 valuta_rif(val_rif);
                                 
    if (valuta == "LIT") valuta.cut(0);                             
    if (valuta_rif == "LIT") valuta_rif.cut(0);                             
    if (valuta != valuta_rif)
    {    
      if (valuta_rif.not_empty())
        _prezzo *= _condv.get_real("CAMBIO");
      
      real cambio(_testa->get(F_CAMBIO));
      
      if (cambio == ZERO)
        cambio = 1.0;
      _prezzo /= cambio;
      _prezzo.round(cambio == 1.0 ? 0 : 3);
    }
  }
  if (_load_mask && _riga && _riga->id2pos(FR_PREZZO) >= 0 && _riga->field(FR_PREZZO).active())
    _riga->set(FR_PREZZO, _prezzo);
}

void TCond_vendita::set_provv(const real & provv)

{
  _provv = provv;
  if (_load_mask && _riga && _riga->id2pos(FR_PERCPROV) >= 0 && _riga->field(FR_PERCPROV).active())
    _riga->set(FR_PERCPROV, _provv);
}

void TCond_vendita::set_iva(const TString & codiva)

{
  _codiva = codiva;
  if (_load_mask && _riga && _riga->id2pos(FR_CODIVA) >= 0 && _riga->field(FR_CODIVA).active())
    _riga->set(FR_CODIVA, _codiva);
}

bool TCond_vendita::cerca( int tiporicerca )
{
  if( config_ditta().get_bool( "GES", "ve", tiporicerca ) )
  {
    // Se h attiva la gestione contratti ...
    _condv.setkey( 1 );
    _condv.zero( );
    switch( tiporicerca )
    {
      case A_CONTRATTI:          
      {
        const TString16 codcont(testa().get(F_CODCONT));
        
        if (codcont.empty())
          return FALSE;
        _condv.put("TIPO", "C");
        if(config_ditta().get_bool("GESSCONCC", "ve"))
        {
          _condv.put("TIPOCF", clifo().tipocf());
          _condv.put("CODCF", clifo().codcf());  
         }
        _condv.put("COD", codcont);  
      }
      break;
      case A_LISTINI:                                    
        {
          const TString16 codlist(testa().get(F_CODLIST));
          
          if (codlist.empty())
            return FALSE;
          _condv.put("TIPO", "L");
            // Se in ditta h abilitata la gestione della categoria di vendita in chiave 
            // al listino, la carico con gioia      
          if( config_ditta().get_bool("GESLISCV", "ve"))
            _condv.put("CATVEN", testa().get(F_CATVEN));
          _condv.put("COD", codlist);
        }
        break;
      case A_OFFERTE:
        {
          const TString16 codcamp(testa().get(F_CODCAMP));
          
          if (codcamp.empty())
            return FALSE;
          _condv.put("TIPO", "O");
          _condv.put("COD", codcamp);
        }
        break;
    }
    if( _condv.read( ) == NOERR )
    { 
//      _rcondv.setkey( 2 );
        
      const bool gest_scagl = _condv.get_bool("GESTSCAGL");
      const TString16 seqricrighe( _condv.get( "SEQRIC" ) );
      bool found = FALSE;
      

      for( int i = 0; !found && i < seqricrighe.len( ); i ++ )
      {
        _rcondv.zero( );
        _rcondv.put( "TIPO", _condv.get( "TIPO"));
        _rcondv.put( "CATVEN", _condv.get( "CATVEN"));
        _rcondv.put( "TIPOCF", _condv.get( "TIPOCF"));
        _rcondv.put( "CODCF", _condv.get( "CODCF"));
        _rcondv.put("COD", _condv.get("COD"));  
        if( _condv.get_bool( "GESTUM" ) )
          _rcondv.put( "UM", riga().get(FR_UMQTA));
        if (gest_scagl)
          _rcondv.put("NSCAGL", 1);
        
        char ricerca = seqricrighe[ i ];
        _rcondv.put( "TIPORIGA", ricerca );
        switch( ricerca )
        {
          case 'A':              
            {
              const TString codriga = riga().get(FR_CODART);  
          
              _rcondv.put( "CODRIGA", codriga);
              if (_rcondv.read() != NOERR &&
                  _rcondv.prev() == NOERR &&
                  _rcondv.get("TIPORIGA")[0] == 'A')
              {
                  const TString cod_found(_rcondv.get("CODRIGA"));
                
                  return cod_found.compare(codriga, cod_found.len()) == 0;
              }
            }
            break;
          case 'R':
            _rcondv.put("CODRIGA", anamag().get( "RAGGFIS"));
            _rcondv.read();
            break;
          case 'S':                       
            {
              _rcondv.put( "CODRIGA", anamag().get("GRMERC"));
              _rcondv.read( );              
            }
            break;
          case 'G':                       
            {
              _rcondv.put( "CODRIGA", anamag().get("GRMERC").left(3));
              _rcondv.read( );              
            }
            break;
          default:
            break;
        }                       
        found = _rcondv.good();
      }
      if (found && gest_scagl)
      {                   
        TRectype rec(_rcondv.curr());
        int last_scagl = 0;      
        int scagl = _rcondv.get_int("NSCAGL");
        const real qta(_riga->get_real(FR_QTA));
        real qta_lim(_rcondv.get_real("QLIM"));
        
        while (_rcondv.good() && scagl > last_scagl && qta_lim > ZERO && qta > qta_lim)
        {                    
          if (_rcondv.next() == NOERR)
          {
            last_scagl = scagl;
            scagl = _rcondv.get_int("NSCAGL");
            qta_lim =_rcondv.get_real("QLIM");
            rec = _rcondv.curr();
          }
        }
        _rcondv.read(rec);
      }                                                                  
      
      return found;
    }
  }
  // Ricerca fallita
  return FALSE;
}
    
// Probabilmente dovrebbe lavorare sulla maschera, ma per ora la lasciamo cosl
void TCond_vendita::ricerca(bool load_um_only, bool load_scagl_only)
{
  TString codart = anamag().get( "CODART" );
  const TString codriga = riga().get( FR_CODART );
  _load_mask = !load_um_only && !load_scagl_only;  
  
  if(anamag().bad() || codriga != codart )
  {
    anamag().setkey(1);
    anamag().put("CODART", codriga);
    if (anamag().read() != NOERR)
    {                                     
//      if (full_load)
//      {
        set_prezzo(ZERO);
        set_sconto("");  
        set_iva("");
        set_provv(ZERO);
//      }
      return;
    }  
  }                  
  codart = umart().get( "CODART" );         
  const TString16 umriga(riga().get(FR_UMQTA));
  const TString16 um(umart().get("UM"));
  if (umart().bad() || codart != codriga || um != umriga)
  { 
    umart().setkey(2);
    umart().put("CODART", codriga);
    umart().put("UM", um);
    if (umart().read != NOERR)
      umart().zero();
  }                                  

  const bool found_condv = cerca(A_CONTRATTI) || cerca(A_OFFERTE) || cerca(A_LISTINI);
  const bool cv_scagl = _condv.get_bool("GESTSCAGL");
  const bool cv_um = _condv.get_bool("GESTUM");

  if (found_condv)
  {
    _load_mask |= load_scagl_only && cv_scagl;
    _load_mask |= load_um_only && cv_um;
    set_prezzo(_rcondv.get_real("PREZZO"), _condv.get("CODVAL"));
    _load_mask = !load_um_only && !load_scagl_only;  
  }
  else
//    if (full_load)
      set_prezzo(umart().get_real("PREZZO")); 
      
      
//  if (full_load)     
//  {
    if (_ivarid)
      set_iva(anamag().get("CODIVAR"));
    else
      set_iva(anamag().get("CODIVA"));
//  }

  const char gestione = config_ditta().get_char( "GESSCORIGA", "ve" );                        
  const bool sco_scagl =  config_ditta().get_bool("GESCOSCA", "ve");
  const bool sco_um_gest =  config_ditta().get_bool("GESSCORIGAUM", "ve");
      
//  if (!full_load && gestione != 'A' && !sco_scagl)
//  {
//    if (gestione == 'L' && found_condv)
//      set_sconto(_rcondv.get("SCONTO"));
//}
//  else
  {
    switch (gestione)
    {
      case 'N':
        // Sconti di riga non gestiti
        set_sconto(""); 
        break;
      case 'L':
        // Percentuale su contratti/offerte/listini/anagrafica   
        if (found_condv)
        {
          _load_mask |= load_scagl_only && cv_scagl;
          _load_mask |= load_um_only && cv_um;
          set_sconto(_rcondv.get("SCONTO"));
          _load_mask = !load_um_only && !load_scagl_only;  
        }
        else
          set_sconto(anamag().get("SCONTO"));
        break;
      case 'A':
        {
        // Posiziono l'anagrafica
          const char rigakey = config_ditta().get_char( "SCORIGAKEY", "ve" );                        
  
          _sconti.setkey(1);
          _sconti.put("TIPO", "R");
          if( config_ditta().get_bool("GESSCORIGACV", "ve"))
            _sconti.put("CODCAT", clifo().get(LF_CFVEN, "CATVEN"));
          if (sco_um_gest)
            _sconti.put("UM", riga().get( FR_UMQTA));
          _sconti.put("TIPORIGA", rigakey);

          if (sco_scagl)
            _sconti.put("NSCAGL", 1);

          switch (rigakey)
          {
            case 'A':
              _sconti.put("CODART", codriga);
              _sconti.read();
              break;
            case 'R':
              _sconti.put("CODART", anamag().get("RAGGFIS"));
               _sconti.read();
              break;
            case 'C':                       
              {
                _sconti.put( "CODART", anamag().get("GRMERC"));
                _sconti.read( );              
              }
              break;
            case 'L':                       
              {
                _sconti.put("CODART", anamag().get("GRMERC").left(3));
                _sconti.read();              
              }
              break;
            default:
               error_box("Tipo di chiave righe sconti '%c' non valida!", rigakey);
            break;                                          
          }     
          
          const bool found = _sconti.good();
           
          if (found && sco_scagl)
          {                   
            TRectype rec(_sconti.curr());
            int last_scagl = 0;      
            int scagl = _sconti.get_int("NSCAGL");
            const real qta(_riga->get_real(FR_QTA));
            real qta_lim(_sconti.get_real("QLIM"));
            
            while (_sconti.good() && scagl > last_scagl && qta_lim > ZERO && qta > qta_lim)
            {                    
              if (_sconti.next() == NOERR)
              {
                last_scagl = scagl;
                scagl = _sconti.get_int("NSCAGL");
                qta_lim =_sconti.get_real("QLIM");
                rec = _sconti.curr();
              }
            }
            _rcondv.read(rec);
          }                                                                  
          if (!found)
            _sconti.zero();
          _load_mask |= load_scagl_only && sco_scagl;
          _load_mask |= load_scagl_only && sco_um_gest;
          set_sconto(_sconti.get("SCONTO"));
          _load_mask = !load_um_only && !load_scagl_only;  
        }
        break; 
      case 'C':
        set_sconto(clifo().get(LF_CFVEN, "SCONTO"));
        break;
      default:
        error_box("Tipo di gestione sconti '%c' non valido!", gestione );
        break;                                          
    }                                  
  }
  
  if (_riga && _riga->id2pos(FR_PERCPROV) >= 0 && _riga->field(FR_PERCPROV).active())
  {
    const TString16 codage(_testa->get(F_CODAG));                 
    
    if (codage.not_empty())
    {                                                             
      TTable age("AGE");
                    
      age.put("CODTAB", codage);
      if (age.read() == NOERR)
      {
        char tipoprovv = age.get("S6")[0];
        
        if (tipoprovv <= ' ')
          tipoprovv = config_ditta().get_char( "AGETIPOPERC", "ve" );
          
//        if (!full_load)
//        {
//          if (tipoprovv == 'L' && found_condv)
//            set_provv(_rcondv.get_real("PERCPROVV"));
//        }
//        else
        {
          switch (tipoprovv)
          {
            case 'A':
              set_provv(age.get_real("R0"));
              break;
            case 'C':
              set_provv(real(clifo().get(LF_CFVEN, "PERCPROVV")));
              break;                                              
            case 'L':
              if (found_condv)
              {
                _load_mask |= load_scagl_only && sco_scagl;
                _load_mask |= load_scagl_only && sco_um_gest;
                set_provv(_rcondv.get_real("PERCPROVV"));
              }
              else
                set_provv(anamag().get_real("PERCPROVV"));
              break;
            case 'V':
              {
                TString16 catven(testa().get(F_CATVEN));
                  
                if (catven.empty())
                  catven = clifo().get(LF_CFVEN, "CATVEN");
                  
                if (catven.not_empty())
                {  
                  TTable cve("CVE");
                      
                  cve.put("CODART", codage);
                  if (cve.read() == NOERR)
                    set_provv(cve.get_real("R0"));
                }
              }
              break;
            default:
              error_box("Tipo di gestione provvigioni '%c' non valido!", tipoprovv );
              break;
          }
        }
      }
    }
  }
}

TCond_vendita::TCond_vendita(TCliFor * clifo, TConfig * ditta, TMask * testa, TMask * riga,
                             TLocalisamfile * anamag, TLocalisamfile * umart)
             : _clifo(clifo), _testa(testa), _riga(riga),
               _condv( LF_CONDV ), _rcondv( LF_RCONDV ), _sconti( LF_SCONTI ),
               _anamag(anamag), _umart(umart), _config_ditta(ditta), _ivarid(FALSE)
{
}
    
