/*   EXTRAITS DE LA LICENCE
	Copyright CEA, contributeurs : Luc BILLARD et Damien
	CALISTE, laboratoire L_Sim, (2001-2006)
  
	Adresse mèl :
	BILLARD, non joignable par mèl ;
	CALISTE, damien P caliste AT cea P fr.

	Ce logiciel est un programme informatique servant à visualiser des
	structures atomiques dans un rendu pseudo-3D. 

	Ce logiciel est régi par la licence CeCILL soumise au droit français et
	respectant les principes de diffusion des logiciels libres. Vous pouvez
	utiliser, modifier et/ou redistribuer ce programme sous les conditions
	de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA 
	sur le site "http://www.cecill.info".

	Le fait que vous puissiez accéder à cet en-tête signifie que vous avez 
	pris connaissance de la licence CeCILL, et que vous en avez accepté les
	termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel).
*/

/*   LICENCE SUM UP
	Copyright CEA, contributors : Luc BILLARD et Damien
	CALISTE, laboratoire L_Sim, (2001-2006)

	E-mail address:
	BILLARD, not reachable any more ;
	CALISTE, damien P caliste AT cea P fr.

	This software is a computer program whose purpose is to visualize atomic
	configurations in 3D.

	This software is governed by the CeCILL  license under French law and
	abiding by the rules of distribution of free software.  You can  use, 
	modify and/ or redistribute the software under the terms of the CeCILL
	license as circulated by CEA, CNRS and INRIA at the following URL
	"http://www.cecill.info". 

	The fact that you are presently reading this means that you have had
	knowledge of the CeCILL license and that you accept its terms. You can
	find a copy of this licence shipped with this software at Documentation/licence.en.txt.
*/
#ifndef VISU_PAIRS
#define VISU_PAIRS

#include "visu_data.h"

/**
 * PAIRS_MIN
 *
 * Flag used to define the minimum length to draw pair. This is useful with
 * the getPairsDistance() and the getPairsDistance() methods.
 */
#define PAIRS_MIN 0
/**
 * PAIRS_MAX
 *
 * Flag used to define the maximum length to draw pair. This is useful with
 * the getPairsDistance() and the getPairsDistance() methods.
 */
#define PAIRS_MAX 1

/**
 * PAIRS_COLOR_R
 *
 * Flag used to define the red color of a pair. This is useful to access
 * the rgba array of the #Color object return by setPairsColor().
 */
#define PAIRS_COLOR_R 0
/**
 * PAIRS_COLOR_G
 *
 * Flag used to define the green color of a pair. This is useful to access
 * the rgba array of the #Color object return by setPairsColor().
 */
#define PAIRS_COLOR_G 1
/**
 * PAIRS_COLOR_B
 *
 * Flag used to define the blue color of a pair. This is useful to access
 * the rgba array of the #Color object return by setPairsColor().
 */
#define PAIRS_COLOR_B 2

/**
 * pairsData_struct:
 * @name1: the name of the first #VisuElement ;
 * @name2: the name of the second #VisuElement ;
 * @minMax: storage for the length bounds for drawn pairs ;
 * @properties: a storage for userData ;
 * @drawn: a boolean to say if the pair is drawn or not.
 *
 * This structure is used to describe a pair between two elements.
 * These elements are described by their name. A pair is drawn only
 * its length is between the minimum and the maximum value stored in
 * the minMax array.
 */
struct pairsData_struct
{
  char *name1, *name2;
  float minMax[2];
  GHashTable *properties;
  gboolean drawn;
};
/**
 * PairsData:
 * 
 * A common way to name #pairsData_struct objects.
 */
typedef struct pairsData_struct PairsData;


/**
 * initEndOpenGlPairsFunc:
 *
 * Prototype of functions called at the beginning and
 * the end of opengl pairs drawing. Such methods are useful
 * to change some OpenGL variables such as lighting or
 * blending...
 */
typedef void (*initEndOpenGlPairsFunc)();
/**
 * startEndPairsFunc:
 * @ele1: a #VisuElement object ;
 * @ele2: a #VisuElement object ;
 * @data: a #PairsData object.
 *
 * Prototype of functions called at the beginning and
 * the end of drawing of each pairs types. @ele1 and @ele2
 * arguments are the two elements between the pair defined by @data is drawn.
 * This is useful to set some OpenGL definition specific to each pair, such
 * as the color for example.
 */
typedef void (*startEndPairsFunc)(VisuElement *ele1, VisuElement *ele2, PairsData *data);
/**
 * pairDefinitionFunc:
 * @ele1: a #VisuElement object ;
 * @ele2: a #VisuElement object ;
 * @data: a #PairsData object ;
 * @view: a #OpenGLView object, giving some constants describing
 *        the OpenGL scene ;
 * @x1: a floating point value ;
 * @y1: a floating point value ;
 * @z1: a floating point value ;
 * @x2: a floating point value ;
 * @y2: a floating point value ;
 * @z2: a floating point value ;
 * @d2: a floating point value.
 *
 * Prototype of function to draw a pair. Such function are called each time a pair
 * is drawn between the two points (@x1, @y1, @z1) and (@x2, @y2, @z2). The @d2 argument
 * is the square distance between the two points.
 */
typedef void (*pairDefinitionFunc)(VisuElement *ele1, VisuElement *ele2, PairsData *data,
				   OpenGLView *view, double x1, double y1, double z1,
				   double x2, double y2, double z2, float d2);
/**
 * foreachPairsFunc:
 * @data: a #PairsData object ;
 * @userData: some user defined data.
 *
 * Prototype of functions called with the foreach method apply to each
 * pairs.
 */
typedef void (*foreachPairsFunc)(PairsData *data, gpointer userData);

/**
 * PairsExtension_struct:
 *
 * Structure to store pairs extensions. All fields are private and should not
 * be accessed directly.
 */
struct PairsExtension_struct;
/**
 * PairsExtension:
 * 
 * Common naming for #PairsExtension_struct objects.
 */
typedef struct PairsExtension_struct PairsExtension;

/**
 * pairsExtension_new:
 * @name: name of the extension (must be non null) ;
 * @printName: a string to label the method that can be safely translated ;
 * @description: a brief description of the extension (can be null) ;
 * @sensitive: a boolean 0 or 1 ;
 * @init: a initEndOpenGlPairsFunc() method or NULL ;
 * @stop: a initEndOpenGlPairsFunc() method or NULL ;
 * @start: a startEndPairsFunc() method or NULL ;
 * @end: a startEndPairsFunc() method or NULL ;
 * @draw: a pairDefinitionFunc() method (not NULL).
 *
 * This creates a new pairs extension. Such an extension describes how to draw
 * links (called pairs) between elements. The @sensitive argument is to inform if
 * pairs must be redrawn when the OpenGL engine sends the OpenGLFacetteChanged signal.
 *
 * Returns: the new PairsExtension or null if something wrong happens.
 */
PairsExtension* pairsExtension_new(char* name, char* printName, char* description, int sensitive,
				   initEndOpenGlPairsFunc init, initEndOpenGlPairsFunc stop,
				   startEndPairsFunc start, startEndPairsFunc end,
				   pairDefinitionFunc draw);
/**
 * PairsExtension_free:
 * @extension: the extension to delete.
 *
 * Free all the allocated attributes of the specified method.
 */
void PairsExtension_free(PairsExtension* extension);
/**
 * registerPairsExtension:
 * @extension: an extension.
 *
 * A method used by user to registered a new extension.
 */
void registerPairsExtension(PairsExtension *extension);

/**
 * isValidPairsExtension:
 * @pairsModel: a #PairsExtension object.
 *
 * Test if the given #PairsExtension has been already registered
 * by V_Sim.
 *
 * Returns: 1 if the given extension is already stored.
 */
int isValidPairsExtension(PairsExtension* pairsModel);

/**
 * createPairs:
 * @dataObj: the #VisuData object to create pairs for.
 *
 * This methods recreates the OpenGL list of the #OpenGLExtension associated
 * to the pairs.
 * Thus it is the heart of the pairs drawing. When called, if a
 * valid #PairsExtension has been set with setPairsMethod(), it takes all the
 * nodes and compute all the distances between two different nodes. If this distance
 * is compatible with the distance of drawn pairs for the two elements it calls
 * the pairDefinitionFunc() for these two nodes. WARNING! this method is very expensive
 * in computing cost.
 *
 * Returns: 1 if the OpenGLAskForReDraw signal show be emitted or not.
 */
int createPairs(VisuData *dataObj);

/**
 * setPairsOnOff:
 * @onOff : a boolean 0 or 1.
 * 
 * Turn on or off the pairs.
 *
 * Returns: 1 if createPairs() should be called and then the 'OpenGLAskForReDraw'
 *          signal be emitted.
 */
int setPairsOnOff(int onOff);
/**
 * setPairsMethod:
 * @extension: a #PairsExtension object.
 *
 * Choose the method used to draw pairs. If necessary, createPairs() are called.
 *
 * Returns: 1 if the OpenGLAskForReDraw signal show be emitted or not.
 */
int setPairsMethod(PairsExtension *extension);
/**
 * setPairsAll:
 * @data: a #PairsData object ;
 * @rgb: an array of three floating point values ;
 * @minMax: an array of two floating point values.
 *
 * This method sets length and color informations for the given pairs.
 *
 * Returns: 1 if createPairs() should be called and then the 'OpenGLAskForReDraw'
 *          signal be emitted.
 */
int setPairsAll(PairsData *data, float rgb[3], float minMax[2]);
/**
 * setPairsDrawn:
 * @data: a #PairsData object ;
 * @drawn: a boolean.
 *
 * A pair can or cannot be drawn, use this method to tune it.
 *
 * Returns: 1 if createPairs() should be called.
 */
int setPairsDrawn(PairsData *data, gboolean drawn);
/**
 * getPairsDrawn:
 * @data: a #PairsData object ;
 *
 * A pair can or cannot be drawn, use this method to retrieve its state.
 *
 * Returns: TRUE if pairs can be drawn.
 */
gboolean getPairsDrawn(PairsData *data);
/**
 * setPairsDistance:
 * @val: a floating point value ;
 * @data: a #PairsData object ;
 * @minOrMax: #PAIRS_MAX or #PAIRS_MIN.
 *
 * Set the minimum or the maximum length for the given pair.
 *
 * Returns: 1 if createPairs() should be called or not.
 */
int setPairsDistance(float val, PairsData *data, int minOrMax);
/**
 * setPairsColor:
 * @data: a #PairsData object ;
 * @color: a #Color object..
 *
 * Set the color of the given pair.
 *
 * Returns: 1 if createPairs() should be called or not.
 */
int setPairsColor(PairsData *data, Color *color);
/**
 * setPairsAreOutOfDate:
 *
 * Use this method to change the internal flag that pairs should be
 * rebuilt. It is useful when an extension of pairs has one of its
 * parameters that has changed.
 */
void setPairsAreOutOfDate();
/**
 * getPairsOnOff:
 * 
 * Get the status of pairs, drawn or not.
 *
 * Returns: 1 if pairs are drawn.
 */
int getPairsOnOff();
/**
 * setPairsProperty:
 * @data: a #PairsData object ;
 * @key: a static string ;
 * @value: a pointer to some allocated data.
 *
 * Each pair can store some informations that can be retrieve by a string key.
 * This method is used to registered a new value associated to the key @key.
 */
void setPairsProperty(PairsData *data, const gchar* key, gpointer value);
/**
 * getAllPairsMethods:
 * 
 * Useful to know all #PairsExtension.
 *
 * Returns: a list of all the known #PairsExtension. This list should
 *          be considered read-only.
 */
GList* getAllPairsMethods();
/**
 * getCurrentPairsMethods:
 *
 * If some process need to know the current #PairsExtension. Such extension has
 * been set with setPairsMethod().
 *
 * Returns: the current #PairsExtension, NULL if none has been set.
 */
PairsExtension* getCurrentPairsMethods();
/**
 * getNameOfPairsMethod:
 * @extension: a #PairsExtension object.
 *
 * All #PairsExtension has a name.
 *
 * Returns: a string that is associated to the given #PairsExtension. This string
 *          should not be freed.
 */
char* getNameOfPairsMethod(PairsExtension *extension);
/**
 * getPairsDistance:
 * @ele1: a #VisuElement object ;
 * @ele2: a #VisuElement object ;
 * @minOrMax: #PAIRS_MIN or #PAIRS_MAX.
 *
 * A pair between @ele1 and @ele2 is drawn only if its length is between
 * a minimum and a maximum value. This method can get these values.
 *
 * Returns: the minimum or the maximum value for the pair between @ele1 and @ele2.
 */
float getPairsDistance(VisuElement *ele1, VisuElement *ele2, int minOrMax);
/**
 * getPairsProperty:
 * @data: a #PairsData object ;
 * @key: a static string.
 *
 * Each pair can store some informations that can be retrieve by a string key.
 * This method is used to retrieve a stored value associated to the key @key.
 *
 * Returns: a found value, or NULL if nothing is associated to the @key.
 *          If something is returned it should not be freed.
 */
gpointer getPairsProperty(PairsData *data, const gchar* key);
/* float getPairsColor(VisuElement *ele1, VisuElement *ele2, int color); */
/**
 * getPairsData:
 * @ele1: a #VisuElement object ;
 * @ele2: a #VisuElement object.
 *
 * The object #PairsData is used to characterized the link between two elements.
 *
 * Returns: the #PairsData object associated to the given two elements. If
 *          none exists it is created. The returned value should not be freed.
 */
PairsData* getPairsData(VisuElement *ele1, VisuElement *ele2);
/**
 * foreachPairsData:
 * @whatToDo: a foreachPairsFunc() method ;
 * @userData: some user defined data.
 *
 * The way #PairsData are stored in V_Sim is private and could changed between version.
 * This method is used to apply some method each pairs.
 */
void foreachPairsData(foreachPairsFunc whatToDo, gpointer userData);


/****************/
/* Private area */
/****************/

/* Explicit definition of the structure. */
struct PairsExtension_struct
{
  /* Some variable to describe this OpenGL extension.
     The attribute name is mandatory since it is
     used to identify the method. */
  char* name;
  char* printName;
  char* description;

  int sensitiveToFacette;

  initEndOpenGlPairsFunc initOpenGl;
  initEndOpenGlPairsFunc stopOpenGl;
  startEndPairsFunc beginDrawingPairs;
  startEndPairsFunc endDrawingPairs;
  pairDefinitionFunc drawPairs;
};


/**
 * initPairsModule:
 *
 * Initialise all the variable of this part. It calls all
 * the elements in %listInitPairsFunc (that stores the
 * init function of the pairs extensions). If these elements return
 * valid PairsExtension, they are registered through a call
 * to registerPairsExtension().
 * This method is called by the main program at the initialisation stage and
 * should not be called in others circonstempses.
 *
 * Returns: 1 if everything goes allright during the initialisation.
 */
int initPairsModule();


#endif
