/*

    Bist: a chemical drawing tool
    Copyright (C) 2008 Valerio Benfante

    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 3 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, see <http://www.gnu.org/licenses/>.
*/
// generated by Fast Light User Interface Designer (fluid) version 1.0104

#include <config.h>
#include <global.hpp>

#include <cairo/cairo.h>
#include <pango/pangocairo.h>
#include <cairo_t_singleton.hpp>
#include <glib.h>


#include <FL/Fl_Pixmap.H>
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Menu_Bar.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Choice.H>
#include <FL/Fl_Group.H>
#include <FL/Fl_Round_Button.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Return_Button.H>
#include <FL/Fl_Scroll.H>
#include <FL/Fl_Color_Chooser.H>
#include <FL/Fl_Help_Dialog.H>

#include <interfacce.hpp>
#include <legame.hpp>
#include <etichetta.hpp>
#include <multiline_label.hpp>
#include <multifont_label.hpp>
#include <paragraph_text.hpp>
#include <atomo.hpp>
#include <procedura.hpp>
#include <gruppo.hpp>
#include <immagine.hpp>
#include <bist_plugin.hpp>
#include <mol_canvas.hpp>
#include <finestra_pr.hpp>
#include <editor.hpp>
#include <util.hpp>
#include <string_prop.hpp>

void string_prop_color_cb(Fl_Widget* w, void* d){
  string_prop* prop=dynamic_cast<string_prop*>(w->parent());
  unsigned char r,g,b;
  int pushd=fl_color_chooser(_("pick a color..."), r, g, b);
  if(pushd){
    prop->_str->cr(r);
    prop->_str->cg(g);
    prop->_str->cb(b);
  }
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->redraw();
}

void string_prop_ok_cb(Fl_Widget* w, void* d){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  string_prop* prop=dynamic_cast<string_prop*>(w->parent());
  Fl_Choice* dimensioni=dynamic_cast<Fl_Choice*>(prop->child(2));
  Fl_Choice* i_font=dynamic_cast<Fl_Choice*>(prop->child(1));
  int font_ch=i_font->value(); 
  prop->_str->font(font_ch);
  prop->_str->dim(strtol(dimensioni->mvalue()->text,NULL,0));
  ed->redraw();
}


void string_prop_font_cb(Fl_Widget* w, void* d){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  string_prop* prop=dynamic_cast<string_prop*>(w->parent());
  Fl_Choice* dimensioni=dynamic_cast<Fl_Choice*>(prop->child(2));
  prop->_str->dim(strtol(dimensioni->mvalue()->text,NULL,0));
  ed->redraw();
}



void string_prop_canc_cb(Fl_Widget* w, void* d){
  string_prop* prop=dynamic_cast<string_prop*>(w->parent());
  prop->hide();
}



Fl_Menu_Item str_voci_font_face[] = {
  {"helvetica", 0, 0, 0,},
  {"helvetica bold", 0, 0, 0,},
  {"helvetica italic", 0, 0, 0,},
  {"helvetica bold italic", 0, 0, 0,},

  {"courier", 0, 0, 0,},
  {"courier bold", 0, 0, 0,},
  {"courier italic", 0, 0, 0,},
  {"courier bold italic", 0, 0, 0,},

  {"times", 0, 0, 0,},
  {"times bold", 0, 0, 0,},
  {"times italic", 0, 0, 0,},
  {"times bold italic", 0, 0, 0,},

  {"symbol", 0, 0, 0,},

  {"screen", 0, 0, 0,},
  {"screen bold", 0, 0, 0,},

  {"zapf dingbats", 0, 0, 0,},

  {0}
};


Fl_Menu_Item voci_font_dim_str[NUM_FONT_DIM];

string_prop::string_prop(etichetta* et)
  :Fl_Double_Window(339,144,_("Text properties")),
   _str(et)
 {
 
   { 
     Fl_Box* o = new Fl_Box(5, 5, 330, 100); //0
      o->box(FL_ENGRAVED_BOX);
    }
   { 
     Fl_Choice* o = new Fl_Choice(90, 15, 145, 20, _("Font:")); //1
      o->down_box(FL_BORDER_BOX);
      o->menu(str_voci_font_face);
    }
   { 
     Fl_Choice* o = new Fl_Choice(90, 40, 60, 20, _("Dimension:"));//2
     o->down_box(FL_BORDER_BOX);
     for(int i=0;i<NUM_FONT_DIM-1;i++){
       ostringstream ostr;
       ostr << i+5;
       voci_font_dim_str[i].text=strdup(ostr.str().c_str());
     }
     o->menu(voci_font_dim_str);
     o->value(8);
     o->callback(string_prop_font_cb);
   }

   Fl_Button* text= new Fl_Button(109, 65, 30, 30);//3
   text->type(FL_RADIO_BUTTON);
   text->image(image_lb_normal_str_atom);

   Fl_Button* sup=  new Fl_Button(139, 65, 30, 30);//4
   sup->type(FL_RADIO_BUTTON);
   sup->image(image_lb_supers);

   Fl_Button* sub=  new Fl_Button(169, 65, 30, 30);//5
   sub->type(FL_RADIO_BUTTON);
   sub->image(image_lb_subs);

   Fl_Button* color=new Fl_Button(199, 65, 30, 30);//6
   color->image(image_lb_select_font_color);
   color->callback(string_prop_color_cb);

   Fl_Return_Button* ok= new Fl_Return_Button(110, 109, 80, 30, _("OK"));//7
   ok->callback(string_prop_ok_cb);

   Fl_Button* ann=new Fl_Button(190, 109, 65, 30, _("Close"));//8
   ann->callback(string_prop_canc_cb);
   end();
   set_modal();

   /************************************************************/
   std::vector < std::pair<std::string,int> > the_vec_str=_str->vec_str();
   //std::cerr << the_vec_str.size() << std::endl;

   if(the_vec_str.size() >0){
     //     _pos.first=the_vec_str.size()-1;
     //_pos.second=((the_vec_str.back().first).size())-1;
     int currtype=_str->type_etic_at_cur_pos();
     if(currtype>0){
       set_type_text_button(currtype);
     }else{
       set_type_text_button(ET_STR);
     }
   }
   
   //_str->set_cursor_position(_pos);
   _str->draw_cursor(true);
   dialog_position(this);
}

string_prop::~string_prop(){
  _str->draw_cursor(false);
}

void string_prop::set_type_text_button(int which){
  Fl_Button* text_normal=dynamic_cast<Fl_Button*>(child(3));
  Fl_Button* apic=dynamic_cast<Fl_Button*>(child(4));
  Fl_Button* pedic=dynamic_cast<Fl_Button*>(child(5));
  switch(which){
  case ET_STR:
    text_normal->value(1);
    apic->value(0);
    pedic->value(0);
    break;
  case ET_APICE:
    text_normal->value(0);
    apic->value(1);
    pedic->value(0);
    break;

  case ET_PEDICE:
    text_normal->value(0);
    apic->value(0);
    pedic->value(1);
    break;
  }
}


// void string_prop::delete_char_curr_pos(bool before){
//   std::vector < std::pair<std::string,int> > the_vec_str=_str->vec_str();
//   try{
//     check_if_type_etic(ET_STR,_pos.first);
//     check_if_type_etic(ET_APICE,_pos.first);
//     check_if_type_etic(ET_PEDICE,_pos.first);
//     std::string to_update= the_vec_str[_pos.first].first;
//     int type=the_vec_str[_pos.first].second;
//     //std::cerr << "to_update.size()" <<  to_update.size() << " " << _pos.second << std::endl;

//     if(before){
//       cerr << "to update " <<  to_update << std::endl;
//         cerr << "BBBB" << _pos.first  <<std::endl;
//         cerr << "_cursor_pos.second" << _pos.second  <<std::endl;
//       if(_pos.second<=to_update.size() && _pos.second>0){
// 	to_update.erase(_pos.second-1,1);

// 	_str->sostituisci(to_update,type,_pos.first);
// 	_pos.second--;
//       }else if(_pos.second==0 && ( (static_cast<int>(_pos.first)-1) >=0)){
// 	//cerr << "AAAAAA" << _pos.first-1 << " " << ( (_pos.first-1) >=0) <<std::endl;
// 	_str->elimina(_pos.first);
// 	_pos.first--;
// 	_pos.second=the_vec_str[_pos.first].first.size();
		
//       }else{
// 	//cerr << "fermo" <<  std::endl;
//       }
//     }else{
//       if(_pos.second<to_update.size()){ //cursore non  alla   fine  della
// 	                                //stringa
// 	to_update.erase(_pos.second,1);
// 	if(to_update!=""){
// 	  _str->sostituisci(to_update,type,_pos.first);
// 	}else{
// 	  _str->elimina(_pos.first);
// 	  if(static_cast<int>(_pos.first) < _str->size_str()){
// 	    _pos.second=0;
// 	  }else{
// 	    _pos.first--;
// 	    _pos.second=the_vec_str[_pos.first].first.size();
// 	  }
// 	}
// 	//_pos.second++;
//       }
//     }
//   }catch (out_of_range e){
//     std::cerr << __FUNCTION__ << "Exception: can not delete char" << std::endl;
//   }

// }

// void string_prop::insert_char_in_curr_pos(char add, int type){
//   std::vector < std::pair<std::string,int> > the_vec_str=_str->vec_str();
//   if(the_vec_str.size()<=0){ //inizializza il vettore
//     _str->aggiungi(std::string(1,add),type);
//     _pos.second=1;
//     _pos.first=0;
//   }else if(_pos.first<the_vec_str.size()){ //posizione first valida
//     if(_pos.second<=0){
//       /*
//       cerr << "entro in " << _pos.first << " " << the_vec_str[_pos.first].first
// 	   << " " << _pos.second  << std::endl;
//       */
//       if( the_vec_str[_pos.first].first.size()>0){
// 	std::string to_update= the_vec_str[_pos.first].first;
// 	to_update.insert(_pos.second,std::string(1,add));
// 	_str->sostituisci(to_update,type,_pos.first);
// 	_pos.second++;
//       }else{// ma vuota
// 	_str->sostituisci(std::string(1,add),type,_pos.first);
// 	_pos.second=1;
//       }
//     }else{ // non vuota inserisci
//       std::string to_update= the_vec_str[_pos.first].first;
//       //std::cerr << "to_update.size()" <<  to_update.size() << " " << _pos.second << std::endl;
//       if(_pos.second<to_update.size()){ //cursore non  alla   fine  della
// 					//stringa
// 	to_update.insert(_pos.second,std::string(1,add));
// 	_str->sostituisci(to_update,type,_pos.first);
// 	_pos.second++;
//       }else{
// 	to_update+=std::string(1,add);
// 	_str->sostituisci(to_update,type,_pos.first);
// 	_pos.second=to_update.size();
// 	//std::cerr << "dopo :" <<  to_update.size() << " " << _pos.second << std::endl;
//       }
//     }
//   }
  
  
// }

// bool string_prop::check_if_type_etic(int typ,int pos) throw (out_of_range){
 
//   //int nis=_str->size_str();
//   vector < pair<string,int> > stringhe=_str->vec_str();

//   if(static_cast<unsigned int>(pos) < _str->vec_str().size()){
//     vector < pair<string,int> >::iterator it= stringhe.begin();
//     pair<string,int> pt= *(it+pos);
//     if(pt.second==typ){
//       return true;
//     }else{
//       return false;
//     }
//   }else{
//     string exc="Errore where < _vec_str.size() nella classe etichetta.";
//     throw out_of_range(exc);
//   }
// }


// bool string_prop::check_if_type_etic(int typ) throw (out_of_range){
//   bool res=false;
//   if(_str->size_str()>0){
//     //int nis=_str->size_str();
//     vector < pair<string,int> > stringhe=_str->vec_str();
//     pair<string,int> pt= stringhe.back();
    
//     if(pt.second==typ){
//       res= true;
//     }else{
//       res= false;
//     }
//     return res;
//   }else{
//     std::string exc="Errore where < _vec_str.size() nella classe etichetta. " 
//       + std::string(__FUNCTION__);
//     throw out_of_range(exc);
//   }
// }



int string_prop::handle(int e){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  Fl_Double_Window::handle(e);
   switch(e){
     
   case FL_FOCUS:
     return 0;
     break;


   case FL_KEYDOWN:
     {

       //int p;
       Fl_Button* apic=dynamic_cast<Fl_Button*>(child(4));
       Fl_Button* pedic=dynamic_cast<Fl_Button*>(child(5));
       string car;
       //int   carattere=0;
       if(Fl::event_state(FL_SHIFT)){
	 car=toupper(Fl::event_text()[0]);
       }else{
	 car=Fl::event_text()[0];
       }
       /*
       if( isprint(car[0]) && !ispunct(car[0]) && 
	   !isdigit(car[0]) && !isblank(car[0]) && 
	   car[0]!='\b'){
	 return 0;
       }
       */
       //std::cerr << (int)car[0] << "delete " << FL_Delete << std::endl;
       
       if(Fl::event_key(FL_Delete)){ //cancellare il successivo
	 // std::cerr << "canc" << std::endl;
	 //if(_str->size_str()>0){
	   _str->delete_char_curr_pos(false);
           //}
       }else if(car=="\b"){//cancellare il precedente
	 //if(_str->size_str()>0){
	   _str->delete_char_curr_pos(true);
           //}
       }else if(isprint(car[0])){
	 if(apic->value()){
	   //manage_sub_super(ET_APICE, ET_PEDICE,car);
           _str->insert_string_in_curr_pos(car,ET_APICE);
	 }else if(pedic->value()){//dovremmo aggiungere un pedice
	   //manage_sub_super(ET_PEDICE,ET_APICE,car);
           _str->insert_string_in_curr_pos(car,ET_PEDICE);
	 }else{ // normal string
// 	   try{
// 	     //std::cerr << "try..." << std::endl;
// 	     if(!_str->check_if_type_etic(ET_STR,_pos.first)){
// 	       //std::cerr << "not str" << std::endl;
// 	       _pos.second=0;
//  	       _str->aggiungi(std::string(""),ET_STR);
// 	       _pos.first=_str->size_str()-1;//spostiamoci in  modo da prenotare  un nuovo
// 	                                     //elemento nel vettore
//  	     }
	     
// 	     for(unsigned int i=0;i<car.size();i++){
// 	       _str->insert_char_in_curr_pos(car[i],ET_STR);
// 	     }
// 	   }catch (out_of_range e){ // il  vettore  e' vuoto  possiamo
// 				    // aggiungere e inizializzarlo
// 	     //std::cerr << "catch" << std::endl;
// 	     for(unsigned int i=0;i<car.size();i++){
// 	       _str->insert_char_in_curr_pos(car[i],ET_STR);
// 	     }
// 	   }

           _str->insert_string_in_curr_pos(car,ET_STR);
           ed->redraw();
           return 1;
      

	 }
       }else if(Fl::event_key()==FL_Left){
	 // std::vector < std::pair<std::string,int> > the_vec_str=_str->vec_str();
// 	 if(_pos.second>0){
// 	   _pos.second--;
// 	 }else if(( (static_cast<int>(_pos.first)-1) >=0)){
// 	   _pos.first--;
// 	   _pos.second=the_vec_str[_pos.first].first.size();
// 	 }else{
// 	   //cerr << "fermo" <<  std::endl;
// 	 }

// 	 //dobbiamo cambiare bottone ?
// 	 int currtype=the_vec_str[_pos.first].second;
// 	 set_type_text_button(currtype);

	 
	 //solo prova
	 //_pos.second--;
	 //std::cerr << "car == <-" << std::endl;
 	 int currtype=0;
         _str->cursor_one_step_back(currtype);
         set_type_text_button(currtype);
       }else if(Fl::event_key()==FL_Right){
// 	 std::vector < std::pair<std::string,int> > the_vec_str=_str->vec_str();
// 	 if(_pos.second<the_vec_str[_pos.first].first.size()){
// 	   _pos.second++;
// 	 }else if((_pos.first+1)<static_cast<unsigned int>(_str->size_str())) {
// 	   _pos.first++;
// 	   _pos.second=0;
// 	 }
// 	 //std::cerr << "car == ->" << std::endl;

// 	 //dobbiamo cambiare bottone ?
// 	 int currtype=the_vec_str[_pos.first].second;
// 	 set_type_text_button(currtype);
	   

         int currtype=0;
         _str->cursor_one_step_fwd(currtype);
         set_type_text_button(currtype);

       }
       //_str->set_cursor_position(_pos);
       ed->redraw();
       return 1;
      
     }
   default:
     return 0; 
  
   }
 
}


// void string_prop::manage_sub_super(int check, int troublesome,std::string car){
//   //poniamo sia un apice

//   if(check_if_type_etic(check,_pos.first)){ //ultimo e' apice aggiungere
//     //std::cerr << "ultimo apice!" << std::endl;
//     for(unsigned int i=0;i<car.size();i++){
//       insert_char_in_curr_pos(car[i],check);
//     }

//   }else if(check_if_type_etic(ET_STR,_pos.first)){

//     vector < pair<string,int> > stringhe=_str->vec_str();    
//     std::string head_chunk;
//     std::string tail_chunk;
//     std::string to_break=stringhe[_pos.first].first;
//     head_chunk=to_break.substr(0,_pos.second);
//     tail_chunk=to_break.substr(_pos.second);
//     /*
//     std::cerr << "head: " << head_chunk << std::endl
// 	      << "tail: " << tail_chunk << std::endl;
//     */
//     if(tail_chunk==""){
//       _pos.second=0;
//       _pos.first++;
//       if(_pos.first<static_cast<unsigned int>(_str->size_str())){
// 	//if(check_if_type_etic(check,_pos.first)){

// 	//}else  

// 	if(check_if_type_etic(troublesome,_pos.first)){
// 	  bool res_next_exist=true;
// 	  bool is_check=check_if_type_etic_next_chunk(check,res_next_exist);
// 	  if(res_next_exist && is_check){
// 	    //std::cerr << "eoociqui!" << std::endl;
// 	     _pos.first++;
// 	     _pos.second=0;
// 	  }else{
// 	    _str->insert(tail_chunk,troublesome,_pos.first);
// 	  }
// 	}else if(check_if_type_etic(ET_STR,_pos.first)) {
// 	  _str->insert(tail_chunk,ET_STR,_pos.first);
// 	}

	
// 	for(unsigned int i=0;i<car.size();i++){
// 	  insert_char_in_curr_pos(car[i],check);
// 	}

//       }else{
// 	_str->aggiungi(tail_chunk,ET_STR);
// 	_pos.first=_str->size_str()-1; //inutile ma innocuo...spero

// 	for(unsigned int i=0;i<car.size();i++){
// 	  insert_char_in_curr_pos(car[i],check);
// 	}



//       }

//     }else{
//       _str->sostituisci(head_chunk,ET_STR,_pos.first);
//       _pos.first++;
//       _pos.second=0;

//       if(_pos.first<static_cast<unsigned int>(_str->size_str())){
// 	_str->insert(tail_chunk,ET_STR,_pos.first);
//       }else{
// 	_str->aggiungi(tail_chunk,ET_STR);
// 	_pos.first=_str->size_str()-1; //inutile ma innocuo...spero
//       }
//       //std::cerr << "OK" << std::endl;
//       _pos.second=0;
//       _str->insert(std::string(""),check,_pos.first);
//       //std::cerr << "OK2" << std::endl;
//       for(unsigned int i=0;i<car.size();i++){
// 	insert_char_in_curr_pos(car[i],check);
//       }
      
//     }


//   }else if (check_if_type_etic(troublesome,_pos.first)){
//     std::vector < std::pair<std::string,int> > the_vec_str=_str->vec_str();
//     try{
//       //std::cerr << "eccoci " << std::endl;
//       if (check_if_type_etic(check,_pos.first+1)){
// 	_pos.first++;
// 	_pos.second=the_vec_str[_pos.first].first.size();
// 	for(unsigned int i=0;i<car.size();i++){
// 	    insert_char_in_curr_pos(car[i],check);
// 	}
//       }


//     }catch (out_of_range e){
//       std::cerr << "Error1: check_if_type_etic(ET_STR,_str->size_str()+1)" 
// 		  << std::endl;
//       try{
// 	std::cerr << "_pos.first" <<_pos.first<< std::endl;
// 	if (check_if_type_etic(ET_STR,_pos.first-2)){
// 	  _pos.first--;
// 	  _pos.second=the_vec_str[_pos.first].first.size();
// 	  for(unsigned int i=0;i<car.size();i++){
// 	    insert_char_in_curr_pos(car[i],check);
// 	  }
// 	}else{
// 	  std::cerr << "noped " << std::endl;
// 	  _pos.first++; //spostiamoci in  modo da prenotare  un nuovo
// 	  //elemento nel vettore
// 	  _pos.second=0;
// 	  _str->aggiungi(std::string(""),check);
// 	  for(unsigned int i=0;i<car.size();i++){
// 	    insert_char_in_curr_pos(car[i],check);
// 	  }
// 	}
//       }catch(out_of_range e){
// 	std::cerr << "Error2: check_if_type_etic(ET_STR,_str->size_str()-2)" 
// 		  << std::endl;
      

// 	//std::cerr << "noped " << std::endl;
// 	_pos.first++; //spostiamoci in  modo da prenotare  un nuovo
// 	//elemento nel vettore
// 	_pos.second=0;
// 	_str->aggiungi(std::string(""),check);
// 	for(unsigned int i=0;i<car.size();i++){
// 	  insert_char_in_curr_pos(car[i],check);
// 	}
      
//       }

//     }
//   }

// }


// bool  string_prop::check_if_type_etic_next_chunk(int equal,bool &res_next_exist){
//   vector < pair<string,int> > stringhe=_str->vec_str();

//   bool res=false;
//   try{
//     if(check_if_type_etic(equal,_pos.first+1)){
//       res=true;
//       res_next_exist=true;
//     }else{
//       res=false;
//       res_next_exist=true;
//     }
//     return res;
//   }catch(out_of_range e){
//     res_next_exist=false;
//     res=false;
//     return res;
//   }
// }
