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

#include "visu_tools.h"

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

char *argFileName;

char *argSpinFileName;
int spinHidingMode;

char *argExportFileName;

gchar *argColorizeFileName;
int argColorizeColUsed[3];
int argColorizePresetColor;
gboolean argColorizeColUsed_isPresent;

gboolean argTranslationsIsSet;
float argTranslations[3];

gchar* argPlanesFileName;

int withGtk;

int xWindowWidth, xWindowHeight;

void printInfoMessage()
{
  fprintf(stdout, _("V_Sim is a software to visualize atomic structures with"
		    " OpenGl rendering.\n\n"));
  fprintf(stdout, _("usage: v_sim [-h|-e file|-g size|-c file|-s file|-m|-t xyz|-u lmn|-p file] [fileToRender]\n"));
  fprintf(stdout, _("-h, --help             show this little help.\n"));
  fprintf(stdout, _("-e, --export file      made an image from the fileToRender\n"));
  fprintf(stdout, _("                       argument. The format is specified through\n"));
  fprintf(stdout, _("                       the extension of the file parameter.\n"));
  fprintf(stdout, _("-g, --geometry size    specify the size of the rendering window,\n"));
  fprintf(stdout, _("                       the size parameter must have the following\n"));
  fprintf(stdout, _("                       format : <width>x<height> with positive non\n"));
  fprintf(stdout, _("                       null values.\n"));
  fprintf(stdout, _("-c, --colorize file    the argument fileToRender must be called,\n"));
  fprintf(stdout, _("                       then the given file of the option is used to\n"));
  fprintf(stdout, _("                       colorize the elements.\n"));
  fprintf(stdout, _("-u, --use-column l:m:n must be used with the '--colorize' option,\n"));
  fprintf(stdout, _("                       it specifies the columns to use from the data\n"));
  fprintf(stdout, _("                       file for the three colour channels [l;m;n].\n"));
  fprintf(stdout, _("                       Columns are counted from 1 and set 0 to use\n"));
  fprintf(stdout, _("                       the constant 1.\n"));
  fprintf(stdout, _("-d, --color-preset id  this option must be used with the 'colorize' one\n"));
  fprintf(stdout, _("                       and a valid file parameter. It chooses a preset\n"));
  fprintf(stdout, _("                       color scheme. The id parameter is an integer\n"));
  fprintf(stdout, _("                       that corresponds to a defined color shade.\n"));
  fprintf(stdout, _("-p, --planes file      the argument fileToRender must be called,\n"));
  fprintf(stdout, _("                       then the given file of the option is parsed\n"));
  fprintf(stdout, _("                       as a list of planes and they are rendered.\n"));
  fprintf(stdout, _("-t, --translate x:y:z  a file must be loaded. It applies the given\n"));
  fprintf(stdout, _("                       translations to the loaded file. The units are\n"));
  fprintf(stdout, _("                       those of the file.\n"));
  fprintf(stdout, _("-s, --spin-file file   use the given file as a spin indicator. If this\n"));
  fprintf(stdout, _("                       option is used, V_Sim switches automatically to\n"));
  fprintf(stdout, _("                       spin rendering whatever method is specified in\n"));
  fprintf(stdout, _("                       the parameter file.\n"));
  fprintf(stdout, _("-m, --hiding-mode      when loading a spin file, hides element containing\n"));
  fprintf(stdout, _("                       null module values.\n"));
}

int parseCommandLine(int argc, char **argv)
{
  struct option long_options[] = {
    {"export", 1, 0, 'e'}, /* export : name, 1 : arg required */
    {"help", 0, 0, 'h'}, /* help : name, 0 : arg not required */
    {"geometry", 1, 0, 'g'}, /* geometry : name, 0 : arg not required */
    {"spin-file", 1, 0, 's'},
    {"hiding-mode", 0, 0, 'm'},
    {"colorize", 1, 0, 'c'}, /* colorize : name, 1 : arg required */
    {"use-column", 1, 0, 'u'}, /* use-column : name, 1 : arg required */
    {"color-preset", 1, 0, 'd'},
    {"translate", 1, 0, 't'}, /* translate : name, 1 : arg required */
    {"planes", 1, 0, 'p'}, /* planes : name, 1 : arg required */
    {0, 0, 0, 0}
  };
  int res, i;
  int option_index;

  /* We want to read . as floating point separator : in french it is , */
  setlocale(LC_NUMERIC, "C");

  argFileName = (char*)0;
  argSpinFileName = (char *)0;
  spinHidingMode = 0;
  argExportFileName = (char*)0;
  argColorizeFileName = (gchar*)0;
  for (i = 0; i < 2; i++)
    argColorizeColUsed[i] = 0;
  argColorizeColUsed_isPresent = FALSE;
  argColorizePresetColor = -1;
  argTranslationsIsSet = FALSE;
  xWindowWidth = 600;
  xWindowHeight = 600;
  argPlanesFileName = (gchar*)0;

  withGtk = 1;

  option_index = 0;
  while (1)
    {
      res = getopt_long (argc, argv, "e:hg:s:mc:u:d:t:p:",
			 long_options, &option_index);

      /* test if there's no more option available. */
      if (res == -1)
	break;

      switch (res)
	{
	case 'e':
	  DBG_fprintf(stderr, "Visu Command : option '%s' found with arg '%s'.\n",
		      long_options[option_index].name, optarg);
	  if (!optarg)
	    g_error("The option 'export' needs a parameter.\n");
	  else
	    {
	      argExportFileName = malloc(sizeof(char) * (strlen(optarg) + 1));
	      if (!argExportFileName)
		{
		  allocationProblems();
		  exit(1);
		}
	      strcpy(argExportFileName, optarg);
	    }
	  /* This option does not need gtk. */
	  withGtk = 0;
	  break;
	case 'h':
	  DBG_fprintf(stderr, "Visu Command : option '%s' found.\n",
		      long_options[option_index].name);
	  printInfoMessage();
	  exit(0);
	  break;
	case 'g':
	  DBG_fprintf(stderr, "Visu Command : set the geometry of the X window (%s).\n", optarg);
	  res = sscanf(optarg, "%dx%d", &xWindowWidth, &xWindowHeight);
	  if (res != 2 || xWindowWidth <= 0 || xWindowHeight <=0)
	    {
	      g_warning("Wrong format for geometry"
			" option (<width>x<height> awaited).\n");
	      xWindowWidth = 600;
	      xWindowHeight = 600;
	      break;
	    }
	  break;
	case 's':
	  DBG_fprintf(stderr, "Visu Command : set the filenane for"
		      " spin rendering to '%s'.\n", optarg);
	  if (!optarg)
	    g_error("The option 'spin-file' needs a parameter.\n");
	  argSpinFileName = g_strdup(optarg);
	  break;
	case 'm':
	  DBG_fprintf(stderr, "Visu Command : set hiding-mode to TRUE in spin rendering.\n");
	  spinHidingMode = 1;
	  break;
	case 'c':
	  DBG_fprintf(stderr, "Visu Command : set the filenane for colorization to '%s'.\n", optarg);
	  if (!optarg)
	    g_error("The option 'colorize' needs a parameter.\n");
	  argColorizeFileName = g_strdup(optarg);
	  break;
	case 'u':
	  DBG_fprintf(stderr, "Visu Command : set the used columns for"
		      " colorize data (%s).\n", optarg);
	  res = sscanf(optarg, "%d:%d:%d", argColorizeColUsed,
		       argColorizeColUsed + 1, argColorizeColUsed + 2);
	  if (res != 3 || argColorizeColUsed[0] < 0 ||
	      argColorizeColUsed[1] < 0 || argColorizeColUsed[2] < 0)
	    {
	      g_warning("Wrong format for use-column"
			" option (<channel-1>:<channel-2>:<channel-3> awaited).\n");
	      for (i = 0; i < 2; i++)
		argColorizeColUsed[i] = 0;
	      break;
	    }
	  argColorizeColUsed_isPresent = TRUE;
	  break;
	case 'd':
	  DBG_fprintf(stderr, "Visu Command : set a previously defined color scheme (%s).\n", optarg);
	  res = sscanf(optarg, "%d", &argColorizePresetColor);
	  if (res != 1 || argColorizePresetColor < 0)
	    {
	      g_warning("Wrong format for color-preset"
			" option (positive integer awaited).\n");
	      argColorizePresetColor = -1;
	      break;
	    }
	  break;
	case 't':
	  DBG_fprintf(stderr, "Visu Command : set the translations (%s).\n", optarg);
	  res = sscanf(optarg, "%f:%f:%f", argTranslations,
		       argTranslations + 1, argTranslations + 2);
	  if (res != 3)
	    {
	      g_warning("Wrong format for translation"
			" option (<x>:<y>:<z> awaited).\n");
	      break;
	    }
	  else
	    argTranslationsIsSet = TRUE;
	  break;
	case 'p':
	  DBG_fprintf(stderr, "Visu Command : set the filenane for planes to '%s'.\n", optarg);
	  if (!optarg)
	    g_error("The option 'planes' needs a parameter.\n");
	  argPlanesFileName = g_strdup(optarg);
	  break;
	default:
	  g_warning("Unknown option.\n");
	  printInfoMessage();
	  exit(0);
	}
    }

  if (argc - optind == 1)
    {
      DBG_fprintf(stderr, "Visu Command : there is one argument '%s'.\n", argv[optind]);
      argFileName = g_strdup(argv[optind]);
    }
  else if (argc - optind == 0)
    return 0;
  else
    g_warning("This program allows only up to one argument.\n");

  return 0;
}

char* commandLineGet_ArgFilename()
{
  return argFileName;
}

char* commandLineGet_ArgSpinFileName()
{
  return argSpinFileName;
}

int commandLineGet_WithGtk()
{
  return withGtk;
}

char* commandLineGet_ExportFileName()
{
  return argExportFileName;
}

void commandLineGet_XWindowGeometry(int *width, int *height)
{
  *width = xWindowWidth;
  *height = xWindowHeight;
}
gchar* commandLineGet_colorizeFileName()
{
  return argColorizeFileName;
}
int* commandLineGet_colorizeColUsed()
{
  if (argColorizeColUsed_isPresent)
    return argColorizeColUsed;
  else
    return (int*)0;
}
float* commandLineGet_translation()
{
  if (argTranslationsIsSet)
    return argTranslations;
  else
    return (float*)0;
}
int commandLineGet_colorizePresetColor()
{
  return argColorizePresetColor;
}
gchar* commandLineGet_planesFileName()
{
  return argPlanesFileName;
}
int commandLineGet_spinHidingMode()
{
  return spinHidingMode;
}
