#include <xvt.h>

#ifndef __CHECKS_H
#include <checks.h>
#endif

#ifndef __CONFAPP_H
#include <confapp.h>
#endif

#ifndef __MSKSHEET_H
#include <msksheet.h>
#endif

#ifndef __RELATION_H
#include <relation.h>
#endif

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

#include "veconf.h"

#define SINTASSI "Usage: VE0 -2 -[1|2|3|4|5|6|7|8]"

class TConf_vendite : public TConfig_application
{
  int _current;

  static bool check_fields(TMask_field& f, KEY k);
  static bool check_fields_iva(TMask_field& f, KEY k);

	virtual const char * extra_modules() const {return "dt";}

public:

  virtual bool preprocess_config (TMask& mask, TConfig& config);
  virtual bool postprocess_config (TMask& mask, TConfig& config);
  virtual bool user_create( );

  TConf_vendite() : TConfig_application( CONFIG_DITTA ){ }
  virtual ~TConf_vendite( ){ }
};

bool TConf_vendite::check_fields(TMask_field& f, KEY k)
{
  if (k == K_TAB && f.focusdirty())
  {
    TString fld(f.get());
    TMask& m = f.mask();
    TToken_string t;
    if (fld == "-") return TRUE;
    for (short i=F_RICERCACR1;i<=F_RICERCAAN4;i++)
    {
      if (f.dlg() == i) continue;
      t.add(m.get(i));
    }
    if (t.find(fld) >= 0)
      return f.error_box("Immettere un gruppo di ricerca non ancora indicato nella sequenza");
  }
  return TRUE;
}

bool TConf_vendite::check_fields_iva(TMask_field& f, KEY k)
{
  if (k == K_ENTER)
  {
    TMask& m = f.mask();

    real tot = ZERO;

    for (short i = F_EX_PERCIVA1; i <= F_EX_PERCIVA5; i+=2)
      tot += m.get_real(i);

    if (tot != ZERO && tot != 100.0)
      return f.error_box("La somma delle percentuali di esclusione deve dare 100 oppure 0.");
  }
  return TRUE;
}

bool TConf_vendite::preprocess_config (TMask& mask, TConfig& config)
{
  disable_menu_item(M_FILE_NEW);

  switch (_current)
  {

  case 5: // solo per configurazione "e"
    {
      TToken_string ric(config.get("RICERCACR"));
      TString ana_items("AR|GM|SM|RF");
      int nor_order = 0, ana_order = 0;
      TString it;
      mask.set_handler(F_RICERCACR1,check_fields);
      mask.set_handler(F_RICERCACR2,check_fields);
      mask.set_handler(F_RICERCACR3,check_fields);
      mask.set_handler(F_RICERCACR4,check_fields);
      mask.set_handler(F_RICERCACR5,check_fields);
      mask.set_handler(F_RICERCAAN1,check_fields);
      mask.set_handler(F_RICERCAAN2,check_fields);
      mask.set_handler(F_RICERCAAN3,check_fields);
      mask.set_handler(F_RICERCAAN4,check_fields);
      for (it = ric.get();it.not_empty();it = ric.get())
      {
        if (ana_items.find(it) >= 0)
        {
          mask.set(F_RICERCAAN1+ana_order,it);
          if (ana_order==0) // Se e' la prima volta...
          {
            mask.set(F_RICERCACR1+nor_order,"AN");
            nor_order++;
          }
          ana_order++;
        }
        else
        {
          mask.set(F_RICERCACR1+nor_order,it);
          nor_order++;
        }
      }
    }
    break;
  case 6: // solo per configurazione "f"
      {
        mask.set_handler(F_EX_PERCIVA1,check_fields_iva); // Basta su uno che controlla tutti all'uscita della maschera
      }
    break;
  case 8:
    {
      TSheet_field& sf = mask.sfield(F_DOCS);  //prende lo sheet..
      const TMask& sm = sf.sheet_mask();       //..poi la maschera di sheet..
      bool found = true;
      for (int r = 0; found; r++)              //finch� ci sono valori c'� speranza!..
      {                                        //Ovvero legge i valori finch� ce ne sono e non sono nulli aggiornando i..
        FOR_EACH_MASK_FIELD(sm, j, f)          //..campi dello sheet
        {
          const TFieldref* fr = f->field();
          if (fr != NULL)
          {
            const TString& value = get_config()->get(fr->name(), NULL, r);
            if (value.empty() && f->dlg() == 101)
            {
              found = false;
              break;
            }
            else
            {
              sf.row(r).add(value, sf.cid2index(f->dlg()));
            }
          }
          sf.check_row(sf.items() - 1);   //metodo per ricaricare le descrizioni delle numerazioni
        } //FOR_EACH_MASK_FIELD
      } //for(int r=0...
    }
    break;

  default:
    break;
  }
  return true;
}


bool TConf_vendite::postprocess_config (TMask& mask, TConfig& config)
{
  enable_menu_item(M_FILE_NEW);

  switch (_current)
  {
  
  case 5: // solo per configurazione "e"
    {
      TToken_string ric;
      TString r;
      const KEY k = mask.last_key();
      bool tosave = k == K_ENTER || k == K_SAVE;

      if (!tosave && mask.dirty())
        tosave = yesno_box("Modifiche non registrate. Salvare?");

      if (!tosave)
        return FALSE;

      for (short i=F_RICERCACR1;i<=F_RICERCACR5;i++)
      {
        r = mask.get(i);
        if (r == "-") continue;
        if (r == "AN")
          for (short j=F_RICERCAAN1;j<=F_RICERCAAN4;j++)
          {
            r = mask.get(j);
            if (r == "-") continue;
            ric.add(r);
          }
        else
          ric.add(r);
      }
      config.set("RICERCACR",ric);
    }
    break;

  case 8:   //ve0200h.uml (fido bau!)
    {
      //sporco trucco perch� la postprocess_config salverebbe tutto in ogni modo (vedi file confapp.cpp e rabbrividisci!)..
      //..mentre qui si vuole salvare solo in caso di CONFERMA da parte dell'utonto
      const KEY k = mask.last_key();
      bool tosave = k == K_ENTER || k == K_SAVE;
      if (tosave)
      {
        TSheet_field& sf = mask.sfield(F_DOCS);  //prende lo sheet..
        const TMask& sm = sf.sheet_mask();       //..poi la maschera di sheet..
        FOR_EACH_SHEET_ROW(sf, j, row)           //per ogni riga dello sheet deve salvare SOLO i campi che hanno un field
        {
          short id = 101;
          FOR_EACH_TOKEN((*row), tok)
          {
            const TFieldref* fr = sm.field(id++).field(); //settatore dei valori sul .ini
            if (fr != NULL)
              config.set(fr->name(), tok, NULL, true, j);
          }
        }
        //gestione della eliminazione: finito il giro sulle righe presenti (FOR_EACH_SHEET_ROW) ogni altro campo presente..
        //..eventualmente sul config risulta di troppo e viene giustamente accoppato
        const TFieldref* fr = sm.field(101).field();
        config.remove(fr->name(), sf.items());
      }
    }
    break;

  default:
    break;
  }
  return true;
}


bool TConf_vendite::user_create( )
{
  TString16 arg( argv(2) );
  if( arg[ 0 ] != '-' )
    fatal_box( SINTASSI );

  _current = arg[1] - '0';

  TConfig conf(_current == 6 ? CONFIG_STUDIO : CONFIG_DITTA );
  if (_current == 6) 
    set_config(CONFIG_STUDIO);

  switch( _current )
  {
  case 1:
    conf.set( "EdMask", "ve0200a", "ve" );
    break;
  case 2:
    conf.set( "EdMask", "ve0200b", "ve" );
    break;
  case 3:
    conf.set( "EdMask", "ve0200c", "ve" );
    break;
  case 4:
    conf.set( "EdMask", "ve0200d", "ve" );
    break;
  case 5:
    conf.set( "EdMask", "ve0200e", "ve" );
    break;
  case 6:
    conf.set( "EdMask", "ve0200f", "ve" );
    break;
  case 7:
    conf.set( "EdMask", "ve0200g", "ve" );
    break;
  case 8:
    conf.set( "EdMask", "ve0200h", "ve");
    break;
  default:
    fatal_box( SINTASSI );
    return false;
    break;
  }
  return true;
}

int ve0200(int argc, char* argv[])
{
  TConf_vendite appc;

  if( argc < 3 )
    fatal_box( SINTASSI );
  appc.run(argc, argv, "Parametri gestione vendite");
  return 0;
}