#include <applicat.h>
#include <mask.h>
#include <form.h>
#include <tabutil.h>

#include "pr1200a.h"
#include "percprov.h"

static word __lenfields[4];

class TPercprovv_form : public TForm
{ 
  TString _conf;
  
protected:  
  virtual bool validate(TForm_item &, TToken_string &); 
public:
  void set_conf(const char* s) { _conf = s;}
  TPercprovv_form(const char *);
  virtual ~TPercprovv_form(){};
};

TPercprovv_form::TPercprovv_form(const char* name): TForm()
{
  read(name);
}

bool TPercprovv_form::validate(TForm_item &cf, TToken_string &s)
{
  const TString code(s.get(0));      
  TString valore; 

  if (code == "_FILLFIELDS")     
  {
    TString value(cf.get()), x;
    const int l = _conf.len();
    short flid = 0;
    for (int i = 0; i < l; i++)
    {
      switch (_conf[i])
      {
        case 'C':
          flid = FRM_CLI;
          break;
        case 'V':
          flid = FRM_CVE;
          break;
        case 'A':
          flid = FRM_AGE;
          break;
        case 'P':
          flid = FRM_PAG;
          break;
        case 'S':
          flid = FRM_SCO;
          break;
        case 'Z':
          flid = FRM_ZON;
          break;
        case 'M':
          flid = FRM_ART;
          break;
        case 'E':
          flid = FRM_GMC;
          break;
        case 'R':
          flid = FRM_SMC;
          break;
        case 'F':
          flid = FRM_RFA;
          break;
        default:
          flid = 0;
          break;
      }
      if (flid == 0)
        break;
      // Estrae il valore da  value in x tramite __lenfields[]
      x = value.left(__lenfields[i]);
      value.ltrim(__lenfields[i]);
      // Setta il TForm_item corrispondente
      TForm_item& fi = find_field('B', odd_page, flid);
      fi.set(x);
    }
  }
  return TForm::validate(cf, s);
}

class TStampa_percprovv : public TSkeleton_application
{
  TLocalisamfile *_percprov;
  TTable *_apr;
  TMask * _m;

protected:
  void   compose_ranges(const TString& k, TString& s1, TString& s2);
  static bool codarc_handler(TMask_field& fld, KEY k);
  virtual bool create(); 
  virtual bool destroy(); 
  virtual void main_loop();
};

inline TStampa_percprovv& app() { return (TStampa_percprovv&) main_app();}

bool TStampa_percprovv::codarc_handler(TMask_field& fld, KEY k)
{
  if (fld.to_check(k) && k == K_TAB)
  {
    TMask& m = fld.mask();
    TTable* apr = app()._apr;
    apr->put("CODTAB", fld.get());
    if (apr->read() == NOERR)
    {
      TString s3(apr->get("S3"));
      const int len = s3.len();
      m.hide(-G_ALL);
      m.reset(-G_ALL);
      for (int i = 0; i<len; i++)
        switch (s3[i])
        {
          case 'C': 
            m.show(-G_CLI);
            break;
          case 'V':
            m.show(-G_CATV);
            break;
          case 'A':
            m.show(-G_AGE);
            break;
          case 'P':
            m.show(-G_PAG);
            break;
          case 'S':
            m.show(-G_SCONTO);
            break;
          case 'Z':
            m.show(-G_ZONA);
            break;
          case 'M':
            m.show(-G_ART);
            break;
          case 'E':
            m.show(-G_GMC);
            break;
          case 'R':
            m.show(-G_SMC);
            break;
          case 'F':
            m.show(-G_RFA);
            break;
          default:
            break;
        }
    }
  }
  return TRUE;
}

void TStampa_percprovv::compose_ranges(const TString& k, TString& s1, TString& s2)
{
  const int len = k.len();
  TString formato,ws;
  short id_from, id_to;
  s1 = "";
  s2 = "";
  for (int i=0; i<len; i++)
  {
    switch(k[i])
    {
      case 'C':
        id_from =  F_FROMCLIENTE;
        id_to   =  F_TOCLIENTE;
        break;
      case 'V':
        id_from =  F_FROMCATVEN;
        id_to   =  F_TOCATVEN;
        break;
      case 'A':
        id_from =  F_FROMCODAGE;
        id_to   =  F_TOCODAGE;
        break;
      case 'P':
        id_from =  F_FROMCODPAG;
        id_to   =  F_TOCODPAG;
        break;
      case 'S':
        id_from =  F_FROMCODSCONTO;
        id_to   =  F_TOCODSCONTO;
        break;
      case 'Z':
        id_from =  F_FROMCODZONA;
        id_to   =  F_TOCODZONA;
        break;
      case 'M':
        id_from =  F_FROMCODART;
        id_to   =  F_TOCODART;
        break;
      case 'E':
        id_from =  F_FROMCODGMC;
        id_to   =  F_TOCODGMC;
        break;
      case 'R':
        id_from =  F_FROMCODSMC;
        id_to   =  F_TOCODSMC;
        break;
      case 'F':
        id_from =  F_FROMCODRFA;
        id_to   =  F_TOCODRFA;
        break;
      default:
        id_from = id_to = 0;
        break;
    }
    if (id_from == 0)
      break;
    __lenfields[i] = _m->field(id_from).size();
    if (id_from == F_FROMCLIENTE) // I codici clienti vanno allineati a destra!
      formato.format("%%%ds",__lenfields[i]);
    else
      formato.format("%%-%ds",__lenfields[i]); // Gli altri a sinistra
    ws.format(formato,(const char*)_m->get(id_from));
    s1 << ws;
    ws.format(formato,(const char*)_m->get(id_to));
    s2 << ws;
  }
}

void TStampa_percprovv::main_loop()
{
  TRectype from(LF_PERCPROV), to(LF_PERCPROV);
  TString codpr, s1,s2, s3;

  _m->hide(-G_ALL);
  while (_m->run() == K_ENTER)
  {
    TPercprovv_form frm("pr1200a");
    codpr = _m->get(F_CODPR); // Codice archivio
    _apr->put("CODTAB", codpr);
    if (_apr->read() == NOERR) // legge la stringa di definizione dei campi
      s3 = _apr->get("S3");
    else
      s3 = "----";

    // Compone le stringhe per from e to
    compose_ranges(s3, s1, s2);
    
    from.zero();
    from.put(PER_CODPR, codpr);
    from.put(PER_KEYORD,s1);
    
    to = from;
    to.put(PER_KEYORD, s2);
    
    TCursor* cur = frm.cursor();
    cur->setregion(from, to);
    if (cur->items() == 0L)
    {
      warning_box("Non vi sono elementi da stampare nell'intervallo indicato.");
      continue;
    }
      
    for (short k = FRM_CLI; k <= FRM_RFA; k++) // Nasconde tutti gli items del cazzo
    {
      TForm_item& fi = frm.find_field('B', odd_page, k);
      fi.hide();
    }
    // Ripristina solo quelli necessari cambiandogli la coordinata y in sequenza (tanto al massimo
    // sono 4)
    const int l = s3.len();
    short flid = 0;
    for (int i=0; i < l; i++)
    {
      switch (s3[i])
      {
        case 'C':
          flid = FRM_CLI;
          break;
        case 'V':
          flid = FRM_CVE;
          break;
        case 'A':
          flid = FRM_AGE;
          break;
        case 'P':
          flid = FRM_PAG;
          break;
        case 'S':
          flid = FRM_SCO;
          break;
        case 'Z':
          flid = FRM_ZON;
          break;
        case 'M':
          flid = FRM_ART;
          break;
        case 'E':
          flid = FRM_GMC;
          break;
        case 'R':
          flid = FRM_SMC;
          break;
        case 'F':
          flid = FRM_RFA;
          break;
        default:
          flid = 0;
          break;
      }
      if (flid == 0)
        break;
      TForm_item& fi = frm.find_field('B', odd_page, flid);
      fi.show();
      fi.y() = i+1;
    }
    frm.set_conf(s3);
    frm.print();
  }
}

bool TStampa_percprovv::create()
{
  _m   = new TMask ("pr1200a");
  _m->set_handler(F_CODPR, codarc_handler);
  _apr = new TTable("APR");
  _percprov = new TLocalisamfile(LF_PERCPROV);
  return TSkeleton_application::create();
}

bool TStampa_percprovv::destroy()
{
  delete _m;
  delete _apr;
  delete _percprov;
  return TSkeleton_application::destroy();
}

int pr1200(int argc, char* argv[])
{
  TStampa_percprovv a;
  a.run(argc,argv,"Stampa % di provvigione");
  return 0;
}