/*   EXTRAITS DE LA LICENCE
	Copyright CEA, contributeurs : Damien
	CALISTE, laboratoire L_Sim, (2017)
  
	Adresses 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 : Damien
	CALISTE, laboratoire L_Sim, (2017)

	E-mail addresses :
	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 SFIELDDIST_H
#define SFIELDDIST_H

#include <glib.h>

#include <extraFunctions/scalarFields.h>

/**
 * VISU_TYPE_SCALAR_FIELD_DATA:
 *
 * return the type of #VisuScalarFieldData.
 */
#define VISU_TYPE_SCALAR_FIELD_DATA	     (visu_scalar_field_data_get_type ())
/**
 * SCALAR_FIELD_DATA:
 * @obj: a #GObject to cast.
 *
 * Cast the given @obj into #VisuScalarFieldData type.
 */
#define VISU_SCALAR_FIELD_DATA(obj)	     (G_TYPE_CHECK_INSTANCE_CAST(obj, VISU_TYPE_SCALAR_FIELD_DATA, VisuScalarFieldData))
/**
 * VISU_SCALAR_FIELD_DATA_CLASS:
 * @klass: a #GObjectClass to cast.
 *
 * Cast the given @klass into #VisuScalarFieldDataClass.
 */
#define VISU_SCALAR_FIELD_DATA_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST(klass, VISU_TYPE_SCALAR_FIELD_DATA, VisuScalarFieldDataClass))
/**
 * VISU_IS_SCALAR_FIELD_DATA:
 * @obj: a #GObject to test.
 *
 * Test if the given @ogj is of the type of #VisuScalarFieldData object.
 */
#define VISU_IS_SCALAR_FIELD_DATA(obj)    (G_TYPE_CHECK_INSTANCE_TYPE(obj, VISU_TYPE_SCALAR_FIELD_DATA))
/**
 * VISU_IS_SCALAR_FIELD_DATA_CLASS:
 * @klass: a #GObjectClass to test.
 *
 * Test if the given @klass is of the type of #VisuScalarFieldDataClass class.
 */
#define VISU_IS_SCALAR_FIELD_DATA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE(klass, VISU_TYPE_SCALAR_FIELD_DATA))
/**
 * VISU_SCALAR_FIELD_DATA_GET_CLASS:
 * @obj: a #GObject to get the class of.
 *
 * It returns the class of the given @obj.
 */
#define VISU_SCALAR_FIELD_DATA_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS(obj, VISU_TYPE_SCALAR_FIELD_DATA, VisuScalarFieldDataClass))

typedef struct _VisuScalarFieldData        VisuScalarFieldData;
typedef struct _VisuScalarFieldDataPrivate VisuScalarFieldDataPrivate;
typedef struct _VisuScalarFieldDataClass   VisuScalarFieldDataClass;

/**
 * VisuScalarFieldData:
 *
 * An opaque structure for the scalar field.
 */
struct _VisuScalarFieldData
{
  VisuScalarField parent;

  VisuScalarFieldDataPrivate *priv;
};

/**
 * VisuScalarFieldDataClass:
 * @parent: the parent class.
 *
 * An opaque structure for the class.
 */
struct _VisuScalarFieldDataClass
{
  VisuScalarFieldClass parent;
};

/**
 * VisuScalarFieldDataOrder:
 * @VISU_SCALAR_FIELD_DATA_XYZ: packed data are ordered x first.
 * @VISU_SCALAR_FIELD_DATA_ZYX: packed data are ordered z first.
 * 
 * Ordering of 3D data.
 **/
typedef enum
  {
    VISU_SCALAR_FIELD_DATA_XYZ,
    VISU_SCALAR_FIELD_DATA_ZYX
  } VisuScalarFieldDataOrder;

/**
 * visu_scalar_field_data_get_type:
 *
 * This method returns the type of #VisuScalarFieldData, use VISU_TYPE_SCALAR_FIELD_DATA instead.
 *
 * Returns: the type of #VisuScalarFieldData.
 */
GType visu_scalar_field_data_get_type(void);

GList* visu_scalar_field_data_new_fromFile(const gchar *filename, GHashTable *table,
                                           GCancellable *cancel,
                                           GAsyncReadyCallback callback,
                                           gpointer user_data);
GList* visu_scalar_field_data_new_fromFileSync(const gchar *filename, GHashTable *table,
                                               GCancellable *cancel, GError **error);

void visu_scalar_field_data_set(VisuScalarFieldData *field, GArray *data,
                                VisuScalarFieldDataOrder xyzOrder);

const GArray* visu_scalar_field_data_getArray(const VisuScalarFieldData *field);

/* Handling load methos. */
/**
 * VISU_TYPE_SCALAR_FIELD_METHOD:
 *
 * Return the associated #GType to the VisuScalarFieldMethod objects.
 */
#define VISU_TYPE_SCALAR_FIELD_METHOD         (visu_scalar_field_method_get_type ())
/**
 * VISU_SCALAR_FIELD_METHOD:
 * @obj: the widget to cast.
 *
 * Cast the given object to a #VisuScalarFieldMethod object.
 */
#define VISU_SCALAR_FIELD_METHOD(obj)         (G_TYPE_CHECK_INSTANCE_CAST ((obj), VISU_TYPE_SCALAR_FIELD_METHOD, VisuScalarFieldMethod))
/**
 * VISU_SCALAR_FIELD_METHOD_CLASS:
 * @klass: the class to cast.
 *
 * Cast the given class to a #VisuScalarFieldMethodClass object.
 */
#define VISU_SCALAR_FIELD_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), VISU_TYPE_SCALAR_FIELD_METHOD, VisuScalarFieldMethodClass))
/**
 * VISU_IS_SCALAR_FIELD_METHOD:
 * @obj: the object to test.
 *
 * Return if the given object is a valid #VisuScalarFieldMethod object.
 */
#define VISU_IS_SCALAR_FIELD_METHOD(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VISU_TYPE_SCALAR_FIELD_METHOD))
/**
 * VISU_IS_SCALAR_FIELD_METHOD_CLASS:
 * @klass: the class to test.
 *
 * Return if the given class is a valid #VisuScalarFieldMethodClass class.
 */
#define VISU_IS_SCALAR_FIELD_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), VISU_TYPE_SCALAR_FIELD_METHOD))
/**
 * VISU_SCALAR_FIELD_METHOD_GET_CLASS:
 * @obj: the widget to get the class of.
 *
 * Get the class of the given object.
 */
#define VISU_SCALAR_FIELD_METHOD_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS(obj, VISU_TYPE_SCALAR_FIELD_METHOD, VisuScalarFieldMethodClass))

/**
 * VisuScalarFieldMethod:
 *
 * An opaque structure.
 */
typedef struct _VisuScalarFieldMethod VisuScalarFieldMethod;
/**
 * VisuScalarFieldMethodClass:
 * @parent: the parent class.
 *
 * An opaque structure.
 */
typedef struct _VisuScalarFieldMethodClass VisuScalarFieldMethodClass;
struct _VisuScalarFieldMethodClass
{
  ToolFileFormatClass parent;
};

/**
 * visu_scalar_field_method_get_type
 *
 * #GType are unique numbers to identify objects.
 *
 * Returns: the #GType associated with #VisuScalarFieldMethod objects.
 */
GType visu_scalar_field_method_get_type(void);

typedef struct _VisuScalarFieldMethodData VisuScalarFieldMethodData;
/**
 * visu_scalar_field_method_data_get_type
 *
 * #GType are unique numbers to identify objects.
 *
 * Returns: the #GType associated with #VisuScalarFieldMethodData objects.
 */
GType visu_scalar_field_method_data_get_type(void);

/**
 * VisuScalarFieldMethodLoadFunc:
 * @meth: a #VisuScalarFieldMethod object ;
 * @data: the various data the load method requires.
 * @cancel: (allow-none): a #GCancellable object ;
 * @error: a location on a error pointer.
 *
 * Read the given file try to load it as a scalar field file.
 * If succeed (i.e. with none fatal errors) the method should return TRUE. If an error
 * occurs, it is stored into @error.
 *
 * If the file contains several fields, they must be loaded and added
 * to @data with visu_scalar_field_method_data_addField().
 * 
 *
 * Returns: TRUE if the read file is in a valid format (even with minor
 *          errors), FALSE otherwise.
 */
typedef gboolean (*VisuScalarFieldMethodLoadFunc)(VisuScalarFieldMethod *meth,
                                                  VisuScalarFieldMethodData *data,
                                                  GCancellable *cancel,
                                                  GError **error);

struct _VisuScalarFieldMethod
{
  ToolFileFormat parent;

  VisuScalarFieldMethodLoadFunc load;
  int priority;
};

VisuScalarFieldMethod* visu_scalar_field_method_new(const gchar* descr,
                                                    const gchar** patterns,
                                                    VisuScalarFieldMethodLoadFunc method,
                                                    int priority);

GList* visu_scalar_field_method_load(VisuScalarFieldMethod *fmt,
                                     const gchar *filename,
                                     GHashTable *options,
                                     GCancellable *cancel,
                                     GAsyncReadyCallback callback,
                                     gpointer user_data);
GList* visu_scalar_field_method_loadSync(VisuScalarFieldMethod *fmt,
                                         const gchar *filename,
                                         GHashTable *options,
                                         GCancellable *cancel,
                                         GError **error);

const gchar* visu_scalar_field_method_data_getFilename(const VisuScalarFieldMethodData *data);
void visu_scalar_field_method_data_addField(VisuScalarFieldMethodData *data,
                                            VisuScalarField *field);
void visu_scalar_field_method_data_ready(VisuScalarFieldMethodData *data);

GList* visu_scalar_field_method_getAll(void);
void visu_scalar_field_method_class_finalize(void);

#endif
