#include <applicat.h>
#include <automask.h>
#include <progind.h>
#include <relation.h>

#include "ve5300.h"
#include "velib.h"

///////////////////////////////////////////////////////////
// TCopydoc mask
///////////////////////////////////////////////////////////

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

protected:  
  int fill_sheet();

public:
  long get_first_ndoc() const;
  TCopydoc_mask() : TAutomask("ve5300a") { open(); }
};

int TCopydoc_mask::fill_sheet()
{
  TSheet_field& sf = sfield(F_TIPI_DOC);
  sf.destroy();

  TString16 n1 = get(F_FROM_NUM);
  TString16 n2 = get(F_TO_NUM);
  if (n1.empty()) n1 = n2;
  if (n2.empty()) n2 = n1;

  if (n1.not_empty())
  {
    const TCodice_numerazione num1(n1);
    TAssoc_array tipi;
    int t;
    for (t = 0; t < num1.ntipi_doc(); t++)
    {
      const TString& td = num1.tipo_doc(t);
      tipi.add(td, NULL);
    }

    const TCodice_numerazione num2(n2);
    for (t = 0; t < num2.ntipi_doc(); t++)
    {
      const TString& td = num2.tipo_doc(t);
      if (tipi.is_key(td))
      {
        sf.row(-1) << "X|" << td;
        sf.check_row(sf.items()-1);
      }
    }
    sf.force_update();
  }

  return sf.items();
}

long TCopydoc_mask::get_first_ndoc() const
{
  long n = get_long(F_TO_NDOC);
  if (n <= 0)
  {
    TLocalisamfile doc(LF_DOC);
    TRectype& curr = doc.curr();
  
    const TDate dd = get_date(F_TO_DATA);
    const int anno = dd.year();
    const char provv = get(F_TO_PROVV)[0];
    const TString& codnum = get(F_TO_NUM);
  
    curr.put(DOC_PROVV, provv);
    curr.put(DOC_ANNO, anno);
    curr.put(DOC_CODNUM, codnum);
    curr.put(DOC_NDOC, 9999999L);
  
    const int err = doc.read(_isgreat);      
    if (err != _isemptyfile)
    {
      if (err == NOERR)
        doc.prev();
      if (curr.get_char(DOC_PROVV) == provv && 
          curr.get_int(DOC_ANNO) == anno && 
          curr.get(DOC_CODNUM) == codnum)
         n = curr.get_long(DOC_NDOC);
    }     
    n++;
  }  
  return n;   
}

bool TCopydoc_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
  switch (o.dlg())
  {
  case F_FROM_NUM:
    if (e == fe_modify && !o.empty())
    {
      set(F_TO_NUM, o.get());
      set(F_TO_DES, get(F_FROM_DES));
    }
    // Fall down
  case F_TO_NUM:
    if (e == fe_modify && !o.empty())
    {
      const int tot = fill_sheet();
      if (tot == 0)
        return error_box("Non ci sono tipi documento compatibili");
    }
    // Fall down
  case F_FROM_FRNDOC:
  case F_FROM_TONDOC:  
    if (e == fe_modify || e == fe_init)
    {
      const long docfr = get_long(F_FROM_FRNDOC);
      const long docto = get_long(F_FROM_TONDOC);
      reset(F_TO_NDOC);
      enable(F_TO_NDOC, docfr > 0 && docfr == docto);
    }
    break;
  case F_TIPI_DOC:
    if (e == fe_close)
    {
      TSheet_field& sf = (TSheet_field&)o;
      int selected = 0;
      FOR_EACH_SHEET_ROW(sf, r, row)
        if (row->get_char(0) > ' ') selected++;
      if (selected == 0)
        return error_box("Non ci sono tipi documento selezionati");
    }
    break;
  case F_TO_NDOC:
    if ((e == fe_modify || e == fe_close) && !o.empty())
    {
      TLocalisamfile doc(LF_DOC);
      doc.put(DOC_PROVV, get(F_TO_PROVV));
      doc.put(DOC_ANNO, get_date(F_TO_DATA).year());
      doc.put(DOC_CODNUM, get(F_TO_NUM));
      doc.put(DOC_NDOC, o.get());
      if (doc.read() == NOERR)
        return error_box("Il documento di destinazione esiste gia'");
    }
    break;  
  default:
    break;
  }
  return TRUE;
}

///////////////////////////////////////////////////////////
// Main program
///////////////////////////////////////////////////////////

class TCopydoc_app : public TSkeleton_application
{ 
  bool _preserve_num;
  
protected:
  bool replace(TRectype& rec, const char* field, const TString& oldstr, const TString& newstr) const;

public:
  virtual void main_loop();
};

bool TCopydoc_app::replace(TRectype& rec, const char* field, const TString& oldstr, const TString& newstr) const
{
  bool done = FALSE;
  if (oldstr.not_empty())
  {
    TString str = rec.get(field);
    int last = -1;
    for (int start = str.find(oldstr); start > last; start = str.find(oldstr, last))
    {
      const TString aft = str.mid(start+oldstr.len());
      str.cut(start);
      str << newstr << aft;
      last = start + newstr.len();
    }
    done = last >= 0;
    if (done)
    {
      // Attenzione al campo DESCR che non e' un MEMO!
      if (str.len() > 50 && strcmp(field, RDOC_DESCR) == 0)
        str.cut(50);   
      rec.put(field, str);
    }
  }
  return done;
}

void TCopydoc_app::main_loop()
{
  open_files(LF_TAB, LF_TABCOM, LF_DOC, LF_RIGHEDOC, LF_CONDV, LF_RCONDV, 
             LF_ANAMAG, LF_SCONTI, LF_UMART, LF_CLIFO, LF_CFVEN, LF_INDSP, 
             LF_OCCAS, LF_MOVMAG, LF_RMOVMAG, LF_SVRIEP, LF_AGENTI, LF_PERCPROV, 0);

  TCopydoc_mask m; 
  while (m.run() == K_ENTER)
  {
    TRectype rec_from(LF_DOC);
    rec_from.put(DOC_ANNO, m.get(F_FROM_ANNO));
    rec_from.put(DOC_CODNUM, m.get(F_FROM_NUM));
    rec_from.put(DOC_PROVV, m.get(F_FROM_PROVV));
    rec_from.put(DOC_NDOC, m.get(F_FROM_FRNDOC));    
    _preserve_num = m.get_bool(F_PRESERVE_NUM);

    TRectype rec_to(rec_from);
    rec_to.put(DOC_NDOC, m.get(F_FROM_TONDOC));

    // Costruisce il filtro sui tipi documento selezionati
    // Il pipe significa OR per le espressioni
    TToken_string filtro(80, '|');
    TSheet_field& sf = m.sfield(F_TIPI_DOC);
    FOR_EACH_SHEET_ROW(sf, r, row)
    {
      if (row->get_char(0) > ' ')
      {
        filtro.add("(");
        filtro << DOC_TIPODOC << "=\"" << row->get(1) << "\")";
      }
    }
    // Se li ho selezionati tutti e' inutile filtrare
    if (m.get(F_FROM_NUM) == m.get(F_TO_NUM) && 
        sf.items() == filtro.items())
      filtro.cut(0);

    TRelation rel(LF_DOC);
    TCursor cur(&rel, filtro, 1, &rec_from, &rec_to);
        
    const long tot = cur.items();
    if (tot > 0L)
    {
      if (yesno_box("Confermate la copia di %ld document%c?", 
                    tot, (tot == 1L) ? 'o' : 'i'))
      {
        const TString& provv = m.get(F_TO_PROVV);
        const TDate data = m.get_date(F_TO_DATA); 
        TString16 anno; anno << data.year();
        const TString& codnum = m.get(F_TO_NUM);     
        long ndoc = m.get_first_ndoc();
  
        cur.freeze();
        TProgind pi(tot, "Copia in corso...", FALSE, TRUE);
        for (cur = 0; cur.pos() < tot; ++cur)
        {
          pi.addstatus(1);

          TDocumento olddoc(cur.curr()), newdoc;
          // Rinumera documento principale
          newdoc.put(DOC_PROVV, provv);
          newdoc.put(DOC_ANNO, anno);
          newdoc.put(DOC_CODNUM, codnum); 
          if (_preserve_num)
          {
            const long ndoc_src = olddoc.get_long(DOC_NDOC);
            newdoc.put(DOC_NDOC, ndoc_src);
          }
          else          
            newdoc.put(DOC_NDOC, ndoc++);
          newdoc.copy_contents(olddoc);
          newdoc.put(DOC_DATADOC, data);

          const TString& oldstr = m.get(F_OLD_STR);
          const TString& newstr = m.get(F_NEW_STR);
          const real perc = m.get_real(F_PERC);
          for (int i = newdoc.physical_rows(); i > 0; i--)
          {
            TRectype& r = newdoc[i];
            if (oldstr.not_empty())
            {
              replace(r, RDOC_DESCR, oldstr, newstr);
              if (r.get_bool(RDOC_DESCLUNGA))
                replace(r, RDOC_DESCEST, oldstr, newstr);
            }
            if (!perc.is_zero())
            {
              real price = r.get_real(RDOC_PREZZO);
              if (!price.is_zero())
              {
                price *= (100.0 + perc) / 100.0;
                r.put(RDOC_PREZZO, price);
              }
            }
          }
          newdoc.write();
        }
      }
    }
    else
      warning_box("Nessun documento soddisfa i vincoli indicati");
  }
}

int ve5300(int argc, char* argv[])
{
  TCopydoc_app a;
  a.run(argc, argv, "Copia documenti");
  return 0;
}