/*

    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 <global.hpp>

#include <FL/fl_draw.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Scroll.H>


#include <interfacce.hpp>
#include <multiline_label.hpp>


#include <mol_canvas.hpp>
#include <finestra_pr.hpp>
*/


#include <global.hpp>

#include <cstdio>


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


#include <FL/fl_draw.H>
#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 <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 <prefs.hpp>
#include <util.hpp>

extern finestra_pr* MainWindow;



extern Preferences  __pref;


multifont_label::multifont_label()
  :multiline_label()

{
  layout_lines(MULTILINE_LABEL_ALIGN_SINGLE_LINE_TEXT_LAYOUT);
}



multifont_label::multifont_label(const multifont_label& other)
 :multiline_label(other)
{

}

multifont_label::multifont_label(const multifont_label* other)
  :multiline_label(other)
{

}

multifont_label::multifont_label(int nfont, int ndim, int ncr, int ncg, int ncb)
  :multiline_label()
{
  bool old_t=treat_as_a_whole(true);
  font(nfont);
  dim(ndim);
  cr(ncr);
  cg(ncg);
  cb(ncb);
  treat_as_a_whole(old_t);
  layout_lines(MULTILINE_LABEL_ALIGN_SINGLE_LINE_TEXT_LAYOUT);
}



multifont_label& multifont_label::operator=(const multifont_label& other){
  _treat_as_a_whole=_treat_as_a_whole;
  _pointer_to_currline=other._pointer_to_currline;
  _interline_space=other._interline_space;
  _layout_lines=other._layout_lines;


  _cr=other._cr;
  _cg=other._cg;
  _cb=other._cb;
  _allineamento=other._allineamento;
  _vec_str=other._vec_str;
  _font=other._font;
  _dim=other._dim;
  _x=other._x;
  _y=other._y;
  _v_offset=other._v_offset;
  
  _cursor_pos=other._cursor_pos;
  _draw_cursor=other._draw_cursor;
  _draw_negative=other._draw_negative;
  genitore::_il_genitore=other._il_genitore;



  for(unsigned int i=0;i< (other._lines_of_text.size()) ;i++){
    etichetta* tmp=new etichetta(other._lines_of_text[i]);
    _lines_of_text.push_back(tmp);
  }


  return (*this);
}

multifont_label::~multifont_label(){
  //std::cerr << __FUNCTION__ << std::endl;
}

void multifont_label::format_paragraph(){
  
  //find max height
  int max_h=-1;
  for(unsigned int ct=0;ct<_lines_of_text.size();ct++){
    if(_lines_of_text[ct]->phys_h() > max_h){
      max_h=_lines_of_text[ct]->phys_h();
    }
  }


  for(unsigned int i=0;i<_lines_of_text.size();i++){
    int h_n=_lines_of_text[i]->phys_h();
    _lines_of_text[i]->y(_y + max_h - h_n);
    
    int total_w=0;
    for(unsigned int j=0;j<i;j++){
      total_w+=_lines_of_text[j]->phys_w();
    }
    
    _lines_of_text[i]->x(_x+total_w);
  }  
  
}


void multifont_label::disegna(){
  multiline_label::disegna();
}


void multifont_label::insert_string_in_curr_pos(std::string str,int type){
 
  switch(type){
  case ET_STR:
    {
      for(unsigned int i=0;i<str.size();i++){
        insert_char_in_curr_pos(str[i],ET_STR);
      }
    }
    break;
    
  case ET_PEDICE: 
  case ET_APICE:
    {
       multiline_label::insert_string_in_curr_pos(str,type);

    }
    break;
  }
 
}


void multifont_label::insert_char_in_curr_pos(char add, int type){
    std::pair<int,string::size_type> c_pos(0,0);
    std::vector < std::pair<std::string,int> > the_vec_str;
    std::string car="";
    int old_type=ET_TYPE_NOT_VALID;
    if(_lines_of_text.size()>0){
      get_cursor_position(&c_pos);
      the_vec_str=_lines_of_text[pointer_to_currline()]->vec_str();
      car=the_vec_str[c_pos.first].first;
      old_type=_lines_of_text[pointer_to_currline()]->type_etic_at_cur_pos();
    }
    /*
    std::cerr << car << " insert start!!  c_pos.first " << c_pos.first
              << " c_pos.second " << c_pos.second << std::endl
              << " car " << car << std::endl;
    */
    switch(type){
    case ET_STR:
      {
        if(old_type==ET_STR ||old_type==ET_TYPE_NOT_VALID ){
          std::string str;
          str+=add;
          etichetta*  tmp=new etichetta();

          bool old_t=treat_as_a_whole(true);
          tmp->font(font());
          tmp->dim(phys_dim());
          tmp->cr(cr());
          tmp->cg(cg());
          tmp->cb(cb());
          treat_as_a_whole(old_t);

          tmp->aggiungi(str,ET_STR);
          if(_lines_of_text.size()==0){
            tmp->set_cursor_position(0,1);
            add_line(tmp);
          }else{
            if(pointer_to_currline()== static_cast<int>(_lines_of_text.size()-1) &&
               _lines_of_text.size()>1){
              tmp->set_cursor_position(0,1);
              add_line(tmp);
            }else{
              fall_apart_line_and_add_normal_string(add);
              for(unsigned int i=0;i<_lines_of_text.size();i++){
                if(static_cast<int>(i)<=pointer_to_currline()){
                  _lines_of_text[i]->go_to_end_of_label();
                }else{
                  _lines_of_text[i]->go_to_start_of_label();
                }
              }
            }
          }
        
        }else if(old_type==ET_APICE || old_type==ET_PEDICE){
          fall_apart_line_and_add_normal_string(add);
        }
      }
      break;

    case ET_PEDICE:
    case ET_APICE:
      multiline_label::insert_char_in_curr_pos(add,type);
      break;
      

    }
  
}




void multifont_label::manage_sub_super(int check, int troublesome,std::string car){

}

bool multifont_label::manage_add_sub_super_next_normal_str(int type){
  return false;
}

bool multifont_label::manage_add_sub_next_super(int type){
  return false;
}


bool multifont_label::cursor_one_step_fwd(int &curr_type){
  bool has_more=true;
  if(_lines_of_text.size()>0){
    unsigned int ptr_line=pointer_to_currline();
    std::pair<int,string::size_type> pos;
    _lines_of_text[ptr_line]->get_cursor_position(&pos);
    std::vector < std::pair<std::string,int> > the_vec_str=(_lines_of_text[ptr_line])->vec_str();
    int sz=the_vec_str.size()-1;
    //    std::cerr << ptr_line << std::endl;

    if(ptr_line == (_lines_of_text.size() -1) &&
       pos.first             == sz &&
       pos.second            == the_vec_str.back().first.size() ){
      has_more=false;
    }else{
      multiline_label::cursor_one_step_fwd(curr_type);
      _lines_of_text[pointer_to_currline()]->get_cursor_position(&pos);
      if(pos.second==0 && pos.first==0){ 
        _lines_of_text[pointer_to_currline()]->cursor_one_step_fwd(curr_type);
      }
      _lines_of_text[pointer_to_currline()]->get_cursor_position(&pos);
    }
  }else{
    has_more=false;
  }
  return has_more;
}

bool multifont_label::cursor_one_step_back(int &curr_type){

  bool has_more=true;
  if(_lines_of_text.size()>0 ){
    std::pair<int,string::size_type> pos;
    _lines_of_text[pointer_to_currline()]->get_cursor_position(&pos);

    if(pointer_to_currline() == 0 &&
       pos.first             == 0 &&
       pos.second            == 0 ){
      has_more=false;
    }else{
      multiline_label::cursor_one_step_back(curr_type);
      _lines_of_text[pointer_to_currline()]->get_cursor_position(&pos);
    
      if(pos.second==0 && pos.first==0 && pointer_to_currline()>0){ 
        cursor_one_step_back(curr_type);
        _lines_of_text[pointer_to_currline()]->get_cursor_position(&pos);
        //        std::cerr << pointer_to_currline() << " "
        //          << pos.first << " " << pos.second << std::endl;
      }

    }
  }else{
    has_more=false;
  }

  return has_more;
}
          

void multifont_label::fall_apart_line_and_add_normal_string(char add){
  std::pair<int,string::size_type> old_pos(0,0);
  get_cursor_position(&old_pos);
  //int old_ptrline=pointer_to_currline();
  _lines_of_text[pointer_to_currline()]->break_string_at_cur_pos(ET_STR);
  _lines_of_text[pointer_to_currline()]->insert_char_in_curr_pos(add,ET_STR);
  //int dummy=0;


  std::pair<int,string::size_type> pos;


  int added=break_lines_into_sublabel();
  get_cursor_position(&pos);
  
  pointer_to_currline(added);
  if(old_pos.second>0){
    pointer_to_currline_transl(1);
  }
  _lines_of_text[pointer_to_currline()]->set_cursor_position(0,1);
  /*
  std::cerr << "added " << added << std::endl;
  std::cerr << "pos old " << old_ptrline << std::endl;  
  */
  //works but it is a mess!
  /*
  if(!(pos.second==0 && pos.first==0 && pointer_to_currline()==0)){
    //std::cerr << "ecco 3 " << std::endl;
    pointer_to_currline_transl(1);
    _lines_of_text[pointer_to_currline()]->set_cursor_position(0,0);
    multiline_label::cursor_one_step_fwd(dummy);
  }else  if(old_pos.second>0 &&  old_pos.first==0 && old_ptrline==0  ){
    pointer_to_currline(old_ptrline);
    _lines_of_text[old_ptrline]->set_cursor_position(0,1);
    //std::cerr << "ecco 1 " << std::endl;
    pointer_to_currline(old_pos.second-1);
    cursor_one_step_fwd(dummy);
  }else  if(old_pos.second==0 &&  old_pos.first==0 && old_ptrline==0  ){
    //std::cerr << "ecco 2 " << std::endl;
    pointer_to_currline(0);
    cursor_one_step_fwd(dummy);
  }else if(pos.second==0 && pos.first==0 && pointer_to_currline()==0){
    pointer_to_currline_transl(1);
    _lines_of_text[pointer_to_currline()]->set_cursor_position(0,1);
  }
  */
}




int multifont_label::break_lines_into_sublabel(){
  vector <etichetta*> new_lines_of_text;
  int added=0;
  for(unsigned int i=0;i<_lines_of_text.size();i++){
    int to_add=break_line_into_sublabel(_lines_of_text[i],new_lines_of_text);
    if(static_cast<int>(i) < pointer_to_currline()){
      added+=to_add;
    }
  }
  _lines_of_text=new_lines_of_text;

  return added;
}


int multifont_label::break_line_into_sublabel(etichetta* to_break,
                                               vector <etichetta*>& new_lines_of_text){

   
  int added=0;
  if(to_break->size_str()>0){
    std::vector < std::pair<std::string,int> > the_vec_str=to_break->vec_str();
    for(unsigned int ct=0;ct<the_vec_str.size();){
      added+=atomize_normal_string(to_break,
                                   the_vec_str[ct].first,
                                   new_lines_of_text);
      ct++;
      for(int ct_p=0;ct_p<2;ct_p++){
        if(the_vec_str[ct].second==ET_APICE ||
           the_vec_str[ct].second==ET_PEDICE){
          (new_lines_of_text.back())->aggiungi(the_vec_str[ct].first,the_vec_str[ct].second);
          ct++;
        }
      }
    }
  }


  return added;
}

int multifont_label::atomize_normal_string(etichetta* the_template,
                                            std::string the_string,
                                            vector <etichetta*>& new_lines_of_text){
  int added=0;

  for(unsigned int i=0;i<the_string.size();i++){
    etichetta* tmp=new etichetta(the_template);
    tmp->elimina();
    //tmp->set_cursor_position(0,0);
    std::string single_char="";
    single_char+=the_string[i];
    tmp->aggiungi(single_char,ET_STR);
    new_lines_of_text.push_back(tmp);
    added++;
  }

  return added;
}





void multifont_label::delete_char_curr_pos(bool before){
  int ptr_line=pointer_to_currline();
  std::pair<int,string::size_type> curpos;
  get_cursor_position(&curpos);
  if(_lines_of_text.size()>0){
    std::vector < std::pair<std::string,int> > the_vec_str=
      _lines_of_text[ptr_line]->vec_str();
    etichetta saved=_lines_of_text[ptr_line];
    /*
    bool reassign=false;
    if(!before && curpos.second == 0 &&
       the_vec_str.size()>1
       ){
      std::cerr << "reassign!!!!" << std::endl;
    }else if (before && curpos.second == 1 &&  
              curpos.first == 0 && 
              the_vec_str.size()>1){

          std::cerr << "reassign!!!!" << std::endl;  
        
    }
    */

    multiline_label::delete_char_curr_pos(before);


    //readjust cursor in a tricky way...
    if(size_lines_of_text()>0){
      std::pair<int,string::size_type> curpos;
      _lines_of_text[pointer_to_currline()]->get_cursor_position(&curpos);
      int curr_type=0;
      //if(before && size_lines_of_text()==1){
        //cursor_one_step_fwd(curr_type);
      /*}else*/

      if(!ptr_line_is_last_line() || (curpos.first==0 && curpos.second==0)){
        cursor_one_step_fwd(curr_type);
        cursor_one_step_back(curr_type);
      }
    }
  }
}

