/* This file is part of the 'atomes' software

'atomes' is free software: you can redistribute it and/or modify it under the terms
of the GNU Affero General Public License as published by the Free Software Foundation,
either version 3 of the License, or (at your option) any later version.

'atomes' is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.

You should have received a copy of the GNU Affero General Public License along with 'atomes'.
If not, see <https://www.gnu.org/licenses/>

Copyright (C) 2022-2026 by CNRS and University of Strasbourg */

/*!
* @file msdcall.c
* @short Callbacks for the MSD calculation dialog
* @author Sébastien Le Roux <sebastien.leroux@ipcms.unistra.fr>
*/

/*
* This file: 'msdcall.c'
*
* Contains:
*

 - The callbacks for the MSD calculation dialog

*
* List of functions:

  void init_msd (project * this_proj);
  void update_dynamic_view (project * this_proj, GtkTextBuffer * calc_buffer);
  void update_msd_view (project * this_proj);

  G_MODULE_EXPORT void on_calc_msd_released (GtkWidget * widg, gpointer data);

*/

#include <gtk/gtk.h>
#include <string.h>
#include <stdlib.h>

#include "global.h"
#include "bind.h"
#include "interface.h"
#include "callbacks.h"
#include "curve.h"
#include "project.h"

/*!
  \fn void init_msd (project * this_proj)

  \brief initialize the curve widgets for the MSD

  \param this_proj the target project
*/
void init_msd (project * this_proj)
{
  int i, j;
  j = 0;
  for ( i = 0 ; i < this_proj -> nspec ; i++ )
  {
    this_proj -> analysis[MSD] -> curves[j] -> name = g_strdup_printf ("%s[%s]", _("MSD"), active_chem -> label[i]);
    j=j+1;
    this_proj -> analysis[MSD] -> curves[j] -> name = g_strdup_printf ("%s(%s)[%s]", _("MSD"), _("nac"), active_chem -> label[i]);
    j=j+1;
  }
  for ( i = 0 ; i < this_proj -> nspec ; i++ )
  {
    this_proj -> analysis[MSD] -> curves[j] -> name = g_strdup_printf ("%s(x)[%s]", _("MSD"), active_chem -> label[i]);
    j=j+1;
    this_proj -> analysis[MSD] -> curves[j] -> name = g_strdup_printf ("%s(y)[%s]", _("MSD"), active_chem -> label[i]);
    j=j+1;
    this_proj -> analysis[MSD] -> curves[j] -> name = g_strdup_printf ("%s(z)[%s]", _("MSD"), active_chem -> label[i]);
    j=j+1;
    this_proj -> analysis[MSD] -> curves[j] -> name = g_strdup_printf ("%s(xy)[%s]", _("MSD"), active_chem -> label[i]);
    j=j+1;
    this_proj -> analysis[MSD] -> curves[j] -> name = g_strdup_printf ("%s(xz)[%s]", _("MSD"), active_chem -> label[i]);
    j=j+1;
    this_proj -> analysis[MSD] -> curves[j] -> name = g_strdup_printf ("%s(yz)[%s]", _("MSD"), active_chem -> label[i]);
    j=j+1;
  }
  for ( i = 0 ; i < this_proj -> nspec ; i++ )
  {
    this_proj -> analysis[MSD] -> curves[j] -> name = g_strdup_printf ("%s(x/%s)[%s]", _("MSD"), _("nac"), active_chem -> label[i]);
    j=j+1;
    this_proj -> analysis[MSD] -> curves[j] -> name = g_strdup_printf ("%s(y/%s)[%s]", _("MSD"), _("nac"), active_chem -> label[i]);
    j=j+1;
    this_proj -> analysis[MSD] -> curves[j] -> name = g_strdup_printf ("%s(z/%s)[%s]", _("MSD"), _("nac"), active_chem -> label[i]);
    j=j+1;
    this_proj -> analysis[MSD] -> curves[j] -> name = g_strdup_printf ("%s(xy/%s)[%s]", _("MSD"), _("nac"), active_chem -> label[i]);
    j=j+1;
    this_proj -> analysis[MSD] -> curves[j] -> name = g_strdup_printf ("%s(xz/%s)[%s]", _("MSD"), _("nac"), active_chem -> label[i]);
    j=j+1;
    this_proj -> analysis[MSD] -> curves[j] -> name = g_strdup_printf ("%s(yz/%s)[%s]", _("MSD"), _("nac"), active_chem -> label[i]);
    j=j+1;
  }
  this_proj -> analysis[MSD] -> curves[j] -> name = g_strdup_printf ("%s[x]", _("Correction"));
  j=j+1;
  this_proj -> analysis[MSD] -> curves[j] -> name = g_strdup_printf ("%s[y]", _("Correction"));
  j=j+1;
  this_proj -> analysis[MSD] -> curves[j] -> name = g_strdup_printf ("%s[z]", _("Correction"));
  j=j+1;
  this_proj -> analysis[MSD] -> curves[j] -> name = g_strdup_printf ("%s[x]", _("Drift"));
  j=j+1;
  this_proj -> analysis[MSD] -> curves[j] -> name = g_strdup_printf ("%s[y]", _("Drift"));
  j=j+1;
  this_proj -> analysis[MSD] -> curves[j] -> name = g_strdup_printf ("%s[z]", _("Drift"));

  add_curve_widgets (this_proj, MSD);
  this_proj -> analysis[MSD] -> init_ok = TRUE;
}

/*!
  \fn void update_dynamic_view (project * this_proj, GtkTextBuffer * calc_buffer)

  \brief print molecular dynamics information

  \param this_proj the target project
  \param calc_buffer the GtkTextBuffer to print into
*/
void update_dynamic_view (project * this_proj, GtkTextBuffer * calc_buffer)
{
  gchar * str;
  print_info (_("\t - Number of configurations: "), "bold", calc_buffer);
  str = g_strdup_printf ("%d", this_proj -> steps);
  print_info (str, "bold_blue", calc_buffer);
  g_free (str);
  print_info (_("\n\n\t - Number of time steps between each configuration: "), "bold", calc_buffer);
  str = g_strdup_printf ("%d", this_proj -> analysis[MSD] -> num_delta);
  print_info (str, "bold_blue", calc_buffer);
  g_free (str);
  print_info (_("\n\n\t - Time step δt used to integrate Newton's equations of motion: "), "bold", calc_buffer);
  str = g_strdup_printf ("%f", this_proj -> analysis[MSD] -> delta);
  print_info (str, "bold_blue", calc_buffer);
  g_free (str);
  print_info (" ", "bold", calc_buffer);
  print_info (untime[this_proj -> tunit], "bold_red", calc_buffer);
}
/*!
  \fn void update_msd_view (project * this_proj)

  \brief update the project text view for the MSD calculation

  \param this_proj the target project
*/
void update_msd_view (project * this_proj)
{
  if (this_proj -> analysis[MSD] -> calc_buffer == NULL) this_proj -> analysis[MSD] -> calc_buffer = add_buffer (NULL, NULL, NULL);
  view_buffer (this_proj -> analysis[MSD] -> calc_buffer);
  print_info (_("\n\nMean Square Displacement\n\n"), "heading", this_proj -> analysis[MSD] -> calc_buffer);
  print_info (_("Calculation details:\n\n"), NULL, this_proj -> analysis[MSD] -> calc_buffer);
  update_dynamic_view (this_proj, this_proj -> analysis[MSD] -> calc_buffer);
  print_info ("\n", NULL, this_proj -> analysis[MSD] -> calc_buffer);
  print_info (calculation_time(TRUE, this_proj -> analysis[MSD] -> calc_time), NULL, this_proj -> analysis[MSD] -> calc_buffer);
}

/*!
  \fn G_MODULE_EXPORT void on_calc_msd_released (GtkWidget * widg, gpointer data)

  \brief compute MSD

  \param widg the GtkWidget sending the signal
  \param data the associated data pointer
*/
G_MODULE_EXPORT void on_calc_msd_released (GtkWidget * widg, gpointer data)
{
  int i;
  if (! active_project -> analysis[MSD] -> init_ok) init_msd (active_project);
  clean_curves_data (MSD, 0, active_project -> analysis[MSD] -> numc);
  prepostcalc (widg, FALSE, MSD, 0, opac);
  active_project -> analysis[MSD] -> min = active_project -> analysis[MSD] -> delta*active_project -> analysis[MSD] -> num_delta;
  active_project -> analysis[MSD] -> max = (active_project -> steps - 1)*active_project -> analysis[MSD] -> delta*active_project -> analysis[MSD] -> num_delta;
  i = msd_ (& active_project -> analysis[MSD] -> delta, & active_project -> analysis[MSD] -> num_delta);
  prepostcalc (widg, TRUE, MSD, i, 1.0);
  if (! i)
  {
    show_error (_("The MSD calculation has failed"), 0, widg);
  }
  else
  {
    update_msd_view (active_project);
    show_the_widgets (curvetoolbox);
  }
  fill_tool_model ();
}
