#include "baformed.h"
#include "ba2100.h"   
#include <colors.h>
// -----------------------------------------------------------------
// maschera per le finkature
// -----------------------------------------------------------------

#include "ba21fn.h"

class TFink_mask : public TMask
{                              
    TToken_string _chars;  
    
    enum pos { // posizioni scatoletta
      xl  = 1,
      xm  = 15,
      xr  = 29,
      yt  = 1,
      ym  = 5,
      yb  = 9,
      ofs = 36
    };
    
   protected:                  

    void paint_example();   
   
    virtual void handler(WINDOW win, EVENT* ep);  
    static  bool char_handler(TMask_field& f, KEY k);
    virtual void start_run();
    virtual bool stop_run(KEY k);
    virtual PNT log2dev(long x, long y) const;

   public:               
                                  
    TToken_string& get_chars() { return _chars; }
    
    TFink_mask(const char* def) : TMask("ba21fn"), _chars(def,',') 
    { 
      set_handler(C_TR, char_handler);
      set_handler(C_TL, char_handler);
      set_handler(C_TM, char_handler);
      set_handler(C_BR, char_handler);
      set_handler(C_BL, char_handler);
      set_handler(C_BM, char_handler);
      set_handler(C_CM, char_handler);
      set_handler(C_CR, char_handler);
      set_handler(C_CL, char_handler);
      set_handler(C_HR, char_handler);
      set_handler(C_VR, char_handler);
    }
    virtual ~TFink_mask() {}
};
        
PNT TFink_mask::log2dev(long x, long y) const
{                 
  PNT p;
  p.h   = ((short)x+1)*CHARX;
  p.v    = (short)y*ROWY;  
  return p;
}        
        
void TFink_mask::handler(WINDOW win, EVENT* ep)
{                       
  TMask::handler(win, ep);
  if (ep->type == E_UPDATE)
  {         
    // pittura le righette
    rect(xl, yt, xr+1, yb+1);
    line(xl, ym, xr, ym);  
    line(xm, yt, xm, yb);
    paint_example();
  }
}
                      
void TFink_mask::paint_example()
{      
  // pittura un'immaginetta finculata
  // on the right of the mask 
  TString line(xr);                          
  set_font(XVT_FFN_COURIER);
  set_color(MASK_DARK_COLOR,MASK_BACK_COLOR);  
  set_opaque_text(TRUE);

  for (int i = yt; i <= yb; i++)
  { 
    line.spaces();
    if (i == yt)
    {               
      line.fill(_chars.get_char(9)); 
      line[xl-1] = _chars.get_char(0);
      line[xm-1] = _chars.get_char(1);
      line[xr-1] = _chars.get_char(2);
    }
    else if (i == ym) 
    {
      line.fill(_chars.get_char(9)); 
      line[xl-1] = _chars.get_char(6);
      line[xm-1] = _chars.get_char(7);
      line[xr-1] = _chars.get_char(8);
    }
    else if (i == yb) 
    {
      line.fill(_chars.get_char(9)); 
      line[xl-1] = _chars.get_char(3);
      line[xm-1] = _chars.get_char(4);
      line[xr-1] = _chars.get_char(5);
    }
    else
    {
      line[xl-1] = _chars.get_char(10);
      line[xm-1] = _chars.get_char(10);
      line[xr-1] = _chars.get_char(10);
    }
    stringat(ofs, i, line);
  } 
}                      

void TFink_mask::start_run()
{                          
  TMask::start_run();
  for (int i = 101; i <= 111; i++)
  {
    field(i).allow_pipe();   // allowa la pipa, se no son cazzi
    field(i).set(_chars.get(i - 101)); 
  }
}
                      
bool TFink_mask::stop_run(KEY k)
{                              
  if (k == K_ENTER)
  {
    for (int i = 101; i <= 111; i++)
      _chars.add(field(i).get(), i-101);
  }
  return TMask::stop_run(k);
}
                      
bool TFink_mask::char_handler(TMask_field& f, KEY k)
{             
  if (f.focusdirty() && k == K_TAB)
  { 
    TFink_mask& m = (TFink_mask&)f.mask();
    TToken_string& ch = m.get_chars();
    ch.add(f.get(), f.dlg() - 101);
    m.paint_example();
  }
  return TRUE;
}


// -----------------------------------------------------------------
// form editor
// -----------------------------------------------------------------


TForm_editor::TForm_editor() : _form(NULL), _extra(FALSE), _m(NULL)
{}

TForm_editor::~TForm_editor()
{}

bool TForm_editor::create()
{
  TApplication::create();

  const char* form = NULL;
  long code = 0;
  
  for (int a = 2; a < argc(); a++)
  {
    if (stricmp(argv(a), "-E") == 0)
    {
      _extra = TRUE;
      continue;
    }  
    
    if (form == NULL)
      form = argv(a);
    else                  
      if (code == 0)
        code = atol(argv(a));
  }
  
  enable_menu_item(M_FILE_PRINT);
  if ((form && code) || (form && code == 0 && _extra))
  {
    _form = new TForm(form, (code!=0) ? format("%05ld",code) : "", _extra ? 2 : 1);
    if (!_extra) dispatch_e_menu(MENU_ITEM(13));
  } 
  else
    dispatch_e_menu(MENU_ITEM(14));       
  
  _m = new TMask("ba2100b");
  if (form)
  {
    _m->set(F_BASE, form);
    _m->disable(F_BASE);
  }
  
  if (code) _m->set(F_CODE, code);
  
  return TRUE;
}

bool TForm_editor::destroy()
{
  if (_form) delete _form;
  if (_m)    delete _m;
  return TApplication::destroy();
}


bool TForm_editor::menu(MENU_TAG tag)
{
  char sec = 'B';
  pagetype pt = odd_page;
  bool quit = FALSE; 
  
  switch(tag)
  {
  case MENU_ITEM(11): 
    sec = 'R'; pt = odd_page; break;
  case MENU_ITEM(12): 
    sec = 'D'; pt = odd_page; break;  
  case MENU_ITEM(13):
    sec = 'K'; break;
  case MENU_ITEM(14):
    quit = ask_profile();
    sec = 'B'; pt = odd_page; break;
  case MENU_ITEM(15):   // formato numeri
    sec = 'J'; break;
  case MENU_ITEM(16):   // formato date
    sec = 'Y'; break;
  case MENU_ITEM(21): 
    sec = 'H'; pt = odd_page; break;
  case MENU_ITEM(22): 
    sec = 'H'; pt = even_page; break;
  case MENU_ITEM(23): 
    sec = 'H'; pt = first_page; break;
  case MENU_ITEM(24): 
    sec = 'H'; pt = last_page; break;
  case MENU_ITEM(31): 
    sec = 'B'; pt = odd_page; break;
  case MENU_ITEM(32): 
    sec = 'B'; pt = even_page; break;
  case MENU_ITEM(33): 
    sec = 'B'; pt = first_page; break;
  case MENU_ITEM(34): 
    sec = 'B'; pt = last_page; break;
  case MENU_ITEM(41): 
    sec = 'F'; pt = odd_page; break;
  case MENU_ITEM(42): 
    sec = 'F'; pt = even_page; break;
  case MENU_ITEM(43): 
    sec = 'F'; pt = first_page; break;
  case MENU_ITEM(44): 
    sec = 'F'; pt = last_page; break;
  case MENU_ITEM(51): 
    sec = 'G'; pt = odd_page; break;
  case MENU_ITEM(52): 
    sec = 'G'; pt = even_page; break;
  case MENU_ITEM(53): 
    sec = 'G'; pt = first_page; break;
  case MENU_ITEM(54): 
    sec = 'G'; pt = last_page; break;
  default: 
    break;
  }
  
  if (!quit) edit(sec, pt);
  return TRUE;
} 

void TForm_editor::print()
{
  _form->print();
}

bool TForm_editor::file_handler(TMask_field& f, KEY k)
{  
  bool ok = TRUE;

  if (k == K_TAB && f.dirty())
  {               
    const char* n = f.get();
    if (*n > ' ')
    {
      const char* d = prefix().description(n);
      if (*d == '\0') ok = error_box("Nome di file o tabella errato"); 
      f.mask().set(f.dlg()+1, d);
    }  
  }
  
  return ok;  
}

bool TForm_editor::cod_handler(TMask_field& f, KEY k)
{ 
  bool ok = TRUE;
  
  if (k==K_TAB && f.dirty())
  {
    TLocalisamfile frm(LF_FORM);
    frm.zero();
    frm.put("TIPOPROF",f.mask().get(F_BASE));
    frm.put("CODPROF",f.mask().get(F_CODE));
    if (frm.read() == NOERR)
      f.mask().set(F_DESC,frm.get("DESC"));
  }
  return ok; 
}

bool TForm_editor::edit_fincatura()
{
   TFink_mask m(_form->get_fincatura());   
   bool dirty = FALSE;
   
   if (m.run() == K_ENTER)
   {
     _form->set_fincatura(m.get_chars());   
     dirty = TRUE;
   }
   return dirty;
}

bool TForm_editor::date_example(TMask_field& f, KEY k)
{
  if (k == K_TAB && f.focusdirty())
  { 
    TMask& m = f.mask();          
    char format[6];
    format[0] = m.get(F_DFORMAT)[0];
    format[1] = m.get(F_DDAY   )[0];
    format[2] = m.get(F_DMONTH )[0];
    format[3] = m.get(F_DYEAR  )[0];
    format[4] = m.get(F_DSEP   )[0];   
    format[5] = '\0';   
    
    TDate dd(TODAY);
    TFormatted_date d(dd);  
    
    d.set_format(format);    
    m.set(F_DEXAMPLE, d.string());    
  }
  return TRUE;
}

bool TForm_editor::edit_formato_numero()
{ 
  bool dirty = FALSE;
  
  TMask m("ba21nm");
  if (dirty = (m.run() == K_ENTER))
  {
    int w = m.get_int(F_WIDTH); 
    int d = m.get_int(F_DECIMALS);  
    TString p(m.get(F_PICTURE));

    _form->change_number_format(w, d, p);
  }
  return dirty;
  
}

bool TForm_editor::edit_formato_data()
{
  bool dirty = FALSE;
  char format[6] = { "1444-" };
  TMask m("ba21dt");  
  
  m.set_handler(F_DFORMAT, date_example);
  m.set_handler(F_DDAY,    date_example);
  m.set_handler(F_DMONTH,  date_example);
  m.set_handler(F_DYEAR,   date_example);
  m.set_handler(F_DSEP,    date_example);
                    
  TDate dd(TODAY);                  
  TFormatted_date d(dd); 
  d.set_format(format);

  m.set(F_DFORMAT, "1");
  m.set(F_DDAY, "4");
  m.set(F_DMONTH, "4");
  m.set(F_DYEAR, "4");
  m.set(F_DSEP, "-");
  m.set(F_DEXAMPLE, d.string());
  
  if (dirty = (m.run() == K_ENTER))
  { 
    format[0] = m.get(F_DFORMAT)[0];
    format[1] = m.get(F_DDAY   )[0];
    format[2] = m.get(F_DMONTH )[0];
    format[3] = m.get(F_DYEAR  )[0];
    format[4] = m.get(F_DSEP   )[0];   
    format[5] = '\0';                 
    
    _form->change_date_format(format);
  }
  return dirty;

}

bool TForm_editor::edit_relation()
{
  TMask m("ba2100r");
  TSheet_field& s = (TSheet_field&)m.field(F_ITEMS);
  s.sheet_mask().set_handler(101, file_handler);
  
  TRelation* & rel = _form->_relation;  
  TCursor*   & cur = _form->_cursor;  
  
  if (rel)
  {    
    s.rows_array() = _form->rel_desc().get_all_desc();
    // Disable meaningless fields for main file
    s.disable_cell(0, 2);     // Join
    s.disable_cell(0, 4);     // Alias
  }  

  if (m.run() != K_ENTER || !m.dirty()) 
    return FALSE;
  
  if (rel) 
  {
    delete cur; cur = NULL;
    delete rel; rel = NULL;
  }  
  
  TToken_string& r = s.row(0);
  TString16 name = r.get(0);
  
  if (name.not_empty())
  {
    int logicnum = atoi(name);
    
    int alias = 0, to = 0, key = r.get_int(3);
    TString80 exp = r.get(5);
    
    rel = (logicnum > 0) ? new TRelation(logicnum) : new TRelation(name);                 
    cur = new TCursor(rel, exp, key);
    
    for (int i = 1; i < s.items(); i++)
    {
      TToken_string& r = s.row(i);
      name = r.get(0); logicnum = atoi(name);
      r.get();                          // Skip description
      to = name2log(r.get());           // Join
      key = r.get_int();                // Key
      alias = r.get_int();              // Alias
      exp = r.get();                    // Expression
      
      const int l = exp.len();
      for (int j = 0; j < l; j++) 
        if (exp[j] == ' ') exp[j] = '|';
      
      if (logicnum > 0)
        rel->add(logicnum, exp, key, to, alias);   // join file
      else
        rel->add(name, exp, key, to, alias);       // join table
    }   
    
    _form->rel_desc().change_relation(*rel, s.rows_array());
  }
  
  return TRUE;
}


bool TForm_editor::edit(char s, pagetype t)
{
  bool dirty = FALSE;
  
  if (s == 'R')
    dirty = edit_relation();
  else  
    if (s == 'D')
      form_config();
  else
    if (s == 'K')
      dirty = edit_fincatura();
  else
    if (s == 'J')
      dirty = edit_formato_numero();
  else
    if (s == 'Y')
      dirty = edit_formato_data();
    else  
    {                             
      TString80 caption;
      switch(s)
      {
      case 'F': 
        caption << "Piede"; break;
      case 'G': 
        caption << "Sfondo"; break;
      case 'H': 
        caption << "Testa"; break;
      default:  
        caption << "Corpo"; break;
      }                    
      
      switch(t)
      {
      case first_page:
        caption << " della prima pagina"; break;
      case even_page:
        caption << " delle pagine pari"; break;
      case last_page:
        caption << " dell'ultima pagina"; break;
      default:                            
        caption << " standard"; break;
      }                          
      
      dirty = TRUE;
      if (!_form->exist(s, t))
      {
        const KEY k = yesnocancel_box("La sezione %s non esiste:\n"
                                      "si desidera generare quella standard?", 
                                      (const char*)caption);
        if (k == K_ESC) 
          dirty = FALSE;
        else
        {
          TPrint_section* sec = _form->exist(s, t, TRUE);
          if (k == K_YES) 
          {
            const TPrint_section* def = _form->exist(s, odd_page);
            if (def) *sec = *def;
            else dirty = FALSE;
          }
        }
      }            
      if (dirty)
        dirty = _form->section(s, t).edit(caption);
    }
  
  if (dirty && yesno_box("Salvare le modifiche?"))
  {
    if (_form->code() == "")
    {
      TFilename n(_form->name()); n.ext("frm");
      TFilename bak(n); bak.ext("bak");
      rename(n, bak);
      ofstream out(n);
      _form->print_on(out);
    }
    else 
      _form->write_profile();
  }
  
  if (!_extra) dispatch_e_menu(MENU_ITEM(13));
  return dirty;
}


bool TForm_editor::form_config() const
{                               
  TFilename cnfnam(_form->name()); cnfnam.ext("ini");
  
  TString16 cnfpar;
  if (_form->code() != "")
    cnfpar << _form->code();
  else  
    cnfpar << "Main";
  
  TConfig cnf(cnfnam, cnfpar);
  bool ok = FALSE;
  
  const TFilename maskname(cnf.get("EdMask"));
  if (maskname.empty())
    return warning_box("Nessun parametro da configurare");

  TMask m(maskname);
  
  // carica campi
  for (int i = 0; i < m.fields(); i++)
  {
    TMask_field& f = m.fld(i);
    const TFieldref* fref = f.field();
    if (fref != NULL)
    {
      const char* fname = fref->name();
      if (fname != NULL)
      {
        const TString& oldvl = cnf.get(fname);
        if (!oldvl.empty())
          f.set(oldvl);
      }
    }
  }
  
  if (m.run() == K_ENTER && m.dirty())
  {
    // aggiusta campi
    for (i = 0; i < m.fields(); i++)
    {
      TMask_field& f = m.fld(i);
      if (f.dirty())
      {
        const TFieldref* fref = f.field();
        if (fref != NULL)
          cnf.set(fref->name(), f.get(), NULL, TRUE);
      }
    }
    ok = TRUE;
  }
  
  return ok;
}

bool TForm_editor::ask_profile()
{
  
  _m->set_handler(F_CODE, cod_handler);
  
  // choose form from mask 
  KEY k; 
  while ((k = _m->run()) != K_QUIT)
  {
    TString16 fform = _m->get(F_BASE);
    TString80 fdesc = _m->get(F_DESC);
    long fcode = _m->get_long(F_CODE); 
    if (!_extra && (fcode == 0 || fform.left(3) == "BOL"))
    {
      error_box("Non e' possibile modificare i profili standard o i bollettini.") ;
      continue;
    }
    if (k == K_ENTER)
    {
      if (_form != NULL) delete _form;
      _form = new TForm(fform, (fcode!=0) ? format("%05ld",fcode) : "", _extra ? 2 :1, fdesc);    
      break;
    }            
    else if (k == K_DEL)
    {
      if (fcode != 0 && yesno_box("Confermare la cancellazione del profilo %05ld", fcode))
      { 
        TLocalisamfile frm(LF_FORM);
        frm.zero(); 
        frm.put("TIPOPROF", fform); 
        if (fcode != 0 )
          frm.put("CODPROF",  format("%05ld",fcode));
        if (frm.read() == NOERR)
          frm.remove();
        TLocalisamfile rfr(LF_RFORM);
        rfr.zero(); 
        rfr.put("TIPOPROF", fform);
        rfr.put("CODPROF",  format("%05ld",fcode));
        if (rfr.read() == NOERR)
        {
          for ( ; atol(rfr.get("CODPROF")) == fcode && rfr.get("TIPOPROF") == fform; rfr.next())
            rfr.remove();
        }
        _m->set(F_CODE,"");
        _m->set(F_BASE,"");
        _m->set(F_DESC,"");
      }
    }                                                        
  }
  if (k == K_QUIT)
  {
    dispatch_e_menu(M_FILE_QUIT);   
    return TRUE;
  }
  
  return FALSE;
}

int ba2100(int argc, char* argv[])
{                                             
  TForm_editor a;      
  a.run(argc, argv, "Parametrizzazione stampa");
  return 0;
}
