#include "ve6400a.h"
#include "velib.h"

#include <applicat.h>
#include <automask.h>
#include <defmask.h>
#include <execp.h>

#include <agasys.h>

///////////////////////////////////////////////////////////
// Maschera principale
///////////////////////////////////////////////////////////

class TScontrino_mask : public TAutomask
{
  bool _ini_loaded;    
  TFilename _ini_name;

protected:
  virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
  
  // Funzioni di invio ai registratori di cassa conosciuti
  bool send_er400_data(bool extra);
  bool send_scr_data();
  
public:                         
  bool load_ini();
  bool save_ini(KEY k);
  
  bool load_profile();
  bool save_profile();
  
  bool send_data();

  TScontrino_mask();
  virtual ~TScontrino_mask();
};

bool TScontrino_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
  switch (o.dlg())
  {
  case DLG_PRINT:
    if (e == fe_button)
    {
      if (send_data() && _ini_loaded)
        stop_run(K_AUTO_ENTER);
      return false;
    }
    break;  
  default:
    break;
  }
  return TRUE;
}

bool TScontrino_mask::load_profile()
{
  TFilename f;
  f =::firm2dir(-1);    // Directory dati
  f.add("config");      // Directory config
  f.add(source_file()); // Nome Maschera
  f.ext("ini");         // Estensione
  TConfig ini(f, "Main");
  set(F_REGISTRATORE, ini.get("Registratore"));
  set(F_SALUTI, ini.get("Saluti", NULL, -1, "Arrivederci  Grazie!"));
  set(F_DOPPIOZERO, ini.get("DoppioZero", NULL, -1, "X"));
  return TRUE; 
}

bool TScontrino_mask::save_profile()
{
  TFilename f;
  f =::firm2dir(-1);    // Directory dati
  f.add("config");      // Directory config
  f.add(source_file()); // Nome Maschera
  f.ext("ini");         // Estensione
  TConfig ini(f, "Main");
  ini.set("Registratore", get(F_REGISTRATORE));
  ini.set("Saluti",       get(F_SALUTI));
  ini.set("DoppioZero",   get(F_DOPPIOZERO));
  return TRUE; 
}

bool TScontrino_mask::load_ini()
{ 
  _ini_loaded = false;
   
  const TApplication& a = main_app();
  const int argc = a.argc();
  if (argc <= 2)
    return false;
  
  TSheet_field& sheet = sfield(F_SHEET);  

  const TString& arg = a.argv(2);
  if ((arg[0] != '-' && arg[0] != '/') || (arg[1] != 'i' && arg[1] != 'I'))
    return false;
    
  _ini_name = arg.mid(2);
  if (_ini_name.blank() && argc > 3)  
    _ini_name = a.argv(3);
    
  if (!_ini_name.exist())  
    return false;
  
  TString8 para; para.format("%d", LF_DOC);
  TString tmp;
  
  TDocumento doc;
  
  TConfig ini(_ini_name, para);
  TAssoc_array& vars = ini.list_variables();
  FOR_EACH_ASSOC_STRING(vars, obj, key, str)
  {
    if (*str == '"')
    {
      tmp = str;
      tmp.strip("\"");
      str = tmp;
    }
    doc.put(key, str);
  }
  
  const TString& cofi = doc.clifor().get(CLI_COFI);
  if (cofi.full())
    set(F_COFI, cofi);
  else
  {
    const TString& piva = doc.clifor().get(CLI_PAIV);
    set(F_COFI, piva);
  }  
  
  for (int i = 1; ; i++)
  {
    para.format("%d,%d", LF_RIGHEDOC, i);
    if (!ini.set_paragraph(para))
      break;          
    
    const TString& tiporiga = ini.get(RDOC_TIPORIGA);
    if (tiporiga.full())
    {
      TRiga_documento& rdoc = doc.new_row(tiporiga);
      TAssoc_array& vars = ini.list_variables();
      FOR_EACH_ASSOC_STRING(vars, obj, key, str)
      {
        if (*str == '"')
        {
          tmp = str;
          tmp.strip("\"");
          str = tmp;
        }
        rdoc.put(key, str);
      }
    
      if (rdoc.is_articolo())  
      {
        const TString80 codart = rdoc.get(RDOC_CODARTMAG);

        TToken_string& row = sheet.row(-1);         // Crea un nuova riga 
        row = codart;                               // Codice articolo
        row.add(rdoc.get(RDOC_DESCR));              // Descrizione riga
        row.add(rdoc.get(RDOC_QTA));                // Quantita'  
        row.add(rdoc.prezzo(true, true).string());  // Prezzo lordo scontato
        row.add(cache().get(LF_ANAMAG, codart, ANAMAG_REPARTO));  // Reparto   
      }  
    }
  }

  _ini_loaded = sheet.items() > 0;
  return _ini_loaded;
}

bool TScontrino_mask::save_ini(KEY k)
{ 
  bool ok = _ini_loaded && _ini_name.exist();
  if (ok)
  {
    TConfig ini(_ini_name, "Main");
    ini.set("Result", k == K_ENTER ? "OK" : "CANCEL");
    ini.set("Error", "0");
    
    const TString& eld = ini.get("Action");
    const TString& stato_finale = cache().get("%ELD", eld, "S4");
    if (stato_finale.full())
    {
      TString4 para; para.format("%d", LF_DOC);
      ini.set(DOC_STATO, stato_finale, para);
    }  
  }
  return ok;
}

bool TScontrino_mask::send_er400_data(bool extra)
{ 
  TSheet_field& sheet = sfield(F_SHEET);
  const int rows = sheet.items();
  if (rows <= 0)
    return false;

  TMask m(TR("Modalita' di pagamento"), 1, 26, 8);
  m.add_radio(101, 0, "", 1, 0, 24, 
              "CASH|TICK|ASS|CARD|CRT", 
              HR("Contanti|Buoni|Assegno|Carta di Credito|Credito"));
  m.add_button(DLG_OK,     0, "", -12, -1, 10, 2);
  m.add_button(DLG_CANCEL, 0, "", -22, -1, 10, 2);
  if (m.run() != K_ENTER)
    return false;

  const char* const server = "Sidcomm95";
  const char* const topic = server; // Ignoranza totale delle regole di buona programmazione DDE!        
  
  const unsigned int conn = aga_dde_connect("localhost", server, topic);
  if (conn == 0)
    return error_box(FR("Impossibile stabilire una comunicazione DDE con %s"), server);

  TString80 cmd, tmp;         

  if (extra && !field(F_COFI).empty())
  {
    cmd = "[CODF,";
    cmd << get(F_COFI) << ']';
    aga_dde_execute(conn, cmd);
  }

  const int text_len = extra ? 18 : 15;
  TParagraph_string para("", text_len);
  
  const int pos_descr  = sheet.cid2index(F_DESCART);
  const int pos_prezzo = sheet.cid2index(F_PREZZO);
  const int pos_rep    = sheet.cid2index(F_REPARTO);
  const int pos_qta    = sheet.cid2index(F_QTA);
  for (int r = 0; r < rows; r++)
  {                 
    const TToken_string& row = sheet.row(r);
    cmd = "[PLU,";

    row.get(pos_descr, tmp); 
    if (tmp.blank()) continue;
      
    tmp.replace(',', ' '); tmp.replace('[', '('); tmp.replace(']', ')');
    para = tmp;
    cmd << para.get(0);
    
    real price; row.get(pos_prezzo, price);
    tmp = price.string(text_len, 2); tmp.trim();
    if (tmp.ends_with(".00") && get_bool(F_DOPPIOZERO))
      tmp.strip(".");
    cmd << ',' << tmp;
    
    int rep;  row.get(pos_rep, rep);
    if (rep <= 0 || rep > 25) rep = 1;
    cmd << ',' << rep;             

    real qta; row.get(pos_qta, qta);
    tmp = qta.string(10, 5); tmp.trim();
    cmd << ',' << tmp << ']';
    
    aga_dde_execute(conn, cmd);
  }
  
  if (extra)
  {        
    para = get(F_SALUTI); // ARRIVEDERCI E GRAZIE!
    for (int i = 1; i <= 2; i++)
    {
      tmp = para.get();
      if (tmp.full())
      {
        tmp.replace(',', ' '); tmp.replace('[', '('); tmp.replace(']', ')');
        cmd.format("[TXT%d,%s]", i,  (const char*)tmp);
        aga_dde_execute(conn, cmd);
      }  
    }
  }
  
  cmd.cut(0) << '[' << m.get(101) << ']';
  aga_dde_execute(conn, cmd);
  
  aga_dde_terminate(conn);

  return true;
}


bool TScontrino_mask::send_scr_data()
{ 
  TSheet_field& sheet = sfield(F_SHEET);
  const int rows = sheet.items();
  if (rows <= 0)
    return false; 
  
  ofstream o("input.scr");
  
  o<<"$max_num_dept=20;"<<endl;
  
  const int pos_code   = sheet.cid2index(F_CODART);
  const int pos_prezzo = sheet.cid2index(F_PREZZO);
//  const int pos_rep    = sheet.cid2index(F_REPARTO);
  const int pos_qta    = sheet.cid2index(F_QTA);
         
  TString codart, grmerc, descr;
  real prezzo, qta;
         
  for (int r = 0; r < rows; r++)
  {                                         
    const TToken_string& row = sheet.row(r);
    
    row.get(pos_code, codart);
        
    grmerc = cache().get(LF_ANAMAG,codart).get(ANAMAG_GRMERC);
    
    descr = cache().get("GMC",grmerc).get("S0");      //trova nella tabella GMC il record descrizione che corrisponde
                                                      //a grmerc e prende il campo S0, che � la descrizione estesa del
                                                      //gruppo merceologico codificato da grmerc
    grmerc = grmerc.mid(1,2);                                                  
    descr.cut(15);
                                                      
    row.get(pos_prezzo,prezzo);
    row.get(pos_qta,qta);
    real tot = qta * prezzo;
    tot.round(0);                                                         
    
    o << "plud,c,:" << descr << ",n" << grmerc << ",p" << tot.string("@@@@@@@@@@@") << ";"<<endl;
  }
    
  o << "cash;" << endl;
  o.close();                                         // forza la chiusura del file 
  
  TExternal_app a("pos1 input.scr");
  a.run(false,false);
  
  return TRUE;
}


bool TScontrino_mask::send_data()
{           
  bool ok = false;
  const TString& reg = get(F_REGISTRATORE);
  if (reg == "ER400")
    ok = send_er400_data(true);  else
  if (reg == "ER315")
    ok = send_er400_data(false); else
  if (reg == "SCR")
    ok = send_scr_data();
  return ok;  
}

TScontrino_mask::TScontrino_mask() 
               : TAutomask("ve6400a"), _ini_loaded(false) 
{ load_profile(); }

TScontrino_mask::~TScontrino_mask() 
{ save_profile(); }

///////////////////////////////////////////////////////////
// Applicazione principale
///////////////////////////////////////////////////////////

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

void TCoulthard::main_loop()
{                
  open_files(LF_TAB, LF_TABCOM, LF_DOC, LF_RIGHEDOC, NULL);
  open_files(LF_ANAMAG, LF_CLIFO, LF_CFVEN, LF_OCCAS, NULL);
  TScontrino_mask m;
  const bool loaded = m.load_ini();
  const KEY k = m.run();
  if (loaded)
    m.save_ini(k);
}

int ve6400(int argc, char** argv)
{
  TCoulthard app;
  app.run(argc, argv, TR("Scontrino"));
  return 0;
}