#include <applicat.h>
#include <automask.h>
#include <defmask.h>
#include <isam.h>
#include <progind.h>
#include <recset.h>
#include <validate.h>

#include "cg1300l.h"
#include <clifo.h>

///////////////////////////////////////////////////////////
// TCheck_PIVA_mask
///////////////////////////////////////////////////////////

class TCheck_PIVA_mask : public TAutomask
{
protected:
  virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);

  void load_sheet();
  bool save_sheet();
  void update_sheet();
  void dirty_sheet_row();

public:
  TCheck_PIVA_mask() : TAutomask("cg1300l") { }
};

// Carica lo sheet in base alle impostazioni correnti (F_CLIFO, F_COFI)
void TCheck_PIVA_mask::load_sheet()
{
  const bool check_cofi = get_bool(F_COFI);

  TSheet_field& s = sfield(F_CLIFO);
  s.destroy();

  // Elenco di tutti i clienti (o fornitori)
  TISAM_recordset clifo("USE CLIFO\nFROM TIPOCF=#TIPO\nTO TIPOCF=#TIPO");
  clifo.set_var("#TIPO", TVariant(get(F_TIPO)));

  TProgind pi(clifo.items(), TR("Scansione anagrafica"));
  for (bool ok = clifo.move_first(); ok; ok = clifo.move_next())
  {
    const TString& stato = clifo.get(CLI_STATOPAIV).as_string();
    if (stato.full() && stato != "IT")
      continue;  // Ignoro gli esteri

    const TString& occas = clifo.get(CLI_OCCAS).as_string();
    if (occas.full())
      continue;  // Ignoro gli occasionali

    const TString16 paiv = clifo.get(CLI_PAIV).as_string();
    if (paiv.full() && !real::is_natural(paiv))
      continue;  // Ignoro esteri

    const TString16 cofi = clifo.get(CLI_COFI).as_string();

    const bool paiv_good = paiv.full() && pi_check("", paiv);  
    const bool cofi_good = cofi.full() && cf_check("", cofi);
    if (paiv_good && cofi_good)
      continue;  // Ignoro chi sicuramente e' a posto

    const char tipoana = clifo.get(CLI_TIPOAPER).as_string()[0];
    if (tipoana == 'F' && cofi_good)
      continue; // Ignoro le persone fisiche col codice fiscale a posto

    if (paiv_good && !cofi_good && !check_cofi)
      continue;  // Ignoro CF se non voluto

    // Riga sheet: Selezione|Codice|RagioneSociale|P.IVA|C.Fiscale|Messaggio
    TToken_string& tok = s.row(-1);
    tok.add(clifo.get(CLI_CODCF).as_int(), 1);
    tok.add(clifo.get(CLI_RAGSOC).as_string());
    tok.add(paiv);
    tok.add(cofi);

    TToken_string msg(50, '\n');
    if (!paiv_good) msg.add(TR("P.I. errata o mancante"));
    if (!cofi_good) msg.add(TR("C.F. errato o mancante"));
    msg.trim();
    tok.add(msg);  
  }

  s.force_update();
}

// Salva le righe spuntate dello sheet
bool TCheck_PIVA_mask::save_sheet()
{
  // Tengo pronto il file per fare gli aggiornamenti
  TLocalisamfile clifo(LF_CLIFO);

  bool first = true; // Sto per incontrare il primo cliente?

  TSheet_field& s = sfield(F_CLIFO);

  // Mi tengo da parte le posizioni dei campi utili
  const int pos_codcf = s.cid2index(S_CODCF);
  const int pos_paiv = s.cid2index(S_PAIV);
  const int pos_cofi = s.cid2index(S_COFI);
  
  // Scandisco solo le righe "spuntate"
  FOR_EACH_SHEET_ROW(s, r, row) if ((*row)[0] == 'X') 
  {
    // Quando incontro il primo cliente selezionato, chiedo conferma
    if (first)
    {
      const KEY k = yesnocancel_box(TR("Si desidera salvare le modifiche?"));
      if (k != K_YES)
        return k == K_NO;
    }
    first = false; // D'ora in poi non chiedo piu' conferma
    
    clifo.put(CLI_TIPOCF, get(F_TIPO));
    const long codcf = row->get_long(pos_codcf);
    clifo.put(CLI_CODCF, codcf);
    int err = clifo.read(_isequal, _lock); // Locco il cliente da aggiornare
    
    if (err == NOERR)
    {
      clifo.put(CLI_PAIV, row->get(pos_paiv));
      clifo.put(CLI_COFI, row->get(pos_cofi));
      err = clifo.rewrite();               // Aggiorno il record
    }
    
    if (err != NOERR)
      return error_box("Errore %d durante l'aggiornamento del codice %ld", err, codcf);
  }

  return true;
}

// Salva eventuali modifiche pendenti e ricarica lo sheet 
// in base alle impostazioni correnti sulla maschera principale
void TCheck_PIVA_mask::update_sheet()
{
  if (save_sheet())
    load_sheet();
}

// Segna come modificata (F_DIRTY) la riga corrente dello spreadsheet
void TCheck_PIVA_mask::dirty_sheet_row()
{
  TSheet_field& s = sfield(F_CLIFO);
  TMask& m = s.sheet_mask();
  m.set(S_DIRTY, "X");

  // Sporco "giro" per aggiornare lo sheet
  if (!m.is_running())
  {
    const int sel = s.selected();
    s.update_row(sel);
    s.force_update(sel);
  }
}

bool TCheck_PIVA_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
  switch (o.dlg())
  {
  case F_TIPO:
    if (e == fe_init || e == fe_modify)
      update_sheet();
    break;
  case F_COFI:
    if (e == fe_modify)
      update_sheet();
    break;
  case F_RESET:
    if (e == fe_button)
    {
      TSheet_field& s = sfield(F_CLIFO);
      FOR_EACH_SHEET_ROW(s, r, row)
        row->add(" ", 0);
      s.force_update();
    }
    break;
  case DLG_SAVEREC:
    if (save_sheet())
      load_sheet();
    break;
  case S_PAIV:
    if (e == fe_modify)
    {
      if (pi_check("", o.get()))
        dirty_sheet_row();
      else
        return o.error_box("Partita IVA errata");
    }
    break;
  case S_COFI:
    if (e == fe_modify)
    {
      if (cf_check("", o.get()))
        dirty_sheet_row();
      else
        return o.error_box("Codice fiscale errato");
    }
    break;
  case DLG_USER:
    if (e == fe_button)
    {
      TMask& m = o.mask();
      const TString& pi = m.get(S_PAIV);    // Leggo partita IVA e 
      const TString& cf = m.get(S_COFI);    // codice fiscale
      if (pi.blank())                       // Tento di compilare la PAIV vuota 
      {
        if (cf.full() && pi_check("", cf))
        {
          m.set(S_PAIV, cf);
          dirty_sheet_row();
        }
        else
          return o.error_box(TR("Il codice fiscale rappresenta una partita IVA errata"));
      } else
      if (cf.blank())                        // Tento di compilare il COFI vuoto
      {
        if (pi.full() && pi_check("", pi))
        {
          m.set(S_COFI, pi);
          dirty_sheet_row();
        }
        else
          return o.error_box(TR("Partita IVA errata"));
      }
    }
    break;
  case DLG_LINK:
    if (e == fe_button)
    {
      TMask& m = o.mask();
      TLocalisamfile clifo(LF_CLIFO);             // Riempio la chiave 1 di CLIFO  
      clifo.put(CLI_TIPOCF, get(F_TIPO));         
      clifo.put(CLI_CODCF, m.get(S_CODCF));
      if (clifo.curr().edit())                    // Modifica interattiva del cliente
      {
        if (clifo.read() == NOERR)                // Se riesco a rileggerlo ...
        {
          m.set(S_RAGSOC, clifo.get(CLI_RAGSOC)); // aggiorno la ragione sociale,
          m.set(S_COFI, clifo.get(CLI_COFI));     // il codice fiscale
          m.set(S_PAIV, clifo.get(CLI_PAIV));     // e la partita IVA
          dirty_sheet_row();
        }
      }
    }
    break;
  default: break;
  }
  return true;
}

///////////////////////////////////////////////////////////
// TCheck_PIVA
///////////////////////////////////////////////////////////

class TCheck_PIVA : public TSkeleton_application
{
public:
  virtual void main_loop();
};

void TCheck_PIVA::main_loop()
{
  TCheck_PIVA_mask m;
  m.run();
}

void controlla_PIVA(int argc, char* argv[])
{
  TCheck_PIVA cp;
  cp.run(argc, argv, TR("Controllo Partita IVA"));
}