/**
   @license GNU GPLv2
   PROJECT "codfis"
   Copyright © 2005,2006 Danilo Cicerone

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software Foundation,
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/

/**
   @file calccf.cpp
   @author Danilo Cicerone info@digitazero.org
   @date 2006-05-03
   @version 0.4.7
*/

#include "calccf.h"

/*----------------------------------------------------------------------------*/

CFWin::CFWin()
{
   win_main = new Fl_Window((Fl::w() - 450)/2, (Fl::h() - 220)/2, 450, 220,
	   "codfis 0.4.7");
   win_main->callback((Fl_Callback*)cb_win_main, (void*)(this));
   win_main->when(FL_WHEN_RELEASE_ALWAYS);
   win_main->color((Fl_Color)59);
   win_main->begin();
      txt_cogn = new Fl_Input(130, 5, 275, 25, "Cognome");
      txt_cogn->callback((Fl_Callback*)cb_txt_cogn, (void*)(this));
      txt_cogn->labelcolor(FL_BACKGROUND2_COLOR);
      txt_cogn->when(FL_WHEN_CHANGED);

      txt_nome = new Fl_Input(130, 35, 275, 25, "Nome");
      txt_nome->callback((Fl_Callback*)cb_txt_nome, (void*)(this));
      txt_nome->labelcolor(FL_BACKGROUND2_COLOR);
      txt_nome->when(FL_WHEN_CHANGED);

      cbo_sess = new Fl_Choice(130, 65, 50, 25, "Sesso");
      cbo_sess->menu(sex);
      cbo_sess->labelcolor(FL_BACKGROUND2_COLOR);
      cbo_sess->when(FL_WHEN_CHANGED);
      cbo_sess->callback((Fl_Callback*)cb_cbo_sess, (void*)(this));

      lbl_data = new Fl_Box(260, 95, 100, 25, "(GG/MM/AAAA)");
      lbl_data->labelcolor(FL_BACKGROUND2_COLOR);

      txt_data = new Fl_Input(130, 95, 120, 25, "Data di Nascita");
      txt_data->labelsize(12);
      txt_data->maximum_size(10);
      txt_data->labelcolor(FL_BACKGROUND2_COLOR);
      txt_data->callback((Fl_Callback*)cb_txt_data, (void*)(this));
      txt_data->when(FL_WHEN_CHANGED);

      lbl_luna = new Fl_Output(130, 125, 275, 25, "Comune di Nascita");
      lbl_luna->labelsize(12);
      lbl_luna->labelcolor(FL_BACKGROUND2_COLOR);
      lbl_luna->callback((Fl_Callback*)cb_lbl_luna);

      btn_selc = new Fl_Button(410, 125, 30, 25, "&...");
      btn_selc->callback((Fl_Callback*)cb_btn_selc, (void*)(this));
      btn_selc->color((Fl_Color)48);
      btn_selc->labelfont(5);
      btn_selc->labelcolor(FL_FOREGROUND_COLOR);

      lbl_outc = new Fl_Output(130, 155, 275, 25, "Codice Fiscale");
      lbl_outc->box(FL_THIN_UP_BOX);
      lbl_outc->labelfont(1);
      lbl_outc->labelcolor(FL_BACKGROUND2_COLOR);
      lbl_outc->color(FL_YELLOW);
      lbl_outc->textfont(5);
      lbl_outc->textsize(16);
      lbl_outc->callback((Fl_Callback*)cb_lbl_outc);

      btn_calc = new Fl_Button(26, 190, 80, 25, "&Calcola");
      btn_calc->callback((Fl_Callback*)cb_btn_calc, (void*)(this));
      btn_calc->color(FL_BACKGROUND2_COLOR);
      btn_calc->selection_color((Fl_Color)59);
      btn_calc->labelcolor(FL_FOREGROUND_COLOR);

      btn_newc = new Fl_Button(132, 190, 80, 25, "&Nuovo");
      btn_newc->callback((Fl_Callback*)cb_btn_newc, (void*)(this));
      btn_newc->color(FL_BACKGROUND2_COLOR);
      btn_newc->selection_color((Fl_Color)59);
      btn_newc->labelcolor(FL_FOREGROUND_COLOR);

      btn_info = new Fl_Button(238, 190, 80, 25, "&Info");
      btn_info->callback((Fl_Callback*)cb_btn_info, (void*)(this));
      btn_info->color(FL_BACKGROUND2_COLOR);
      btn_info->selection_color((Fl_Color)59);
      btn_info->labelcolor(FL_FOREGROUND_COLOR);

      btn_esci = new Fl_Button(344, 190, 80, 25, "&Esci");
      btn_esci->callback((Fl_Callback*)cb_btn_esci, (void*)(this));
      btn_esci->color(FL_BACKGROUND2_COLOR);
      btn_esci->selection_color((Fl_Color)59);
      btn_esci->labelcolor(FL_FOREGROUND_COLOR);
   win_main->end();

#if defined(WIN32)
   // Nothing to do here (Dev-C++ solve this problem)
#elif defined(__APPLE__)
   // Nothing to do here
#else
   fl_open_display();
   Pixmap mask, p;
   XpmCreatePixmapFromData(fl_display, DefaultRootWindow(fl_display),
   codfis_xpm, &p, &mask, NULL);
   
   win_main->icon((char *)p);
#endif

   gg = 0;
   mm = 0;
   aa = 0;
}

/*----------------------------------------------------------------------------*/

Fl_Menu_Item CFWin::sex[] =
{
   {"M", 0, 0, 0},
   {"F", 0, 0, 0},
   {0}
};

/*----------------------------------------------------------------------------*/

CFWin::~CFWin()
{
   delete win_main;
}

/*----------------------------------------------------------------------------*/

void
CFWin::show()
{
   win_main->show();
}

/*----------------------------------------------------------------------------*/

void
CFWin::hide()
{
   win_main->hide();
}

/*----------------------------------------------------------------------------*/

int
CFWin::visible()
{
   return win_main->visible();
}

/*----------------------------------------------------------------------------*/

inline void
CFWin::cb_win_main_i()
{
   exit(0);
}

/*----------------------------------------------------------------------------*/

void
CFWin::cb_win_main(Fl_Window* o, void* v)
{
   ((CFWin*)(o->user_data()))->cb_win_main_i();
}

/*----------------------------------------------------------------------------*/

inline void
CFWin::cb_txt_cogn_i()
{

}

/*----------------------------------------------------------------------------*/

void
CFWin::cb_txt_cogn(Fl_Input* o, void* v)
{
   ((CFWin*)(o->parent()->user_data()))->cb_txt_cogn_i();
}

/*----------------------------------------------------------------------------*/

inline void
CFWin::cb_txt_nome_i()
{

}

/*----------------------------------------------------------------------------*/

void
CFWin::cb_txt_nome(Fl_Input* o, void* v)
{
   ((CFWin*)(o->parent()->user_data()))->cb_txt_nome_i();
}

/*----------------------------------------------------------------------------*/

inline void
CFWin::cb_cbo_sess_i()
{
	/*
   fl_message("Index : %d", cbo_sess->value());
	*/
}

/*----------------------------------------------------------------------------*/

void
CFWin::cb_cbo_sess(Fl_Input* o, void* v)
{
   ((CFWin*)(o->parent()->user_data()))->cb_cbo_sess_i();
}

/*----------------------------------------------------------------------------*/

inline void
CFWin::cb_txt_data_i()
{
	/*
   printf("txt_data");
	*/
}

/*----------------------------------------------------------------------------*/

void
CFWin::cb_txt_data(Fl_Input* o, void* v)
{
   ((CFWin*)(o->parent()->user_data()))->cb_txt_data_i();
}

/*----------------------------------------------------------------------------*/

inline void
CFWin::cb_lbl_luna_i()
{
	/*
   printf("lbl_luna");
	*/
}

/*----------------------------------------------------------------------------*/

void
CFWin::cb_lbl_luna(Fl_Output* o, void* v)
{
   ((CFWin*)(o->parent()->user_data()))->cb_lbl_luna_i();
}

/*----------------------------------------------------------------------------*/

void
CFWin::cb_lbl_outc(Fl_Output* o, void* v)
{

}

/*----------------------------------------------------------------------------*/

inline void
CFWin::cb_btn_selc_i()
{
   string comune;

   WinSelDB *win = new WinSelDB();

   codcat.clear();

   if (win->standby(codcat, comune))
   {
      lbl_luna->value(comune.c_str());
      //fl_message("CODICE: %s\nCOMUNE: %s", codcat.c_str(), comune.c_str());
   }

   delete win;
}

/*----------------------------------------------------------------------------*/

void
CFWin::cb_btn_selc(Fl_Button* o, void* v)
{
   static_cast<CFWin *>(v)->cb_btn_selc_i();
}

/*----------------------------------------------------------------------------*/

inline void
CFWin::cb_btn_calc_i()
{
   lbl_outc->value("");
   if (check_data())
   {
      calcodfis();
   }
   else fl_message("I dati inseriti sono errati o incompleti!");
}

/*----------------------------------------------------------------------------*/

void
CFWin::cb_btn_calc(Fl_Button* o, void* v)
{
   static_cast<CFWin *>(v)->cb_btn_calc_i();
}

/*----------------------------------------------------------------------------*/

inline void
CFWin::cb_btn_newc_i()
{
   gg = 0;
   mm = 0;
   aa = 0;

   codcat.clear();

   txt_cogn->value("");
   txt_nome->value("");
   txt_data->value("");
   lbl_luna->value("");
   lbl_outc->value("");
   cbo_sess->value(0);

   txt_cogn->take_focus();
}

/*----------------------------------------------------------------------------*/

void
CFWin::cb_btn_newc(Fl_Button* o, void* v)
{
   ((CFWin*)(o->parent()->user_data()))->cb_btn_newc_i();
}

/*----------------------------------------------------------------------------*/

void
CFWin::cb_btn_esci(Fl_Button* o, void* v)
{
   static_cast<CFWin *>(v)->cb_win_main_i();
}

/*----------------------------------------------------------------------------*/

void
CFWin::cb_btn_info(Fl_Button* o, void* v)
{
   static_cast<CFWin *>(v)->show_info();
}

/*----------------------------------------------------------------------------*/

inline void
CFWin::show_info()
{
   WinInfo *win = new WinInfo();

   if (win->standby())
   {
      //fl_message("CODICE: %s\nCOMUNE: %s", codcat.c_str(), comune.c_str());
   }

   delete win;
}

/*----------------------------------------------------------------------------*/

int
CFWin::check_data()
{
   int rit = 1;

   if (!(*txt_cogn->value())) rit = 0;

   if (!(*txt_nome->value())) rit = 0;

   if (!(*txt_data->value())) rit = 0;

   if (!(*lbl_luna->value())) rit = 0;

   vector<string> vdata;
   StrUty app;

   app.split(txt_data->value(), "/", vdata);
   if (vdata.size() == 3)
   {
      gg = app.toint(vdata[0]);
      mm = app.toint(vdata[1]);
      aa = app.toint(vdata[2]);

      if (gg < 1 || gg > 31) rit = 0;
      if (mm < 1 || mm > 12) rit = 0;
      if (aa < 1900 || aa > 2100) rit = 0;
   }
   else rit = 0;

   return rit;
}

/*----------------------------------------------------------------------------*/

void
CFWin::calcodfis()
{
   const string LET_PARI = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
   const string LET_DISP = "BAKPLCQDREVOSFTGUHMINJWZYX";
   const string LET_MESE = "ABCDEHLMPRST";
   const string NUM_PARI = "0123456789";
   const string NUM_DISP = "10___2_3_4___5_6_7_8_9";
   StrUty app;
   string str;
   string cod;
   unsigned int icod = 0;

   str = app.ucase(txt_cogn->value());
   cod += trovacons(str, false);

   str = app.ucase(txt_nome->value());
   cod += trovacons(str, true);

   str = app.int2string(aa);
   str = str.substr(2, 2);

   cod += str;

   str = LET_MESE.substr(mm - 1, 1);

   cod += str;

   if (cbo_sess->value()) str = app.int2string(gg + 40);
   else str = app.int2string(gg);
   str = "00" + str;
   str = str.substr(str.size() - 2, 2);

   cod += str;

   cod += codcat;

   for (unsigned int i = 0; i < cod.size(); i++)
   {
      if (cod[i] >= 'A' && cod[i] <= 'Z')
      {
         if (i % 2) icod += LET_PARI.find(cod[i], 0);
         else icod += LET_DISP.find(cod[i], 0);
      }

      if (cod[i] >= '0' && cod[i] <= '9')
      {
         if (i % 2) icod += NUM_PARI.find(cod[i], 0);
         else icod += NUM_DISP.find(cod[i], 0);
      }
      //fl_message("%d", icod);
   }

   str = static_cast<char>('A' + (icod % 26));

   cod += str;

//   fl_message("Il codice fiscale calcolato è:\n%s", cod.c_str());
   lbl_outc->value(cod.c_str());
   lbl_outc->position(0, cod.size());
   lbl_outc->copy(1);
}

/*----------------------------------------------------------------------------*/

string
CFWin::trovacons(const string& input, const bool isnome)
{
   string vocal;
   string conso;
   unsigned int isize = input.size();

   for (unsigned int i = 0; i < isize; i++)
   {
      if (input[i] == 'A' || input[i] == 'E' || input[i] == 'I' || input[i] == 'O' || input[i] == 'U')
      {
         vocal += input[i];
      }
      else
      {
         if ((input[i] >= 'A' && input[i] <= 'Z')) conso += input[i];
         else conso += "";
      }
   }

   //fl_message("Size %d", conso.size());
   if (conso.size() < 3)
   {
      conso += vocal;
      conso += "---";
   }
   else if (conso.size() > 3 && isnome)
   {
      conso = conso.substr(0, 1) + conso.substr(2, 2);
   }

   return conso.substr(0, 3);
}
