/*

    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/>.
*/

#include <config.h>

#include <global.hpp>

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


#include <wordexp.h>
#include <sys/stat.h>
#include <dirent.h>
#include <cerrno>
//portability problem?
#include <pthread.h>

#include <cstdio>


#include <FL/Fl.H>
#include <FL/Fl_Image.H>
#include <FL/Fl_Pixmap.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Scroll.H>
#include <FL/fl_ask.H>
#include <FL/Fl_Menu_Bar.H>
#include <FL/Fl_Menu_Item.H>
#include <FL/Fl_Toggle_Button.H>
#include <FL/Fl_Menu_Button.H>
#include <FL/Fl_Choice.H>
#include <FL/Fl_Light_Button.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Help_Dialog.H>
#include <FL/Fl_Check_Button.H>
//#include <FL/Fl_PNG_Image.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 <prefs.hpp>

#include <set_conf.hpp>
#include <command_line.hpp>
#include <util.hpp>



#include <enumerate_atoms.hpp>

extern finestra_pr* MainWindow;

extern Preferences  __pref;

extern bool __close;




/**
 *Un plugin deve avere :
 *
 *una funzione  bool (*need_group)()  che ritorna true  se il  plugin ha
 *bisogno di conoscre quali atomi sono selezionati;
 *
 *una funzione  bool (*need_leg)()  che ritorna true  se il  plugin ha
 *bisogno di conoscere quali legami sono selezionati;
 *
 *una funzione  bool (*act)()  che computa quello  per cui il  plugin e'
 *stato scritto
 *
 */


const int enumerate_atoms_etich_entry::max_pos=8;


enumerate_atoms::enumerate_atoms(immagine* image,string libpath)
  :bist_plugin(image,libpath),
   _curr_num(0),
   _has_to_act(true),
   _has_acted(false)

   
  
{
  
}


void enumerate_atoms::inizialize(){
  editor* ed=dynamic_cast<editor*>(MainWindow);

  ed->canvas_give_focus();
  const char* startnum=fl_input("Start number?");
  if(startnum!=NULL){
    _curr_num=strtol(startnum,NULL,0);
  }else{
    _curr_num=1;
  }
}


bool enumerate_atoms::need_atom(){
  return false;
}

bool enumerate_atoms::need_leg(){
  return false;
}

bool enumerate_atoms::act(int e){

  switch(e){
    
  case FL_PUSH:
    {

      if(Fl::event_button()==FL_RIGHT_MOUSE){
        bool exists;
        _the_image->check_click_etichetta(Fl::event_x(), 
                                          Fl::event_y(),
                                          exists,
                                          true);

        

        /**
         *Contiene  coppie <tipo, < gruppo, id > > selezionati, se  si e'
         *selezionato una etichetta gruppo e' uguale a NO_VALID_GROUP
         */
        
        vector< pair < int, pair<int,int> > >* elem=r_elem_selected();
        vector< pair < int, pair<int,int> > >::iterator eliniz=elem->begin();
        vector< pair < int, pair<int,int> > >::iterator elend=elem->end();
        while(eliniz!=elend){
          switch((*eliniz).first){
          case ETICHETTA:
            update_pos(_the_image->ritorna_punt_etich( (*eliniz).second.second ));
          }
          eliniz++;
        }
      }else{

        bool exists=true;
        
        _the_image->prova_click(Fl::event_x(), 
                                Fl::event_y(),
                                exists,
                                true);
        
        enumerate();
      }
    }
    break;
  case  FL_KEYDOWN:
    switch(Fl::event_key()){
    case ' ':
      {
        editor* ed=dynamic_cast<editor*>(MainWindow);
        update_pos(_added.back()._et);
        ed->redraw();
        ed->canvas_give_focus();
      }
      break;
    case FL_Enter:
    default:
      _has_to_act=false;
      break;
    }//end case FL_KEYDOWN:
    
  }//end switch(e)

  return _has_to_act;
}


enumerate_atoms::~enumerate_atoms(){
  

}

void enumerate_atoms::register_plugin(){

}

 
bool enumerate_atoms::time_to_act(){
  return _has_to_act;
}
    

string enumerate_atoms::libpath(){
  return _lib;
}



void enumerate_atoms::enumerate(){

  /**
   *Contiene  coppie <tipo, < gruppo, id > > selezionati, se  si e'
   *selezionato una etichetta gruppo e' uguale a NO_VALID_GROUP
   */
  
  vector< pair < int, pair<int,int> > >* elem=r_elem_selected();
  vector< pair < int, pair<int,int> > >::iterator eliniz=elem->begin();
  vector< pair < int, pair<int,int> > >::iterator elend=elem->end();
  vector <gruppo>* gruppi=r_groups();

   while(eliniz!=elend){
    switch((*eliniz).first){
    case ATOMO:
      float x=0;
      float y=0;
      float dim_atm=8;
      enumerate_atoms_etich_entry ent;
      for(unsigned int ct=0;ct<gruppi->size();ct++){
        if((*gruppi)[ct].id_gruppo()==((*eliniz).second).first){
          atomo* atm=(*gruppi)[ct].find_atomo_id((*eliniz).second.second);
          etichetta* lb=atm->etich_punt();
          x=atm->pos_x();
          y=atm->pos_y();

          
          ent._x=atm->pos_x();
          ent._y=atm->pos_y();

          if(lb->to_raw_string()==std::string(NO_ETIC)){
            ent._w=0;
            ent._h=0;
          }else{
            ent._w=lb->phys_w();
            ent._h=lb->phys_h();
            dim_atm=lb->dim()/2;
          }

          break;
        }
      }
  
      paragraph_text* ch=new paragraph_text();
      std::ostringstream ost;
      ost << _curr_num;
      ch->dim(dim_atm);
      ch->insert_string_in_curr_pos(ost.str(),ET_STR);
      ch->interline_space(0);
      
      ch->trasla(x+ent._w/2,y-ch->h()-ent._h/2);



      

      ent._et=ch;
      ent._last_pos=0;
      _added.push_back(ent);
      _the_image->aggiungi_etich(ch);
      
      _curr_num++;
    }
    eliniz++;
  }
  _the_image->elimina_elem_selected();

}



void enumerate_atoms::update_pos(etichetta* en){
  for(unsigned int i=0;i<_added.size();i++){
    if(_added[i]._et==en){
      etichetta* tr=_added[i]._et;
      
      switch(_added[i]._last_pos){
      case 0:
        tr->trasla(0,
                   tr->h()/2 + _added[i]._h/2);
        break;
      case 1:
        tr->trasla(0,
                   tr->h()/2 + _added[i]._h/2);
        break;
      case 2:
        tr->trasla(-tr->w()/2 -_added[i]._w/2,
                   0);
        break;
      case 3:
        
        tr->trasla(-tr->w()/2-_added[i]._w/2,
                   0);
        break;
      case 4:

        tr->trasla(0,
                   -tr->h()/2-_added[i]._h/2);
        break;
      case 5:

        tr->trasla(0,
                   -tr->h()/2-_added[i]._h/2);
        break;
      case 6:

        tr->trasla(tr->w()/2+_added[i]._w/2,
                   0);
        break;
      case 7:
        tr->trasla(tr->w()/2+_added[i]._w/2,
                   0);

        break;
        
      }

      _added[i]._last_pos=(++_added[i]._last_pos)%enumerate_atoms_etich_entry::max_pos;

      break;
    }
  }

}


/**************fine metodi di classe**********************************/




extern "C" bist_plugin* create_plugin(immagine* imm, string libpath){
  return new enumerate_atoms(imm, libpath);
}

extern "C" void destroy_plugin(bist_plugin* j){
  cout << "distruzione plugin: " << j <<  endl;
  delete j;
  cout << "riuscita" << endl;
}


