#include <applicat.h>
#include <automask.h>
#include <defmask.h>
#include <execp.h>
#include <form.h>
#include <modaut.h>
#include <prefix.h>
#include <report.h>

#include "ba8400.h"

#include <rdoc.h>

///////////////////////////////////////////////////////////
// TFormer_mask
///////////////////////////////////////////////////////////

class TFormer_mask : public TAutomask
{
  bool _doc;
  int _qta_decimals;

protected:
  void run_app(const char* app) const;
  virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);

  void add_array_message(const TString& msg, TReport_field& rf) const;
  void parse_field_line(const TString& line, TReport_field& rf) const;
  void import_section(TScanner& scan, TReport_section& rs) const;
  void import_general(TScanner& scan, TReport& rep);
  void import_sections(TScanner& scan, TReport& rep);
  void import_use(TScanner& scan, TReport& rep) const;
  void import();

public:
  TFormer_mask();
};

void TFormer_mask::import_use(TScanner& scan, TReport& rep) const
{
  TString use;
  int parse_use = 0;
  while (scan.ok())
  {
    const TString& line = scan.line();
    if (line.empty())
      break;
    
    if (parse_use == 0 && line.starts_with("US"))
      parse_use = 1;
    
    if (parse_use == 1)
    {
      if (line.starts_with("EN"))
      {
        parse_use = 2;
        break;
      }
      else
        use << line << '\n';
    }
  }

  if (!use.blank())
    rep.set_recordset(use);
}

void TFormer_mask::add_array_message(const TString& line, TReport_field& rf) const
{
  TToken_string head(line, ' ');

  TString_array list;
  rf.get_list(list);
  const int index = list.last();
  TToken_string item = list.row(index);

  head.add("MESSAGE", 0);
  TString msg = item.get(2);
  msg.trim();
  if (!msg.empty())
    item << '\n';
  msg << head;
  item.add(msg,2);

  list.add(item, index);
  rf.set_list(list);
}

void TFormer_mask::parse_field_line(const TString& line, TReport_field& rf) const
{
  TToken_string head(line, ' ');
  head.trim();
  head.strip_double_spaces();

  if (head.starts_with("DR"))
  {
    if (rf.type() == 'V' || rf.type() == 'P')
      rf.set_codval(head.get(1));
  } else
  if (head.starts_with("FI"))
  {
    TString fld = head.get(1);
    const int arrow = fld.find("->");
    if (arrow > 0)
    {
      const TString& right = fld.mid(arrow+2);
      fld.cut(arrow);
      fld << '.' << right;
    }
    if (rf.field().blank())
      rf.set_field(fld);
    else
      rf.set_alternate_field(fld);
  } else
  if (head.starts_with("FL"))
  {
    const TString& flags = head.get(1);
    for (int i = 0; flags[i]; i++)
    {
      switch (flags[i])
      {
      case 'D': rf.deactivate(); break;
      case 'H': rf.hide(); break;
      case 'U': 
        if (rf.type() == 'V') 
          rf.set_type('P');    // Trasforma da Valuta a Prezzo
        break;
      default: break;
      }
    }
  } else
  if (head.starts_with("GR"))
  {
    TString g = rf.groups();
    for (int i = head.items()-1; i > 0; i--)
      g << ' ' << head.get(i);
    rf.set_groups(g);
    if (_doc && rf.type() == 'N')
    {
      if (rf.in_group(29)) // PREZZO
      {
        rf.set_type('P');
        rf.set_codval("33.CODVAL");
      } else
      if (rf.in_group(30)) // QTA
      {
        TString pic = rf.picture().before(",");
        if (_qta_decimals > 0)
        {
          pic << ',';
          for (int d = 0; d < _qta_decimals; d++)
            pic << '@';
        }
        const int extra = pic.len() - rf.get_rect().width() / 100;
        if (extra > 0)
          pic = pic.mid(extra);
        rf.set_picture(pic);
      } else
      if (rf.in_group(31)) // IMPORTO
      {
        rf.set_type('V');
        rf.set_codval("33.CODVAL");
      }
    }
  } else
  if (head.starts_with("IT"))
  {
    const int apicia = head.find('"')+1;
    if (apicia > 0 && rf.type() == 'A')
    {
      const int apicic = head.find('"', apicia);
      TToken_string item(head.sub(apicia, apicic), SAFE_PIPE_CHR);
      item.replace('|', SAFE_PIPE_CHR);
      TString_array list;
      rf.get_list(list);
      list.add(item);
      rf.set_list(list);

      const int msg = head.find(" ME", apicic);
      if (msg > 0)
        add_array_message(head.mid(msg+1), rf);
    }
  } else
  if (head.starts_with("ME"))
  {
    if (head.find("NUMEXPR") > 0 || head.find("STREXPR") > 0)
    {
      const int pos = head.find(',')+1;
      rf.set_field(head.mid(pos));
    }
    else
    {
      if (rf.type() == 'A')
        add_array_message(head, rf);
      else
      {
        head.add("MESSAGE", 0);
        TString me = rf.prescript();
        if (me.not_empty())
          me << '\n';
        me << head;
        rf.set_prescript(me);
      }
    }
  } else
  if (head.starts_with("PI"))
  {
    const int apici = head.find('"');
    if (apici > 0)
    {
      TString pic = head.mid(apici);
      pic.strip("\"");
      pic.insert(rf.picture());
      rf.set_picture(pic);
			const int len = pic.len() * 100;
			const int field_len = rf.get_rect().width();
			if (len > 400 && len < field_len)
				rf.set_width(len);
    }
  } else
  if (head.starts_with("PR"))
  {
    const int x = 100*(head.get_int(1)-1);
    const int y = 100*(head.get_int()-1);
    rf.set_pos(x, y);
    const int apici = head.find('"');
    if (apici > 0)
    {
      TString prompt = head.mid(apici);
      if (rf.type() == 'I')
        rf.set_field(prompt);
      else
      {
        prompt.strip("\"");
        rf.set_picture(prompt);
      }
    }
  }
}

void TFormer_mask::import_general(TScanner& scan, TReport& rep)
{
  TString expr;
  while (scan.ok())
  {
    TString& line = scan.line();
    if (line.empty() || line.starts_with("EN"))
      break;
    if (_doc)
    {
      if (line.starts_with("EXCLUDE"))
      {
        TToken_string exclude(50, ','); 
        exclude = line.after('"'); 
        exclude.strip("\""); exclude.trim();
        const TString4 tipo = exclude.get(0);
        if (!tipo.blank())
        {
          TString cond;
          cond << "(34.TIPORIGA='" << tipo << "\')";
          TString codart = exclude.get(1);
          if (!codart.blank())
          {
            cond.insert("(");
            cond << "&&(34.CODART?='" << codart << "')";
            cond << ')';
          }
          if (expr.not_empty())
            expr << "||";
          expr << cond;
        }
      } else
      if (line.starts_with("QTA_DECIMALS"))
      {
        _qta_decimals = atoi(line.mid(13));
      }
    }
  }

  if (_doc && expr.not_empty())
  {
    expr.insert("!(");
    expr << ')';
    rep.section('B', 1).set_condition(expr);
  }
}

void TFormer_mask::import_section(TScanner& scan, TReport_section& rs) const
{
  TToken_string head(256, ' ');
  
  int in_field = 0;
  TReport_field* cur_field = NULL;

  while (scan.ok())
  {
    TString& line = scan.line();
    if (line.empty())
      break;

    if (line.starts_with("BE"))
    {
      in_field++;
      if (in_field == 1)
      {
        head.trim();
        head.strip_double_spaces();
        const TString16 str_type = head.get(0);
        char type = ' ';
        if (str_type.starts_with("FI"))
          type = 'I'; else
        if (str_type.starts_with("LI"))
          type = 'A';
        else
          type = str_type[0];

        if (type > ' ')
        {
          const int id = head.get_int(1);
          const int width = 100*head.get_int();
          const int height = 100*head.get_int();

          cur_field = new TReport_field(&rs);
          cur_field->set_type(type);
          if (id > 0) 
            cur_field->set_id(id);
          if (width > 0) 
            cur_field->set_width(width);
          if (height > 0) 
          {
            cur_field->set_height(height);
            if (_doc && type == 'S' && height >= 500 && rs.type() == 'B')
              cur_field->set_dynamic_height(true); // Altezza descrizione automatica
          }      
          if (strchr("NVP", type) != NULL)
          {
            cur_field->set_horizontal_alignment('R');
            cur_field->hide_zeroes(true);
          }

          rs.add(cur_field);
        }
      }
    } else
    if (line.starts_with("EN"))
    {
      if (in_field >= 0)
      {
        if (cur_field != NULL)
        {
          // Trasforma in testi fissi i campi stringa senza sorgente
          if (cur_field->type() == 'S' && !cur_field->picture().blank() &&
              cur_field->field().blank() && cur_field->prescript().blank())
            cur_field->set_type('T');
        }
        in_field--; // END of field
        cur_field = NULL;
      }
      if (in_field < 0)
        break;            // END of section
    } else
    if (cur_field != NULL)
    {
      parse_field_line(line, *cur_field);
    }
    
    head = line;
  }
}

void TFormer_mask::import_sections(TScanner& scan, TReport& rep)
{
  while (scan.ok())
  {
    TString& line = scan.line();
    if (line.empty())
      break;

    if (line.starts_with("GE"))
      import_general(scan, rep);
    
    if (line.starts_with("SE"))
    {
      line.trim();
      line.strip_double_spaces();
      TToken_string head(line, ' ');
      const TString16 str_name = head.get(1);
      const TString16 str_type = head.get();
      int height = 100*head.get_int();
      char type = ' ';
      int level = 0;
      if (str_name.starts_with("BO"))
      {
        if (str_type.starts_with("OD"))
        { type = 'B'; level = 1; height = 0; }
      }
      if (str_name.starts_with("FO"))
      {
        if (str_type.starts_with("LA"))
        { type = 'F'; level = 1; }
        if (str_type.starts_with("OD"))
        { type = 'F'; level = 0; }
      } else
      if (str_name.starts_with("GR"))
      {
        if (str_type.starts_with("OD"))
        { type = 'B'; level = 0; }
      } else
      if (str_name.starts_with("HE"))
      {
        if (str_type.starts_with("FI"))
        { type = 'H'; level = 1; }
        if (str_type.starts_with("OD"))
        { type = 'H'; level = 0; }
      }
      if (type > ' ')
      {
        TReport_section& cur_sec = rep.section(type, level);
        if (height >= 0)
          cur_sec.set_height(height);
        else
        {
          if (type == 'F')
          {
            const TPoint abolute_footer_pos(0, -height);
            cur_sec.set_pos(abolute_footer_pos);
          }
        }
        import_section(scan, cur_sec);
      }
    }
  }

  const char* hf = "HF";
  for (int i = 0; hf[i]; i++)
  {
    TReport_section* sec = rep.find_section(hf[i], 0);
    if (sec != NULL)
    {
      const bool yes = rep.find_section(hf[i], 1) != NULL;
      sec->hide_if_needed(yes);
    }
  }
}

void TFormer_mask::import()
{
  _doc = get_bool(F_DOC);
  TScanner scan(get(F_FORM));
  TReport rep;
  import_use(scan, rep);
  import_sections(scan, rep);
  if (_doc)
  {
    rep.set_command_line("ve1 -2");
    rep.set_libraries("ve1300");
  }
  rep.save(get(F_REPORT));
}

void TFormer_mask::run_app(const char* app) const
{
  TFilename output = get(F_REPORT);
  if (output.custom_path())
  {
    TString cmd = app;
    if (cmd.starts_with("ba8"))
      cmd << ' ' << output.name();
    TExternal_app app(cmd);
    app.run();
  }
  else
    ::error_box(TR("Il file %s non esiste"), output.name());
}

bool TFormer_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
  switch (o.dlg())
  {
  case F_FORM:
    if (e == fe_modify || (e == fe_init && !o.empty()))
    {
      TFilename output = get(F_REPORT);
      TFilename path = output.path();
      if (path.empty())
      {
        path = firm2dir(-1);
        path.add("custom");
      }
      TFilename input = o.get();
      input.ext("frm");
      input.custom_path();
      o.set(input);

      const TString name = input.name();
      
      output = path;
      output.add(name);
      output.ext("rep");
      output.lower();

      set(F_REPORT, output, true);
      enable(DLG_ELABORA, input.exist());
      set(F_DOC, isdigit(name[2]) ? "" : "X");
    }
    break;
  case F_REPORT:
    if (e == fe_modify || e == fe_init)
    {
      const TFilename output = get(F_REPORT);
      const bool yes = output.exist();
      enable(DLG_EDIT, yes);
      enable(DLG_PRINT, yes);
    }
    break;
  case DLG_ELABORA:
    if (e == fe_button)
    {
      const TFilename output = get(F_REPORT);
      if (output.exist())
      {
        if (!yesno_box(TR("Il file %s esiste gia':\nSi desidera sovrascriverlo?"), (const char*)output))
          return false;
      }
      import();
      enable(DLG_PRINT, output.exist());
    }
    break;
  case DLG_EDIT:
    if (e == fe_button)
      run_app("ba8 -2");
    break;
  case DLG_PRINT:
    if (e == fe_button)
    {
      if (get_bool(F_DOC))
        run_app("ve1 -2");
      else
        run_app("ba8 -2");
    }
    return false;
  default: 
    break;
  }
  return true;
}

TFormer_mask::TFormer_mask() 
            : TAutomask("ba8400a"), _qta_decimals(0)
{
#ifdef DBG
  set(F_FORM, "d:/clienti/newcelltop/custom/nctfat.frm");
#endif
}

///////////////////////////////////////////////////////////
// TFormer_app 
///////////////////////////////////////////////////////////

class TFormer_app : public TSkeleton_application
{
protected:
  virtual bool create();
  virtual void main_loop();
};

bool TFormer_app::create()
{
  if (!has_module(RSAUT))
    return error_box(TR("Modulo non autorizzato"));

  return TSkeleton_application::create();
}

void TFormer_app::main_loop()
{
  TFormer_mask m;
  m.run();
}

int ba8400(int argc, char* argv[])
{     
  TFormer_app app;
  app.run(argc, argv, TR("Form Converter"));
  return 0;
}