/*

    Bist: a chemical drawing tool
    Copyright (C) 2008-2010 Valerio Benfante 
    Copyright (C) 2010 Valov Vasily

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

void export_image(std::string format);

void editor_window_cb(Fl_Widget* w , void* d);

void editor_3D_rotation_cb(Fl_Widget* w, void* d);


void start_plugin_cb(Fl_Widget* w, void* d);


/*
 *vertical  flip  
*/

void editor_flip_v_cb(Fl_Widget* w, void* d);


/*
 * horizontal  flip
*/

void editor_flip_h_cb(Fl_Widget* w, void* d);

/**
 *
 */

void editor_paste_cb(Fl_Widget* w, void* d);

/**
 *Disegna la catena
 */

void editor_draw_chain(Fl_Widget* w, void* d);

/**
 *functions to export workable area
 */

void editor_export(Fl_Widget* w, void* d);

/**
 *export in png
 */

void editor_save_as_png_cb(Fl_Widget* w, void*);

/**
 *
 */

void editor_save_as_ps_cb(Fl_Widget* w, void* d);



/**
 *undo!
 */

void editor_undo_cb(Fl_Widget* w, void* d);

/**
 *redo!
 */

void editor_redo_cb(Fl_Widget* w, void* d);


/**
 *
 */

void editor_set_def_cb(Fl_Widget* w, void* d);

/**
 *
 */

void config_cb(Fl_Widget* w, void* v);

/**
 *Show "About" window
 */

void edit_about_cb(Fl_Widget* w, void* v);

/*
 * Show window with tutorial
 */
void edit_tutorial_cb(Fl_Widget*,void* v);
/**
 *
 */

void edit_nowar_cb(Fl_Widget* w, void* v);

/**
 *
 *
 */

void add_lib_cb(Fl_Widget* w, void* v);


/**
 *
 */

void copy_cb(Fl_Widget* w, void* v);


/**
 *
 */

void kill_cb(Fl_Widget* w, void* v);

/**
 *
 */
void choose_font_cb(Fl_Widget* w, void* v);


/**
 *
 *
 */

void quit_cb(Fl_Widget* w, void* v);


/**
 *
 */

void open_file_cb(Fl_Widget* w, void* v);


/**
 *
 *
 */

void save_as_native_file_cb(Fl_Widget* w, void* v);



/**
 *
 */

void editor_save_native(Fl_Widget* w, void* v);

/**
 *
 */
void select_atom_cb(Fl_Widget* w, void* v);

/**
 *
 */

void select_group_cb(Fl_Widget* w, void* v);


/**
 *
 */

void select_color_cb(Fl_Widget* w, void* v);

/**
 *
 */

void select_box_cb(Fl_Widget* w, void* v);


/**
 *
 */

void delete_selected_cb(Fl_Widget* w, void* v);



/**
 *
 */

void draw_single_bond_cb(Fl_Widget* w, void* v);

/**
 *
 */

void draw_double_bond_cb(Fl_Widget* w, void* v);


/**
 *
 */

void draw_triple_bond_cb(Fl_Widget* w, void* v);

/**
 *
 */

void draw_arrow_cb(Fl_Widget* w, void* v);

/**
 *
 */

void draw_bezier_cb(Fl_Widget* w, void* v);

/**
 *
 */

void draw_arc_cb(Fl_Widget* w, void* v);

/**
 *draw a box
 */

void draw_box_cb(Fl_Widget* w, void* v);

/**
 *
 */

void draw_etich_cb(Fl_Widget* w, void* v);

/**
 *
 */

void translate_selected_cb(Fl_Widget* w, void* v);

/**
 *
 */

void rotate_selected_cb(Fl_Widget* w, void* v);


/**
 *
 */


void editor_rotate_selected_fixed_cb(Fl_Widget* w, void* v);


/**
 *
 */

void scale_selected_cb(Fl_Widget* w, void* v);


/**
 *
 */

void draw_orb_cb(Fl_Widget* w, void* v);

void editor_zoom_cb(Fl_Widget* w, void* d);

void editor_unzoom_cb(Fl_Widget* w, void* d);

void editor_unzoom_1o1_cb(Fl_Widget* w, void* d);

/**
 * 
 */
enum BondType {
  BOND_SINGLE = 1,
  BOND_DOUBLE = 2,
  BOND_TRIPLE = 3
};
class editor: public finestra_pr, public Fl_Double_Window {
public:
  editor(int W,int H,const char * titolo);

  virtual ~editor();

  void file_inp(string file);
  
  void showHelpDialog();
  void showAboutDialog();
  void showOpenFileDialog(const char* fname);
  void scaleSelected();
  void selectAtom(finestra_pr*);
  void selectGroup(finestra_pr*);
  void selectBox(finestra_pr*);
  void selectColor(immagine* immPtr,unsigned int r,
		   unsigned int g,unsigned int b);
  void zoom();
  void unzoom();
  void unzoom_1o1();
  void undo();
  void redo();
  void rotate3d();
  void flipV();
  void flipH();
  void paste();
  void drawChain();
  void drawBond(BondType);
  void drawArrow();
  void drawBezier();
  void drawBox();
  void drawArc();
  void drawOrb();
  void drawEtich();
  void deleteSelected(finestra_pr*);
  const std::map<std::string,std::string>&
  getPluginPath() const;
  const void* getHandle()const;
  void setHandle(void* newHandle);
  const bist_plugin* getActualPlugin() const;
  void setActualPlugin(bist_plugin* newPlugin);
  const std::string& isFileOpened() const;
  void openFile(const string&);
  void rotateSelected();
  void rotateSelectedFixed();
  void addLib(finestra_pr*);
  void translateSelected();
  void kill(finestra_pr*);
  bool isFileSaved() const;
  void saveFile();
  /**
   *
   *
   */

  void register_images_undo(immagine* imm);
  

  void reg_modified();


  /**
   *\return the size of the deque useful to check if an immagine has been modified
   */

  deque<immagine>::size_type no_of_images_undo();

  virtual Fl_Scroll*  ritorna_scroll();
  virtual immagine*   ritorna_immagine();
  virtual mol_canvas* ritorna_mol_canvas();


  bist_plugin* actual_plugin();

  /**
   *
   */

  void canvas_resize(int nw_width,int nw_height);

  
  /**
   *
   *Give focus to canvas (main window)
   */

  void canvas_give_focus();


  void canvas_translate(int dx, int dy);


  /**
   *get button set as action defined in editor.hpp
   */

  int get_button_value_as_action();

protected:
  editor()
  :Fl_Double_Window(10,10,""),
   _actual_plugin(0),
   _scroller(LARGH_BUTTON_BAR,ALT_MENU+ALT_TOOLBAR, w()-LARGH_BUTTON_BAR, h()-ALT_MENU-ALT_TOOLBAR),
   _mol_can(LARGH_BUTTON_BAR,ALT_MENU+ALT_TOOLBAR,10,10),
   _il_menu(0, 0,w() , ALT_MENU),
   //riga sotto il menu
   _sup_frame(FL_UP_FRAME, 0, ALT_MENU, LARGH_FIN, ALT_TOOLBAR,""),
   _new_b(PADD_BUTT,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),
   _open_file_b(PADD_BUTT+LARG_BUTTON_TOP,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),
   _save_file_b(PADD_BUTT+LARG_BUTTON_TOP*2,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),
   _save_file_as_b(PADD_BUTT+LARG_BUTTON_TOP*3,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),
   _exp_ps_b(PADD_BUTT+LARG_BUTTON_TOP*4,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),
   _exp_png_b(PADD_BUTT+LARG_BUTTON_TOP*5,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),
   _delete_selected(PADD_BUTT+LARG_BUTTON_TOP*6,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),


   _undo_b(PADD_BUTT+LARG_BUTTON_TOP*8,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),
   _redo_b(PADD_BUTT+LARG_BUTTON_TOP*9,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),


   _b_paste(PADD_BUTT+LARG_BUTTON_TOP*10,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),

   _zoom_b(PADD_BUTT+LARG_BUTTON_TOP*12,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),
   _unzoom_1o1_b(PADD_BUTT+LARG_BUTTON_TOP*13,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),
   _unzoom_b(PADD_BUTT+LARG_BUTTON_TOP*14,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),


   //barra di sinistra
   _select_atom(PADD_BUTT,ALT_MENU+PADD_BUTT+ALT_TOOLBAR,LARG_BUTTON_LEFT,ALT_BUTT_LEFT),
   _select_group(PADD_BUTT*2+LARG_BUTTON_LEFT,
		 ALT_MENU+PADD_BUTT+ALT_TOOLBAR,
		 LARG_BUTTON_LEFT,
		 ALT_BUTT_LEFT),

   _rotate_sel(PADD_BUTT,
	       ALT_MENU+PADD_BUTT+ALT_TOOLBAR+LARG_BUTTON_LEFT,
	       LARG_BUTTON_LEFT,ALT_BUTT_LEFT),
   _b_fixed_rotation(PADD_BUTT*2+LARG_BUTTON_LEFT,
		     ALT_MENU+PADD_BUTT+ALT_TOOLBAR+LARG_BUTTON_LEFT,
		     LARG_BUTTON_LEFT,ALT_BUTT_LEFT),

   _b_rotate_3d(PADD_BUTT,ALT_MENU+PADD_BUTT+ALT_TOOLBAR+LARG_BUTTON_LEFT*2,
		LARG_BUTTON_LEFT,ALT_BUTT_LEFT),
   _scale_sel(PADD_BUTT*2+LARG_BUTTON_LEFT,ALT_MENU+PADD_BUTT+ALT_TOOLBAR+LARG_BUTTON_LEFT*2,
	      LARG_BUTTON_LEFT,ALT_BUTT_LEFT),

   _b_flip_v(PADD_BUTT,
	     ALT_MENU+PADD_BUTT+ALT_TOOLBAR+LARG_BUTTON_LEFT*3,
	     LARG_BUTTON_LEFT,ALT_BUTT_LEFT),
   _b_flip_h(PADD_BUTT*2+LARG_BUTTON_LEFT,
	     ALT_MENU+PADD_BUTT+ALT_TOOLBAR+LARG_BUTTON_LEFT*3,
	     LARG_BUTTON_LEFT,ALT_BUTT_LEFT),



   _kill(PADD_BUTT,
	 ALT_MENU+PADD_BUTT+ALT_TOOLBAR+LARG_BUTTON_LEFT*4,
	 LARG_BUTTON_LEFT,ALT_BUTT_LEFT),
   _select_color(PADD_BUTT*2+LARG_BUTTON_LEFT,
		 ALT_MENU+PADD_BUTT+ALT_TOOLBAR+LARG_BUTTON_LEFT*4,
		 LARG_BUTTON_LEFT,ALT_BUTT_LEFT),

   //SPACER from here
   _draw_single_bond(PADD_BUTT,
		     ALT_MENU+PADD_BUTT+ALT_TOOLBAR+SPACER+LARG_BUTTON_LEFT*5,
		     LARG_BUTTON_LEFT,ALT_BUTT_LEFT),
   _draw_arrow(PADD_BUTT*2+LARG_BUTTON_LEFT,
	       ALT_MENU+PADD_BUTT+ALT_TOOLBAR+SPACER+LARG_BUTTON_LEFT*5,
	       LARG_BUTTON_LEFT,ALT_BUTT_LEFT),



   _draw_double_bond(PADD_BUTT,
		     ALT_MENU+PADD_BUTT+ALT_TOOLBAR+SPACER+LARG_BUTTON_LEFT*6,
		     LARG_BUTTON_LEFT,ALT_BUTT_LEFT),
   _draw_bezier(PADD_BUTT*2+LARG_BUTTON_LEFT,
	       ALT_MENU+PADD_BUTT+ALT_TOOLBAR+SPACER+LARG_BUTTON_LEFT*6,
	       LARG_BUTTON_LEFT,ALT_BUTT_LEFT),

   _draw_triple_bond(PADD_BUTT,
		     ALT_MENU+PADD_BUTT+ALT_TOOLBAR+SPACER+LARG_BUTTON_LEFT*7,
		     LARG_BUTTON_LEFT,ALT_BUTT_LEFT),
   _draw_arc(PADD_BUTT*2+LARG_BUTTON_LEFT,
	       ALT_MENU+PADD_BUTT+ALT_TOOLBAR+SPACER+LARG_BUTTON_LEFT*7,
	       LARG_BUTTON_LEFT,ALT_BUTT_LEFT),
   _draw_box(PADD_BUTT,
	       ALT_MENU+PADD_BUTT+ALT_TOOLBAR+SPACER+LARG_BUTTON_LEFT*8,
	       LARG_BUTTON_LEFT,ALT_BUTT_LEFT),
   _draw_chain(PADD_BUTT*2+LARG_BUTTON_LEFT,
	       ALT_MENU+PADD_BUTT+ALT_TOOLBAR+SPACER+LARG_BUTTON_LEFT*8,
	       LARG_BUTTON_LEFT,ALT_BUTT_LEFT),
   _draw_etich(PADD_BUTT,
	       ALT_MENU+PADD_BUTT+ALT_TOOLBAR+SPACER+LARG_BUTTON_LEFT*9,
	       LARG_BUTTON_LEFT,ALT_BUTT_LEFT),


   _draw_orb(PADD_BUTT*2+LARG_BUTTON_LEFT,
	    ALT_MENU+PADD_BUTT+ALT_TOOLBAR+SPACER+LARG_BUTTON_LEFT*9,
	    LARG_BUTTON_LEFT,ALT_BUTT_LEFT),
   _add_lib(PADD_BUTT,
	    ALT_MENU+PADD_BUTT+ALT_TOOLBAR+SPACER+LARG_BUTTON_LEFT*10,
	    LARG_BUTTON_LEFT,ALT_BUTT_LEFT),


   //INFORMATION BOX
   _inf_frame(FL_EMBOSSED_BOX,0,h()-ALT_BUTT_TOP,FIN_W,HEIGHT_INF_BAR,""),
   _file_saved(false)
  {


  }


  virtual void draw();

  virtual int handle(int e);

  /**
   *Draw mouse coordinate in information_bar
   *\return width of the string;
   */

  int draw_mouse_cordinate_inf_bar(int x=0, int font_size=14);

  /**
   *set button in gui and optionally action too
   */
  void set_button(int which, bool set_action=true);

  void populate_plugin_menu(std::string startdir);


  bist_plugin* _actual_plugin;

  Fl_Scroll _scroller;

  mol_canvas _mol_can;

  Fl_Help_Dialog* _help_dialog;

  Fl_Menu_Bar _il_menu;


  Fl_Box     _sup_frame;
  Fl_Button  _new_b;
  Fl_Button  _open_file_b;
  Fl_Button  _save_file_b;
  Fl_Button  _save_file_as_b;
  Fl_Button  _exp_ps_b;
  Fl_Button  _exp_png_b;
  Fl_Button  _delete_selected;
  Fl_Button  _undo_b;
  Fl_Button  _redo_b;


  Fl_Button     _b_paste;


  Fl_Button  _zoom_b;
  Fl_Button  _unzoom_1o1_b;
  Fl_Button  _unzoom_b;


  Fl_Button  _select_atom;
  Fl_Button  _select_group;
  Fl_Button  _rotate_sel;
  Fl_Button  _b_fixed_rotation;
  Fl_Button  _b_rotate_3d;
  Fl_Button  _scale_sel;
  Fl_Button  _b_flip_v;
  Fl_Button  _b_flip_h;


  Fl_Button  _kill;
  Fl_Button  _select_color;
  Fl_Button  _draw_single_bond;
  Fl_Button  _draw_arrow;
  Fl_Button  _draw_double_bond;
  Fl_Button  _draw_bezier;

  Fl_Button  _draw_triple_bond;
  Fl_Button  _draw_arc;
  Fl_Button  _draw_box;
  Fl_Button  _draw_chain;
  Fl_Button  _draw_etich;
  Fl_Button  _draw_orb;
  Fl_Button  _add_lib;


  string _file_opened;

  Fl_Box _inf_frame;

  /**
   *library name is the key while filesystem path is the value
   *
   */
  std::map<std::string, std::string> _dl_plugin_path;

  /*
   *l'indirizzo dei simboli della libreria
   */

  void* _dl_handle;


  
  /**
   *      front
   *   +---------------+
   *   |       	       |
   *   |       	       |
   *   |               |
   *   |               |
   *   |               |
   *   |               |
   *   +---------------+
   *      back
   */


  

  std::deque<immagine> _immagini;
  std::deque<immagine> _redo_immagini;


  bool _file_saved;

};


