/* This file is part of the Neper software package. */
/* Copyright (C) 2003-2014, Romain Quey. */
/* See the COPYING file in the top-level directory. */

#include"nev_data_utils_.h"

int
nev_data_string_entity_type (char *string, char *entity, char *type)
{
  int skip;
  char *stringcpy = ut_alloc_1d_char (strlen (string) + 1);

  // skipping -data if present
  if (strncmp (string, "-data", 5) == 0)
    strcpy (stringcpy, string + 5);
  else
    strcpy (stringcpy, string);

  // setting entity: must be one of:
  // for the mesh: node, elt, elset, elt1d, eltedge
  // for the tess: edge, poly
  skip = -1;
  if (strncmp (stringcpy, "node", 4) == 0)
    strcpy (entity, "node");
  else if (strncmp (stringcpy, "elt3dedge", 9) == 0)
  {
    strcpy (entity, "elt3db");
    skip = 9;
  }
  else if (strncmp (stringcpy, "elt2dedge", 9) == 0)
  {
    strcpy (entity, "elt2db");
    skip = 9;
  }
  else if (strncmp (stringcpy, "elt3d", 5) == 0)
    strcpy (entity, "elt3d");
  else if (strncmp (stringcpy, "elt2d", 5) == 0)
    strcpy (entity, "elt2d");
  else if (strncmp (stringcpy, "elt1d", 5) == 0)
    strcpy (entity, "elt1d");
  else if (strncmp (stringcpy, "elt0d", 5) == 0)
    strcpy (entity, "elt0d");
  else if (strncmp (stringcpy, "elt", 3) == 0)
    strcpy (entity, "elt");
  else if (strncmp (stringcpy, "elset3dedge", 11) == 0)
  {
    strcpy (entity, "elset3db");
    skip = 11;
  }
  else if (strncmp (stringcpy, "elset2dedge", 11) == 0)
  {
    strcpy (entity, "elset2db");
    skip = 11;
  }
  else if (strncmp (stringcpy, "elset3d", 7) == 0)
    strcpy (entity, "elset3d");
  else if (strncmp (stringcpy, "elset2d", 7) == 0)
    strcpy (entity, "elset2d");
  else if (strncmp (stringcpy, "elset1d", 7) == 0)
    strcpy (entity, "elset1d");
  else if (strncmp (stringcpy, "elset0d", 7) == 0)
    strcpy (entity, "elset0d");
  else if (strncmp (stringcpy, "elset", 5) == 0)
    strcpy (entity, "elset");
  else if (strncmp (stringcpy, "ver", 3) == 0)
    strcpy (entity, "ver");
  else if (strncmp (stringcpy, "edge", 4) == 0)
    strcpy (entity, "edge");
  else if (strncmp (stringcpy, "face", 4) == 0)
    strcpy (entity, "face");
  else if (strncmp (stringcpy, "poly", 4) == 0)
    strcpy (entity, "poly");
  else if (strncmp (stringcpy, "seed", 4) == 0)
    strcpy (entity, "seed");
  else if (strncmp (stringcpy, "cell", 4) == 0)
    strcpy (entity, "cell");
  else if (strncmp (stringcpy, "rptedge", 7) == 0)
    strcpy (entity, "rptedge");
  else if (strncmp (stringcpy, "rpt", 3) == 0)
    strcpy (entity, "rpt");
  else if (strncmp (stringcpy, "csys", 4) == 0)
    strcpy (entity, "csys");
  else if (strncmp (stringcpy, "point", 5) == 0)
    strcpy (entity, "point");
  else
  {
    ut_print_message (2, 0, "option -data*: entity not supported");
    abort ();
  }

  // setting the type of data
  if (skip == -1)
    skip = strlen (entity);
  strcpy (type, stringcpy + skip);

  // fixing stuff
  if (strncmp (type, "colourscheme", 12) == 0
      || strncmp (type, "colorscheme", 11) == 0)
    sprintf (type, "colscheme");

  ut_free_1d_char (stringcpy);

  return 0;
}

int
nev_data_type_size (char *type, int *psize)
{
  int status = 0;
  if (strcmp (type, "scal") == 0
      || strcmp (type, "int") == 0
      || strcmp (type, "rad") == 0
      || strcmp (type, "edgerad") == 0 || strcmp (type, "real") == 0)
    (*psize) = 1;
  else if (strncmp (type, "ori", 3) == 0
	   || strcmp (type, "edgecol") == 0
	   || strcmp (type, "col") == 0
	   || strcmp (type, "coo") == 0)
    (*psize) = 3;
  else if (strcmp (type, "cube"))
    (*psize) = 10;
  else if (strcmp (type, "cyl"))
    (*psize) = 5;
  else if (strcmp (type, "ell"))
    (*psize) = 12;
  else if (strncmp (type, "int", 3) == 0 || strncmp (type, "real", 4) == 0)
    sscanf (type + 4, "%d", psize);
  else
    status = -1;

  return status;
}

void
nev_data_id_colour (double **data, int s1, int **Col)
{
  int i, j;
  int** palette = NULL;
  int palettesize, pos;
  ut_color_palette_0208 (&palette, &palettesize);

  for (i = 1; i <= s1; i++)
  {
    pos = ut_num_d2ri (data[i][0] - 1) % palettesize;
    if (pos >= 0)
      for (j = 0; j < 3; j++)
	Col[i][j] = palette[pos][j];
    else
      ut_array_1d_int_zero (Col[i], 3);
  }

  ut_free_2d_int (palette, palettesize);

  return;
}

void
nev_data_col_colour (double **data, int s1, int **Col)
{
  int i, j;

  for (i = 1; i <= s1; i++)
    for (j = 0; j < 3; j++)
      Col[i][j] = ut_num_d2ri (data[i][j]);

  return;
}

void
nev_data_tr_tr (double **data, int s1, double *trs)
{
  int i;

  for (i = 1; i <= s1; i++)
    trs[i] = data[i][0];

  return;
}

void
nev_data_rad_radius (double **data, int s1, double *Rad)
{
  int i;

  for (i = 1; i <= s1; i++)
    Rad[i] = data[i][0];

  return;
}

void
nev_data_ori_colour (double **data, int s1, char *scheme, int **Col)
{
  int i, j;
  double *R = ol_R_alloc ();

  if (scheme == NULL || !strcmp (scheme, "R"))
    for (i = 1; i <= s1; i++)
    {
      ol_q_R (data[i], R);
      ol_R_Rcrysym (R, "cubic", R);
      for (j = 0; j < 3; j++)
	Col[i][j] = ut_num_d2ri (255 * (R[j] + (OL_S2 - 1))
				 / (2 * (OL_S2 - 1)));
    }
  else
    ut_error_reportbug ();

  ol_R_free (R);

  return;
}

void
nev_data_scal_colour (double **data, int s1, char *scale,
		      char *scheme, int **Col, char** pscale)
{
  int i;
  double ScaleBeg, ScaleEnd;
  double datamin, datamax;
  char** parts = NULL;
  int qty;
  char *min = NULL, *max = NULL;
  char* tmp = ut_alloc_1d_char (1000);

  qty = 0;
  if (scale)
    ut_string_separate (scale, NEUT_SEP_DEP, &parts, &qty);

  if (qty >= 2)
  {
    ut_string_string (parts[0], &min);
    ut_string_string (parts[qty - 1], &max);
  }

  datamin = ut_array_2d_col_min (data + 1, 0, s1);
  datamax = ut_array_2d_col_max (data + 1, 0, s1);

  if (min == NULL || strlen (min) == 0 || !strcmp (min, "min"))
    ScaleBeg = datamin;
  else
    ut_string_real (min, &ScaleBeg);

  if (max == NULL || strlen (max) == 0 || !strcmp (max, "max"))
    ScaleEnd = datamax;
  else
    ut_string_real (max, &ScaleEnd);

  if (ut_num_min (ScaleBeg, ScaleEnd) > datamin)
    ut_print_message (1, 2,
		      "Scale minimum (%f) larger  than data minimum (%f)\n",
		      ut_num_min (ScaleBeg, ScaleEnd), datamin);

  if (ut_num_max (ScaleBeg, ScaleEnd) < datamax)
    ut_print_message (1, 2,
		      "Scale maximum (%f) smaller than data maximum (%f)\n",
		      ut_num_max (ScaleBeg, ScaleEnd), datamax);

  if (scheme == NULL)
    for (i = 1; i <= s1; i++)
      ut_color_scheme_val_color ("blue,cyan,yellow,red",
				 ScaleBeg, ScaleEnd, data[i][0], Col[i]);
  else
    for (i = 1; i <= s1; i++)
      ut_color_scheme_val_color (scheme, ScaleBeg, ScaleEnd, data[i][0],
				 Col[i]);

  if (pscale)
  {
    (*pscale) = ut_alloc_1d_char (1000);
    {
      sprintf (*pscale, "%.12g", ScaleBeg);
      for (i = 1; i < qty - 1; i++)
      {
	(*pscale) = strcat (*pscale, NEUT_SEP_DEP);
	(*pscale) = strcat (*pscale, parts[i]);
      }

      sprintf (tmp, "%.12g", ScaleEnd);
      (*pscale) = strcat (*pscale, NEUT_SEP_DEP);
      (*pscale) = strcat (*pscale, tmp);
    }

    (*pscale) = ut_realloc_1d_char (*pscale, strlen (*pscale) + 1);
  }

  ut_free_2d_char (parts, qty);
  ut_free_1d_char (min);
  ut_free_1d_char (max);
  ut_free_1d_char (tmp);

  return;
}

void
nev_data_coo_coo (double **ref, double **data, double fact, int s1,
		  double **coo)
{
  int i, j;

  for (i = 1; i <= s1; i++)
    for (j = 0; j < 3; j++)
      coo[i][j] = ref[i][j] + fact * (data[i][j] - ref[i][j]);

  return;
}

void
nev_data_disp_coo (double **ref, double **data, double fact, int s1,
		   double **coo)
{
  int i, j;

  for (i = 1; i <= s1; i++)
    for (j = 0; j < 3; j++)
      coo[i][j] = ref[i][j] + fact * data[i][j];

  return;
}

void
nev_data_typearg_args (char* input, char *argument, char *type,
                       char* value, char *mod)
{
  char **args = NULL;
  int argqty;

  ut_string_separate (argument, NEUT_SEP_DEP, &args, &argqty);

  if (argqty == 1 && !strcmp (argument, "ori"))
  {
    strcpy (type, "ori");
    strcpy (value, "");
  }
  else if (argqty == 1 && !strcmp (argument, "id"))
  {
    strcpy (type, "id");
    strcpy (value, "");
  }
  else if (argqty == 1)
  {
    strcpy (type, input);
    strcpy (value, args[0]);
  }
  else if (argqty == 2)
  {
    strcpy (type, args[0]);
    strcpy (value, args[1]);
  }
  else if (argqty == 3)
  {
    strcpy (type, args[0]);
    strcpy (value, args[1]);
    strcpy (mod, args[2]);
  }

  ut_free_2d_char (args, argqty);

  if (!strcmp (type, "col"))
    return;
  else if (!strcmp (type, "e")
	   || !strcmp (type, "ek")
	   || !strcmp (type, "er")
	   || !strcmp (type, "R")
	   || !strcmp (type, "q")
	   || !strcmp (type, "m")
	   || !strcmp (type, "rtheta") || !strcmp (type, "g"))
  {
    char *tmpc = ut_alloc_1d_char (100);
    tmpc = ut_string_paste ("ori", type);
    strcpy (type, tmpc);
    ut_free_1d_char (tmpc);
  }
  else if (!strncmp (type, "ori", 3))
    strcpy (type, "ori");
  // else
  // ut_error_reportbug ();

  if (!strcmp (type, "ori") && strlen (value) > 0)
    strcpy (type, "orie");

  return;
}
