/*   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.
*/
#include "atomic_xyz.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "atomic_yaml.h"

#include <visu_dataloadable.h>
#include <visu_dataatomic.h>
#include <coreTools/toolPhysic.h>
#include <coreTools/toolFiles.h>
#include <extraFunctions/vibration.h>

/*#define TESTNEW*/

/**
 * SECTION:atomic_xyz
 * @short_description: Method to load xyz position file.
 *
 * <para>XYZ formats are plain text format to store atomic
 * positions. This format is quite simple, first line must contain the
 * number of element, then
 * the second usually store a commentary (but this is not required),
 * then all lines that are not beginning with a '#' are tried to match
 * "label x y z":. If succeed a node is added, if not, the next line
 * is read as much time as specified on first line. This scheme can be
 * repeated as much time as required to store animation for instance.</para>
 */

static VisuDataLoader *xyzLoader = NULL;

static gboolean loadXyz(VisuDataLoader *self, VisuDataLoadable *data,
                        guint type, guint nSet,
                        GCancellable *cancel, GError **error);
static int read_Xyz_File(VisuDataLoadable *data, guint iType,
                         guint nSet, GError **error);

#ifdef TESTNEW
static gboolean test_Routine(float* coords, float* dcoord, VisuElement **nodeTypes);
#endif

/******************************************************************************/
/**
 * visu_data_loader_xyz_getStatic:
 *
 * Retrieve the instance of the atomic loader used to parse XYZ files.
 *
 * Since: 3.8
 *
 * Returns: (transfer none): a #VisuDataLoader owned by V_Sim.
 **/
VisuDataLoader* visu_data_loader_xyz_getStatic(void)
{
  const gchar *typeXYZ[] = {"*.xyz", (char*)0};

  if (xyzLoader)
    return xyzLoader;

  return xyzLoader = visu_data_loader_new(_("'Element x y z' format"), typeXYZ,
                                          FALSE, loadXyz, 100);
}

static gboolean loadXyz(VisuDataLoader *self _U_, VisuDataLoadable *data,
                        guint type, guint nSet,
                        GCancellable *cancel _U_, GError **error)
{
  int res;

  g_return_val_if_fail(error && *error == (GError*)0, FALSE);

  res = read_Xyz_File(data, type, nSet, error);

  if (res < 0)
    {
      g_clear_error(error);
      /* The file is not a XYZ file. */
      return FALSE;
    }
  else if (res > 0)
    /* The file is a XYZ file but some errors occured. */
    return TRUE;
  /* Everything is OK. */
  *error = (GError*)0;
  return TRUE;
}

static gboolean readNextLine(ToolFiles *flux, gboolean mandatory,
                             GString *line, GIOStatus *status, GError **error)
{
  /*if there are commentaries */
  do
    {
      *status = tool_files_read_line_string(flux, line, NULL, error);
      if (*status != G_IO_STATUS_NORMAL)
        {
          if (*status == G_IO_STATUS_EOF)
            {
              if (*error)
                g_error_free(*error);
              *error = (GError*)0;
              return !mandatory;
            }
          return FALSE;
        };
      g_strstrip(line->str);
    }
  while (line->str[0] == '#' || line->str[0] == '!' || line->str[0] == '\0');

  return TRUE;
}

static ToolUnits readUnit(const gchar *line)
{
  ToolUnits unit;
  gchar *tmpStr;
  guint nNodes;

  unit = TOOL_UNITS_UNDEFINED;

  tmpStr = g_strdup(line);
  if (sscanf(line, "%u %s", &nNodes, tmpStr) == 2)
    unit = tool_physic_getUnitFromName(g_strstrip(tmpStr));
  DBG_fprintf(stderr, " | units for the set is '%s' -> %d.\n",
              tmpStr, unit);
  g_free(tmpStr);

  return unit;
}
static gboolean readReduced(const gchar *line)
{
  gboolean reduced;
  gchar *tmpStr;
  guint nNodes;

  reduced = FALSE;
  tmpStr = g_strdup(line);
  if (sscanf(line, "%u %s", &nNodes, tmpStr) == 2)
    reduced = (!g_ascii_strcasecmp(tmpStr, "reduced"));
  DBG_fprintf(stderr, " | coordinates are reduced %d.\n", reduced);
  g_free(tmpStr);

  return reduced;
}

static float readEnergy(const gchar *line)
{
  gchar *tmpStr;
  guint nNodes;
  float ene;

  tmpStr = g_strdup(line);
  if (sscanf(line, "%u %s %f", &nNodes, tmpStr, &ene) != 3)
    ene = G_MAXFLOAT;
  else
    ene *= 27.21138386;
  g_free(tmpStr);
  
  DBG_fprintf(stderr, " | total energy for the set is %geV.\n", ene);
  return ene;
}

static VisuBoxBoundaries readBoundary(const gchar *line, const gchar *keyword,
                                      VisuBoxBoundaries bc, gdouble box[3])
{
  gchar *kwd;
  
  kwd = strstr(line, keyword);
  if (kwd && sscanf(kwd + 8, "%lf %lf %lf",
                    box, box + 1, box + 2) == 3)
    return bc;
  return VISU_BOX_FREE;
}

static void readFree(ToolFiles *flux, GList *lst, VisuDataLoaderIter *iter, GString *line,
                     VisuElement **nodeTypes, float *coords,
                     GArray *dcoord, GArray *forces, GList *labels)
{
  GList *tmpLst;

  if (flux) g_object_unref(flux);
  if (line) g_string_free(line, TRUE);
  visu_data_loader_iter_unref(iter);
  for (tmpLst = lst; tmpLst; tmpLst = g_list_next(tmpLst))
    g_free(tmpLst->data);
  if (lst) g_list_free(lst);
  if (nodeTypes) g_free(nodeTypes);
  if (coords) g_free(coords);
  if (dcoord) g_array_free(dcoord, TRUE);
  if (forces) g_array_free(forces, TRUE);
  for (tmpLst = labels; tmpLst; tmpLst = g_list_next(tmpLst))
    {
      tmpLst = g_list_next(tmpLst);
      g_free(tmpLst->data);
    }
  if (labels) g_list_free(labels);
}

static void readCoord(const gchar *line, guint iNodes, guint nNodes,
                      float *xyz, GArray **dxyz, VisuDataLoaderIter *iter,
                      VisuElement **nodeTypes, gchar **label, GError **error)
{
  guint nbcolumn;
  float dxyz_[3];
  gchar nomloc[TOOL_MAX_LINE_LENGTH];
  VisuElement *type;
  int pos;

  *label = (gchar*)0;
  nbcolumn = sscanf(line, "%s %f %f %f %f %f %f",
                    nomloc,  xyz + 3 * iNodes + 0, xyz + 3 * iNodes + 1,
                    xyz + 3 * iNodes + 2, dxyz_ + 0, dxyz_ + 1, dxyz_ + 2);
  if (nbcolumn < 4)
    {
      DBG_fprintf(stderr, "Atomic XYZ: can't read line values.\n");
      *error = g_error_new(VISU_DATA_LOADABLE_ERROR, DATA_LOADABLE_ERROR_FORMAT,
                           _("Wrong XYZ format, 'Atom X Y Z' awaited."));
    }
  else if (((*dxyz) && nbcolumn != 7) ||
           (!(*dxyz) && iNodes > 0 && nbcolumn == 7))
    {
      DBG_fprintf(stderr, "Atomic XYZ: can't read vibration values.\n");
      *error = g_error_new(VISU_DATA_LOADABLE_ERROR, DATA_LOADABLE_ERROR_FORMAT,
                           _("Wrong XYZ + vibration format,"
                             " 'Atom X Y Z vx vy vz' awaited."));
    }
  if (nbcolumn == 7)
    {
      if (!(*dxyz))
        *dxyz = g_array_sized_new(FALSE, FALSE, sizeof(float), 3 * nNodes);
      g_array_append_vals(*dxyz, dxyz_, 3);
    }
  if (*error)
    return;

  nomloc[8] = '\0';
  type = visu_element_retrieveFromName(nomloc, (gboolean*)0);
  nodeTypes[iNodes] = type;
  visu_data_loader_iter_addNode(iter, type);

  /* Store a possible comment. */
  pos = 0;
  if (nbcolumn == 4)
    sscanf(line, "%s %f %f %f %n", nomloc, xyz + 3 * iNodes + 0,
           xyz + 3 * iNodes + 1, xyz + 3 * iNodes + 2, &pos);
  else
    sscanf(line, "%s %f %f %f %f %f %f %n",
           nomloc, xyz + 3 * iNodes + 0, xyz + 3 * iNodes + 1,
           xyz + 3 * iNodes + 2, dxyz_ + 0, dxyz_ + 1, dxyz_ + 2, &pos);
  if (line[pos] != '\0')
    {
      *label = g_strdup(line + pos + ((line[pos] == '#')?1:0));
      g_strstrip(*label);
      if ((*label)[0] == '\0')
        {
          g_free(*label);
          *label = (gchar*)0;
        }
    }
}

static void readForces(ToolFiles *flux, GString *line, guint nNodes,
                       GArray **forces, GIOStatus *status, GError **error)
{
  gfloat fxyz[3];
  guint iNodes;
  gchar nomloc[TOOL_MAX_LINE_LENGTH];
#define FORCES_TAG "forces"

  if (!g_ascii_strncasecmp(g_strchug(line->str), FORCES_TAG, sizeof(FORCES_TAG) - 1))
    {
      DBG_fprintf(stderr, "Atomic XYZ: found a forces tag.\n");
      if (forces)
        *forces = g_array_sized_new(FALSE, FALSE, sizeof(float), nNodes * 3);
      for (iNodes = 0; iNodes < nNodes && *status == G_IO_STATUS_NORMAL; iNodes++)
	{
          if (!readNextLine(flux, TRUE, line, status, error))
            {
              *error = g_error_new(VISU_DATA_LOADABLE_ERROR,
                                   DATA_LOADABLE_ERROR_FORMAT,
                                   _("Missing forces (%d read but"
                                     " %d declared).\n"), iNodes, nNodes);
              return;
            }
          if (forces && sscanf(line->str, "%s %f %f %f",
                               nomloc, fxyz + 0, fxyz + 1, fxyz + 2) != 4)
            {
              *error = g_error_new(VISU_DATA_LOADABLE_ERROR,
                                   DATA_LOADABLE_ERROR_FORMAT,
                                   _("Cannot read forces in '%s'.\n"), line->str);
              return;
            }
          if (forces)
            g_array_append_vals(*forces, fxyz, 3);
	}
      /* Eat blank or commentary lines between Sets */
      readNextLine(flux, FALSE, line, status, error);
    }
}

/******************************************************************************/
static int read_Xyz_File(VisuDataLoadable *data, guint iType,
                         guint nSet, GError **error)
{
  GIOStatus status;
  ToolFiles *flux;
  GString *line;
  guint i;
  int res, nNodes, iNodes, nNodesSet;
  guint nSets;
  float *coords;
  GArray *forces, *dcoord;
  gchar *infoUTF8;
  GList *lst, *tmpLst;
  VisuDataLoaderIter *iter;
  float qpt[3], omega, totalEnergy;
  double box[3], boxGeometry[6];
  ToolUnits unit;
  VisuElement **nodeTypes;
  guint natom;
  gchar *pt, *label;
  VisuBoxBoundaries bc;
  gboolean reduced;
  GList *nodeComments;
  VisuBox *boxObj;
  VisuVibration *vib;
  VisuNodeValuesString *labels;
  VisuNode *node;

#if DEBUG == 1
  GTimer *timer, *readTimer, *internalTimer;
  gulong fractionTimer;
  float time1, time2, time3;
#endif

  flux = tool_files_new();

  DBG_fprintf(stderr, "Atomic xyz: reading file as an xyz file.\n");
  if (!tool_files_open(flux, visu_data_loadable_getFilename(data, iType), error))
    {
      g_object_unref(flux);
      return -1;
    }

  line = g_string_new("");
  unit = TOOL_UNITS_UNDEFINED;
  reduced = FALSE;

  /* Storage of number of elements per types. */
  iter = visu_data_loader_iter_new();

  /* We read the file completely to find the number of sets of points
     and we store only the one corresponding to @nSet. */
#if DEBUG == 1
  timer = g_timer_new();
  readTimer = g_timer_new();
  internalTimer = g_timer_new();
  g_timer_start(timer);
  g_timer_start(internalTimer);
  g_timer_stop(internalTimer);
  time3 = 0.f;
#endif

  nSets        = 0;
  nNodesSet    = 0;
  nodeTypes    = (VisuElement**)0;
  coords       = (float*)0;
  dcoord       = (GArray*)0;
  forces       = (GArray*)0;
  lst          = (GList*)0;
  nodeComments = (GList*)0;
  totalEnergy  = G_MAXFLOAT;
  status = tool_files_read_line_string(flux, line, NULL, error);

  if ( status != G_IO_STATUS_NORMAL )
    {
      readFree(flux, lst, iter, line, nodeTypes, coords, dcoord, forces, nodeComments);
      return -1;
    }
 
  while( status != ( G_IO_STATUS_EOF ) )
    { 
      DBG_fprintf(stderr, "Atomic xyz: read node set number %d (%d).\n", nSets, nSet);

      /*The Number Of Nodes*/
      nNodes=0;
      DBG_fprintf(stderr, "Atomic xyz: get n atoms from '%s'.\n", line->str);
      res = sscanf(line->str, "%d", &nNodes);
      if ( res != 1 ) 
	{ 
	  *error = g_error_new(VISU_DATA_LOADABLE_ERROR, DATA_LOADABLE_ERROR_FORMAT,
			       _("Wrong XYZ format, no number of atoms on line.\n  '%s'"), line->str);
          readFree(flux, lst, iter, line, nodeTypes, coords, dcoord, forces, nodeComments);
	  return (nSets > 0)?1:-1;
	}
      DBG_fprintf(stderr, " | number of declared nodes is %d.\n", nNodes);
#if DEBUG == 1
      if (nSets == nSet)
        g_timer_start(readTimer);
      else
	g_timer_continue(internalTimer);
#endif
      if (nSets == nSet)
        {
          unit = readUnit(line->str);
          reduced = readReduced(line->str);
          totalEnergy = readEnergy(line->str);
        }

      /*The Commentary line */
      if ( tool_files_read_line_string(flux, line, NULL, error) !=
	   G_IO_STATUS_NORMAL )
	{
          readFree(flux, lst, iter, line, nodeTypes, coords, dcoord, forces, nodeComments);
	  return -2;
	}
      g_strstrip(line->str);
      DBG_fprintf(stderr, " | set the commentary to '%s'.\n", line->str);
      if (line->str[0] == '#')
	infoUTF8 = g_locale_to_utf8(line->str + 1, -1, NULL, NULL, NULL);
      else
	infoUTF8 = g_locale_to_utf8(line->str,     -1, NULL, NULL, NULL);
      if (infoUTF8)
	lst = g_list_append(lst, infoUTF8);
      else
	g_warning("Can't convert '%s' to UTF8.\n", line->str);
	
      /* The Data Lines.*/
      if (nSets == nSet)
	{
	  nNodesSet = nNodes; 
	  nodeTypes = g_malloc(sizeof(VisuElement*) * nNodes);
	  coords    = g_malloc(sizeof(float) * 3 * nNodes);
	  dcoord    = (GArray*)0;
          forces    = (GArray*)0;
	  qpt[0] = 0.f;
	  qpt[1] = 0.f;
	  qpt[2] = 0.f;
	}
      status = G_IO_STATUS_NORMAL;
      DBG_fprintf(stderr, " | read node coordinates.\n");
      for (iNodes = 0; iNodes < nNodes && status == G_IO_STATUS_NORMAL; iNodes++)
	{
          if (!readNextLine(flux, TRUE, line, &status, error))
            {
              *error = g_error_new(VISU_DATA_LOADABLE_ERROR,
                                   DATA_LOADABLE_ERROR_FORMAT,
                                   _("Missing coordinates (%d read but"
                                     " %d declared).\n"), iNodes, nNodes);
              readFree(flux, lst, iter, line, nodeTypes, coords, dcoord, forces, nodeComments);
              return 1;
            }
          
          /* if Reading the nSets, parse the data */
          if (nSets == nSet)
            {
              /* Read the coordinates. */
              readCoord(line->str, iNodes, nNodes, coords, &dcoord,
                        iter, nodeTypes, &label, error);
	      if (*error)
		{
                  readFree(flux, lst, iter, line, nodeTypes, coords, dcoord, forces, nodeComments);
		  return 1;			
		}
              if (label)
                {
                  nodeComments = g_list_prepend(nodeComments, label);
                  nodeComments = g_list_prepend(nodeComments,
                                                GINT_TO_POINTER(iNodes));
                }
	    }
#if DEBUG == 1
	  if (nSets == nSet)
	    g_timer_stop(readTimer);
	  else
	    g_timer_stop(internalTimer);
#endif
	}
#if DEBUG == 1
      g_timer_stop(timer);
#endif      
      /* Eat blank or commentary lines after coordinates. */
      if (!readNextLine(flux, FALSE, line, &status, error))
        {
          readFree(flux, lst, iter, line, nodeTypes, coords, dcoord, forces, nodeComments);
          return 1;			
        }
      /* Maybe read forces (BigDFT addition). */
      readForces(flux, line, nNodes, (nSets == nSet)?&forces:(GArray**)0, &status, error);
      if (*error)
        {
          readFree(flux, lst, iter, line, nodeTypes, coords, dcoord, forces, nodeComments);
          return 1;			
        }
      /* OK, one set of nodes have been read. */
      nSets++;
      DBG_fprintf(stderr, " | read OK %d %d.\n", status, G_IO_STATUS_EOF);
    }
  g_object_unref(flux);
  DBG_fprintf(stderr, " | finish to read the file.\n");
#if DEBUG == 1
  g_timer_stop(timer);
  time1 = g_timer_elapsed(timer, &fractionTimer)/1e-6;
  time2 = g_timer_elapsed(readTimer, &fractionTimer)/1e-6;
  time3 = g_timer_elapsed(internalTimer, &fractionTimer)/1e-6;
  g_timer_destroy(readTimer);
#endif

#if DEBUG == 1
  g_timer_start(timer);
#endif
  /* Allocate the space for the nodes. */
  natom = visu_data_loader_iter_allocate(iter, VISU_NODE_ARRAY(data));
  if (natom <= 0)
    {
      readFree(NULL, lst, iter, line, nodeTypes, coords, dcoord, forces, nodeComments);
      *error = g_error_new(VISU_DATA_LOADABLE_ERROR, DATA_LOADABLE_ERROR_FORMAT,
			   _("The file contains no atom coordinates.\n"));
      return 1;
    }
  visu_data_loader_iter_unref(iter);

  g_string_free(line, TRUE);

  /* Begin the storage into VisuData. */
  visu_data_loadable_setNSets(data, nSets);

  /* Set the commentary. */
  bc = VISU_BOX_FREE;
  for (i = 0, tmpLst = lst; i < nSets; i++, tmpLst = g_list_next(tmpLst))
    {
      /* Try to see if the commentary contains some keywords. */
      if (i == nSet)
	{
          if (bc == VISU_BOX_FREE)
            bc = readBoundary(tmpLst->data, "periodic", VISU_BOX_PERIODIC, box);
          if (bc == VISU_BOX_FREE)
            bc = readBoundary(tmpLst->data, "surface", VISU_BOX_SURFACE_ZX, box);
          DBG_fprintf(stderr, " | periodicity is %d (%g %g %g).\n",
                      bc, box[0], box[1], box[2]);
	}

      visu_data_loadable_setSetLabel(data, (const gchar*)tmpLst->data, i);
      g_free(tmpLst->data);
    }
  g_list_free(lst);
  
  boxObj = (VisuBox*)0;
  if (bc != VISU_BOX_FREE)
    {
      DBG_fprintf(stderr, "Atomic xyz: the elements are in %fx%fx%f.\n",
		  box[0], box[1], box[2]);
      boxGeometry[0] = box[0];
      boxGeometry[1] = 0.;
      boxGeometry[2] = box[1];
      boxGeometry[3] = 0.;
      boxGeometry[4] = 0.;
      boxGeometry[5] = box[2];
      boxObj = visu_box_new(boxGeometry, bc);
      visu_boxed_setBox(VISU_BOXED(data), VISU_BOXED(boxObj));
      g_object_unref(boxObj);
    }
  else
    {
      boxObj = visu_boxed_getBox(VISU_BOXED(data));
      if (boxObj)
        visu_box_setBoundary(boxObj, bc);
    }

  /* Store the coordinates */
  for(iNodes = 0; iNodes < nNodesSet; iNodes++)
    visu_data_addNodeFromElement(VISU_DATA(data), nodeTypes[iNodes],
                                 coords + 3 * iNodes, reduced);

#ifdef TESTNEW
  if ( test_Routine(coords, dcoord, nodeTypes) == FALSE )
    return -1;
#endif

  g_free(nodeTypes);
  g_free(coords);

  if (bc != VISU_BOX_PERIODIC)
    boxObj = visu_data_setTightBox(VISU_DATA(data));

  /* create the structure for phonons */
  if (dcoord)
    {
      vib = visu_data_getVibration(VISU_DATA(data), nSets);
      for (i = 0; i < nSets; i++)
	{
	  omega = 1.f;
	  pt = strstr(visu_data_getDescription(VISU_DATA(data)), "freq=");
	  if (pt)
	    sscanf(pt + 5, "%f", &omega);
	  if (omega < 0.)
	    g_warning("Negative phonon frequency (%f).", omega);
	  visu_vibration_setCharacteristic(vib, i, qpt, 0.f, omega);
	}
      visu_vibration_setDisplacements(vib, nSet, dcoord, FALSE);
      g_array_free(dcoord, TRUE);
    }

  /* Store the forces, if any. */
  if (forces)
    {
      visu_node_values_vector_set
        (visu_data_atomic_getForces(VISU_DATA_ATOMIC(data), TRUE), forces);
      g_array_free(forces, TRUE);
    }
  /* We apply the comments, if any. */
  labels = visu_data_getNodeLabels(VISU_DATA(data));
  if (nodeComments)
    {
      for (tmpLst = nodeComments; tmpLst; tmpLst = g_list_next(g_list_next(tmpLst)))
        {
          node = visu_node_array_getFromId(VISU_NODE_ARRAY(data),
                                           GPOINTER_TO_INT(tmpLst->data));
          label = (gchar*)tmpLst->next->data;
          if (label[0] == '{' && label[strlen(label) - 1] == '}')
            visu_data_loader_yaml_setNodeProp(VISU_DATA(data), node, label);
          else
            visu_node_values_string_setAt(labels, node, tmpLst->next->data);
          g_free(tmpLst->next->data);
        }
      g_list_free(nodeComments);
    }
  /* Add some other meta data. */
  if (totalEnergy != G_MAXFLOAT)
    g_object_set(G_OBJECT(data), "totalEnergy", totalEnergy, NULL);

  DBG_fprintf(stderr, "Atomic XYZ: apply the box geometry and set the unit.\n");
  visu_box_setUnit(boxObj, unit);

#if DEBUG == 1
  g_timer_stop(timer);
  fprintf(stderr, "Atomic XYZ: parse all file    in %g micro-s.\n", time1);
  fprintf(stderr, "Atomic XYZ: parse coordinates in %g micro-s.\n", time2);
  fprintf(stderr, "Atomic XYZ: header parse      in %g micro-s.\n", time3);
  fprintf(stderr, "Atomic XYZ: set all data      in %g micro-s.\n",
	  g_timer_elapsed(timer, &fractionTimer)/1e-6);
  g_timer_destroy(timer);
#endif

  return 0;
}

/******************************************************************************/
#ifdef TESTNEW
static gboolean test_Routine(float* coords, float* dcoord, VisuElement **nodeTypes) {

  float xyz[15] = {-0.440035, -0.000385, 2.123698,
    -1.765945, 0.000399, 2.377542,
    -2.249233, -0.001453, 3.679971,
    -1.338875, -0.004508, 4.739569, 
    0.024627, -0.005918, 4.466144};
  float dxyz[15] = {0.001000, -0.151000, -0.002000,
    0.001000, -0.175000, 0.000000,
    0.003000, -0.198000, 0.001000,
    0.005000, -0.183000, -0.000000,
    0.005000, -0.146000, -0.003000};
  char* waitedType[5]={ "N", "C", "C", "Co", "C"};
  int i=0, j=0;

/* Checking coordonates values and type values*/
  DBG_fprintf(stderr, "+---------------------------------------------------------------+\n");
 /* for each node : checking names and coordonates values using a difference.*/
  while( (i<15) && (strcmp(nodeTypes[j]->name,waitedType[j])==0) && (ABS(coords[i]-xyz[i])<1e-6) && (ABS(dcoord[i]-dxyz[i])<1e-6)  )
   {
    if (i%3==0) {
      DBG_fprintf(stderr, "xyz parser : expected element: %s, found: %s \n", waitedType[j], nodeTypes[j]->name);	
      DBG_fprintf(stderr, "xyz parser : expected x: %f, found: %f \t", xyz[i], coords[i]);
      DBG_fprintf(stderr, "xyz parser : expected dx: %f, found: %f \n", dxyz[i], dcoord[i]);
    }
    if (i%3==1) {
      DBG_fprintf(stderr, "xyz parser : expected y: %f, found: %f \t", xyz[i], coords[i]);
      DBG_fprintf(stderr, "xyz parser : expected dy: %f, found: %f \n", dxyz[i], dcoord[i]);
    }	
    if (i%3==2) {
      DBG_fprintf(stderr, "xyz parser : expected z: %f, found: %f \t", xyz[i], coords[i]);
      DBG_fprintf(stderr, "xyz parser : expected dz: %f, found: %f \n", dxyz[i], dcoord[i]);
      j++;
      DBG_fprintf(stderr, "+---------------------------------------------------------------+\n");
    }		
    i++;
   }

  if (i!=15)  
   {
    DBG_fprintf(stderr, "xyz parser : An error occured while reading the test file : node number %d encoutred an error \n", j+1);
    return FALSE;
   }
  else
   {
   DBG_fprintf(stderr, "xyz parser : parser ok ! \n");
    return TRUE;
   }
}
#endif
