/*

    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/>.
*/
#define DEFAULT_ARROW_GAP 0.25
#define UTILS_ARROW_PLOTTER_LINE_WIDTH .1



/**
 *generate a ring
 *\param side_lenght lenght of the side
 *\numside number of sides
 */

gruppo create_ring(float side_lenght, float numsides, bool aromatic=false) throw (out_of_range);




/**
 * Remap font for export
 */

string remap_ps_font(int fltkfont);

/**
 * Remap color component from 32 to 488 bit
 */

int remap_color_48(int trentadue);


float remap_color_1(int byte);

/**
 * Remap y-axis for export
 */

float remap_y_ps(float vx);



void draw_pango_string(std::string st,int x, int y, std::string font,int dim,
                       int cr, int cg, int cb);

/**
 * Find a point belonging the line perpendicular to that defined by the particular points.
 *
 *\param dax  
 *\param day  Coordinates of starting point 
 
 *
 *\param ax Ascissa delpunto sul quale disegnare la freccia
 *\param ay Ascissa delpunto sul quale disegnare la freccia
 *\param gap distance between point and the line
 *\param verso the side toward which to draw the arrow
 *
 * Parameters below used to store coordinate of the found point.
 *\param resx - store X-coordinate
 *\param resy - store Y-coordinate
 *
 *
 */

void is_perpendicular(float dax, float day, 
			  float ax, float ay, 
			  bool verso,float gap,
			  float& resx, float& resy);

  /**
   * Deriving the equation of a line  from two points belonging.
   *
   *Coordinates the first point:
   *\param x1 the abscissa
   *\param y1 the ordinata
   *
   *Coordinates the second point:
   *\param x2 the abscissa
   *\param y2 the ordinata
   *
   *\param m the angular coefficient
   *\param q 
   *
   * return false in case points has the same coordinates, 
   * otherwise function returns false and setting 
   * m and y values to 0.
   */

bool  rett_eqn(float x1, float y1, 
		float x2, float y2, 
		float& m, float& q);




/**
 *calculate vertices of an arrowhead
 *
 *\param dax abscissa of initial point
 *
 *
 *\param day the initial point ordinata
 *
 *
 *\param ax Ascissa delpunto sul quale disegnare la freccia
 *\param ay Ascissa delpunto sul quale disegnare la freccia
 *\param thick arrows thickness
 *\param to the side toward to which draw an arrow
 */




void calculate_arrow_points(float dax, float day, 
                            float ax, float ay, 
                            float thick,float arr_w, 
                            float arr_h, float arr_gap,
                            int cr, int cg, int cb,
                            std::vector<float>& results_x,
                            std::vector<float>& results_y,
                            bool to=false);




/**
 *disegna una punta della freccia.
 *
 *\param dax Ascissa corrispondente  all'inizio del segmento sul quale
 *disegnare la freccia.
 *
 *\param day Ascissa corrispondente  all'inizio del segmento sul quale
 *disegnare la freccia.
 *
 *\param ax Ascissa delpunto sul quale disegnare la freccia
 *\param ay Ascissa delpunto sul quale disegnare la freccia
 *\param spessore lo spessore della freccia
 *\param verso il lato verso cui disegnare la freccia.
 */


void draw_arrow(float dax, float day, 
		     float ax, float ay, 
		     float spessore,float arr_w, 
		     float arr_h, float arr_gap,
                     int cr, int cg, int cb,
		     bool verso=false);



/**
 *Disegna  una retta  parallela a  quella definita  dai punti  dati come
 *parametri.
 *
 *\param dax  Ascissa corrispondente  all'inizio del segmento  sul quale
 *disegnare la freccia.
 *
 *\param day  Ascissa corrispondente  all'inizio del segmento  sul quale
 *disegnare la freccia.
 *
 *\param ax Ascissa delpunto sul quale disegnare la freccia
 *\param ay Ascissa delpunto sul quale disegnare la freccia
 *\param gap la retta sara' piu' corta della principale di?
 *\param verso il lato verso cui disegnare la freccia.
 *\param tratt true se il legame e' tatteggiato, false se pieno
 *
 */

void draw_parallel(float dax, float day, 
		       float ax, float ay,
                       int cr, int cg,int cb,
                       bool verso=false, 
		       float gap=MULTIPLE_BOND_GAP, bool tratt=false, bool noaccorc=false);


/**
 *\return true o false a seconda del semipiano di appartenenza:
 *true se y>=mx+q false se y<mx+q 
 *
 *\param x l'ascissa del punto da valutare
 *\param y l'ordinata del punto da valutare
 *\param xrt l'ascissa di un punto appartenente alla retta
 *\param yrt l'ordinata di un punto appartenente alla retta
 *\param xrt2 l'ascissa di un punto appartenente alla retta
 *\param yrt2 l'ordinata di un punto appartenente alla retta

 *
 */

bool return_half_plane(float x, float y, 
			   float xrt, float yrt,
			   float xrt2, float yrt2
			   );


/**
 *trova il punto di intersezione tra un segmento ed una retta verticale.
 *\param da_x ascissa del primo punto del segmento
 *\param da_y ordinata del primo punto del segmento
 *\param fino_x ascissa del secondo punto del segmento
 *\param fino_y ordinata del secondo punto del segmento
 *
 *\param x_edge ascissa della retta verticale
 *\return l'ordinata del punto di intersezione
 */

float b_clip_v(float da_x, float da_y, float fino_x, float fino_y, float x_edge);


/**
 *trova il punto di intersezione tra un segmento ed una retta orizzontale.
 *\param da_x ascissa del primo punto del segmento
 *\param da_y ordinata del primo punto del segmento
 *\param fino_x ascissa del secondo punto del segmento
 *\param fino_y ordinata del secondo punto del segmento
 *
 *\param y_edge ascissa della retta verticale
 *\return l'ascissa del punto di intersezione
 */

float b_clip_h(float da_x, float da_y, float fino_x, float fino_y, float y_edge);



/**
 *\return true se il punto appartiene al segmento, false altrimenti
 */

bool line_belongs(int x_m, int y_m, 
		      float st_x, float st_y,
		      float e_x, float e_y,
		      int thickness=1);




/**
 *disegna un bel pallino in posizione x y e raggio uguale a RAGGIO_EL
 */

void draw_point(float x, float y);


void draw_shadowed_point(float x, float y, int r, int g, int b);

/**
 *disegna quattro bei pallini ai vertici della box passata come argomento
 */

void draw_frame(int x, int y , int w ,int h);

/**
 *Ritorna la corretta bounding box per l'etichetta in relazione all'allineamento./
 */

void get_bb_etic(etichetta& et, float& x, float& y);


void get_visual_bb_etic(etichetta& et, float& x, float& y);


/**
 *Ottieni i font corretti
 */

void get_font_handle(etichetta et, int &font_fltk, string &font_libplot);


/**
 *Mostra "non ancora implementato"
 */

void not_impl();



/**
 *\param format il formato del file come estensione
 *\return true se il formato e' supportato, false altrimenti
 */

bool format_supported(string format);


/**
 *ricava l'hash per una stringa
 *\param value la stringa dalla quale ricavare l'hash
 *\return l'hash come unsigned int ( max 33554393)
 */


unsigned int create_hash(string value);


/**
 *trova le coordinate del punto di intersezione tra due rette
 *
 *\param xy1  
 *\param xy2 array  delle coordinate dei  punti appartenenti all rette che si intersecano xy1 = {x, y, x2, y2}
 *\param risx ascissa dell'intersezione
 *\param risy ordinata dell'intersezione
 *\return true se le rette non sono parallele o coincidenti , false altrimenti
 */

bool is_intersection(float* xy1,float* xy2, float& resx, float& resy);




class Splash_Widget: public Fl_Widget {
public:
  Splash_Widget(int x,int y,int w, int h);

  virtual ~Splash_Widget();

protected:
  virtual void draw();
};


/**
 *classe per disegnare la splashpage
 */


class Splash_Window: public Fl_Window {

public:
  Splash_Window();
  virtual ~Splash_Window();
  virtual int handle(int e);
  static  void hide_win_timeout(void* win);
  static const double splash_persistence;
  static const int splash_w;
  static const int splash_h;
protected:
  Splash_Widget _logo;
};




void merge_groups(gruppo* g_st , gruppo* g_arr,atomo* st, atomo* arr, int tipo);



bool calc_bb_gen_intersect(pair<float,float>& lu1,
                           pair<float,float>& rd1,
                           pair<float,float>& lu2,
                           pair<float,float>& rd2);

/**
 *calcola la bounding box
 */

void calc_bb_gen(vector<float> x, vector<float>y, 
		 pair<float,float>& ld,
		 pair<float,float>& ru);


/**
 *de-scala pt rispetto a __pref.getZoom();
 */

float descale(float scaled);

/**
 *scala pt rispetto a __pref.getZoom();
 */

float scale_z(float scaled);


float scale_center_point(double point,double trasl, double zoom);


vector<float> correct_arrow(float xtan_st, float ytan_st, 
			    float xtan_end, float ytan_end, 
			    float entity=5/8);



int ask_overwrite_file(string the_file);

int ask_overwrite_file_console(string the_file);

/**
 *bezier curve
 */

std::pair<float, float> poly_bezier(float x0, float y0,
				    float x1, float y1,
				    float x2, float y2,
				    float x3, float y3,
				    float t) throw (out_of_range);
/**
 *return bool if value of v i inside interval (ref-offset;ref+offset)
 */

template <class T> bool similar_to(T v, T ref, T offset){
  bool res=false;
  if( (v >= ref - offset) && (v <= ref + offset) ){
    res=!res;
  }
  return res;
}


/**
 *rotate point (around pivot (0,0)) counterclockwise
 *\param angle angle in radiant 
 */

std::pair<float, float> rotate_point(float x, float y, float angle);

/**
 *Print redfog wisdom to stdout
 */

void print_redfog_wisdom();



float rad2deg(float angle);

float deg2rad(float angle);

/**
 *Attract mouse to magnetic point as specified in preferences
 */

void attract_mouse_to_magnetic_point(int* x_m, int* y_m);



std::string trim(std::string s,const std::string drop=" \t");

/**
 *\param desidered the string representing a font
 *\destination the font whre to copy destination
 *\the number of fonts in fonttable
 */

void search_for_font(const char* desidered, Fl_Font destination, int num_fonts);

void set_actual_font_from_prefs();


bond_type shift_bond_type(bond_type curr);
  


/**
 *
 *guess type of input file
 */
bool guess_is_mdl_file(std::string f);


/**
 *
 *guess type of input file
 */
bool guess_is_cml_file(std::string f);


/**
 *check if file is an ELF shared object
 *\param file path of the shared object
 *\return true if the file is a shared object false otherwise
 */

bool is_ELF_shared_object(std::string file);


void s_regmatch(std::string regex,std::string st,
                std::vector<std::string>& vec_res,
                bool case_ins);

std::string s_replace(std::string regex, std::string where,
	       std::string what,
	       bool case_ins);


proc_bezier* add_bezier_along_circle(gruppo* grp, float center_x, float center_y, float radius , float t1, float t2);


void dialog_position(Fl_Window* win, int offset=100);
