/*   EXTRAITS DE LA LICENCE
	Copyright CEA, contributeurs : Luc BILLARD et Damien
	CALISTE, laboratoire L_Sim, (2001-2005)
  
	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-2005)

	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 INTERACTIVE_H
#define INTERACTIVE_H

#include <glib.h>

#include "view.h"
#include <visu_nodes.h>
#include <visu_data.h>
#include <extensions/nodes.h>
#include <renderingBackend/visu_actionInterface.h>

/**
 * VisuInteractiveMethod:
 * @interactive_constrained: the camera is moved keeping the north
 * pole up. The north pole is defined by the Z axis et periodic
 * boundary conditions and by normal to surface in surface conditions.
 * @interactive_walker: the camera is moved following the mouse moves,
 * orienting the view as a walker would do along a sphere.
 *
 * Describes the different possible methods for observe moves.
 */
typedef enum
  {
    interactive_constrained,
    interactive_walker
  } VisuInteractiveMethod;

/**
 * VisuInteractiveId:
 * @interactive_none: no interaction ;
 * @interactive_observe: interaction to rotate the view ;
 * @interactive_measureAndObserve: interaction to rotate the view and
 * access limited pick action on the right click ;
 * @interactive_measure: interaction to pick and measure ;
 * @interactive_pick: interaction to select node ;
 * @interactive_move: interaction to move nodes ;
 * @interactive_mark: interaction to mark nodes ;
 * @interactive_drag: interaction to get drag moves of the mouse.
 *
 * These are the possible mouse interaction that are implemented.
 */
typedef enum
  {
    interactive_none,
    interactive_observe,
    interactive_measureAndObserve,
    interactive_measure,
    interactive_pick,
    interactive_move,
    interactive_mark,
    interactive_drag
  } VisuInteractiveId;

/**
 * VisuInteractivePick:
 * @PICK_NONE: click to void ;
 * @PICK_SELECTED: click to select one node ;
 * @PICK_DISTANCE: click to measure a distance between two nodes ;
 * @PICK_ANGLE: click to measure an angle ;
 * @PICK_HIGHLIGHT: click to highlight a node ;
 * @PICK_REFERENCE_1: click to select a first reference ;
 * @PICK_UNREFERENCE_1: click to un-select a first reference ;
 * @PICK_REFERENCE_2: click to select a second reference ;
 * @PICK_UNREFERENCE_2: click to un-select a second reference ;
 * @PICK_INFORMATION: click to measure distances and angles around one
 * node ;
 * @PICK_REGION: click to select a list of nodes.
 *
 * Possible significations of a click.
 */
typedef enum
  {
    PICK_NONE,
    PICK_SELECTED,
    PICK_DISTANCE,
    PICK_ANGLE,
    PICK_HIGHLIGHT,
    PICK_REFERENCE_1,
    PICK_UNREFERENCE_1,
    PICK_REFERENCE_2,
    PICK_UNREFERENCE_2,
    PICK_INFORMATION,
    PICK_REGION
  } VisuInteractivePick;

/**
 * VisuInteractivePickError:
 * @PICK_ERROR_NONE: no error during click ;
 * @PICK_ERROR_NO_SELECTION: click to sleect but nothing selected ;
 * @PICK_ERROR_SAME_REF: click to set a reference but reference
 * already exists ;
 * @PICK_ERROR_REF1: click to select a first reference but impossible
 * to choose this one ;
 * @PICK_ERROR_REF2: the same for second reference.
 *
 * Possible errors to occur when pick or measure.
 */
typedef enum
  {
    PICK_ERROR_NONE,
    PICK_ERROR_NO_SELECTION,
    PICK_ERROR_SAME_REF,
    PICK_ERROR_REF1,
    PICK_ERROR_REF2
  } VisuInteractivePickError;

/**
 * VISU_TYPE_INTERACTIVE:
 *
 * return the type of #VisuInteractive.
 */
#define VISU_TYPE_INTERACTIVE	     (visu_interactive_get_type ())
/**
 * VISU_INTERACTIVE:
 * @obj: a #GObject to cast.
 *
 * Cast the given @obj into #VisuInteractive type.
 */
#define VISU_INTERACTIVE(obj)	     (G_TYPE_CHECK_INSTANCE_CAST(obj, VISU_TYPE_INTERACTIVE, VisuInteractive))
/**
 * VISU_INTERACTIVE_CLASS:
 * @klass: a #GObjectClass to cast.
 *
 * Cast the given @klass into #VisuInteractiveClass.
 */
#define VISU_INTERACTIVE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST(klass, VISU_TYPE_INTERACTIVE, VisuInteractiveClass))
/**
 * VISU_IS_INTERACTIVE:
 * @obj: a #GObject to test.
 *
 * Test if the given @ogj is of the type of #VisuInteractive object.
 */
#define VISU_IS_INTERACTIVE(obj)    (G_TYPE_CHECK_INSTANCE_TYPE(obj, VISU_TYPE_INTERACTIVE))
/**
 * VISU_IS_INTERACTIVE_CLASS:
 * @klass: a #GObjectClass to test.
 *
 * Test if the given @klass is of the type of #VisuInteractiveClass class.
 */
#define VISU_IS_INTERACTIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE(klass, VISU_TYPE_INTERACTIVE))
/**
 * VISU_INTERACTIVE_GET_CLASS:
 * @obj: a #GObject to get the class of.
 *
 * It returns the class of the given @obj.
 */
#define VISU_INTERACTIVE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS(obj, VISU_TYPE_INTERACTIVE, VisuInteractiveClass))

typedef struct _VisuInteractiveClass VisuInteractiveClass;
typedef struct _VisuInteractive VisuInteractive;

/**
 * visu_interactive_get_type:
 *
 * This method returns the type of #VisuInteractive, use VISU_TYPE_INTERACTIVE instead.
 *
 * Returns: the type of #VisuInteractive.
 */
GType visu_interactive_get_type(void);

struct _VisuInteractiveClass
{
  VisuObjectClass parent;

  VisuInteractiveMethod preferedObserveMethod;

  /* The save camera positions are implemented as
     a circular list we a pointer on the current head. */
  GList *savedCameras, *lastCamera;
};

/**
 * visu_interactive_class_setPreferedObserveMethod:
 * @method: an integer that identify the method, see #OPENGL_OBSERVE_CONSTRAINED,
 *          and #OPENGL_OBSERVE_WALKER flags.
 *
 * There are two methods to move the camera in a pick and observe sesion. These
 * two methods are described in the commentary of the keys #OPENGL_OBSERVE_CONSTRAINED
 * an d#OPENGL_OBSERVE_WALKER.
 */
void visu_interactive_class_setPreferedObserveMethod(VisuInteractiveMethod method);
/**
 * visu_interactive_class_getPreferedObserveMethod:
 *
 * There are two methods to move the camera in a pick and observe sesion. These
 * two methods are described in the commentary of the keys #OPENGL_OBSERVE_CONSTRAINED
 * an d#OPENGL_OBSERVE_WALKER.
 *
 * Returns: an integer that identify the method, see #OPENGL_OBSERVE_CONSTRAINED,
 *          and #OPENGL_OBSERVE_WALKER flags.
 */
VisuInteractiveMethod visu_interactive_class_getPreferedObserveMethod();

VisuInteractive* visu_interactive_new(VisuInteractiveId type);

gboolean visu_interactive_setType(VisuInteractive *inter, VisuInteractiveId id);
VisuInteractiveId visu_interactive_getType(VisuInteractive *inter);

void visu_interactive_handleEvent(VisuInteractive *inter,
                                  VisuGlView *view, ToolSimplifiedEvents *ev);
ToolSimplifiedEvents* visu_interactive_getEvent(VisuInteractive *inter);

void visu_interactive_setNodeList(VisuInteractive *inter, VisuGlExtNodes *nodes);
void visu_interactive_setMovingNodes(VisuInteractive *inter, GArray *nodeIds);
void visu_interactive_setMovingAxe(VisuInteractive *inter, float axe[3]);

void visu_interactive_highlight(VisuInteractive *inter, guint nodeId);

VisuGlCamera* visu_interactive_popSavedCamera(VisuInteractive *inter);
void visu_interactive_pushSavedCamera(VisuInteractive *inter, VisuGlCamera *camera);
void visu_interactive_getSavedCameras(VisuInteractive *inter,
				     GList **cameras, GList **head);
void visu_interactive_setReferences(VisuInteractive *inter, VisuInteractive *from);

void visu_interactive_setMessage(VisuInteractive *inter, const gchar *message);
const gchar* visu_interactive_getMessage(VisuInteractive *inter);

/**
 * visu_interactive_class_getNodes2DCoordinates: (skip)
 * @dataObj: a #VisuData object ;
 * @nodeIds: an array of #VisuNode ids ;
 * @nNodes: the number of nodes in the array ;
 * @coordinates2D: an array of nodes 2D coordinates ;
 * @size: the size of the coordinates array.
 *
 * From nodes ids, compute and store in @coordinates2D their 2D coordinates.
 */
void visu_interactive_class_getNodes2DCoordinates(VisuData *dataObj, guint *nodeIds,
	guint nNodes, float *coordinates2D, guint *size);

#endif
