/*
 * Copyright University of Reims Champagne-Ardenne
 * Authors and Contributors: Akilan RAJAMANI, Corentin LEFEBVRE, Johanna KLEIN,
 *                           Emmanuel PLUOT, Gaetan RUBEZ, Hassan KHARTABIL,
 *                           Jean-Charles BOISSON and Eric HENON
 * (24/07/2017)
 * jean-charles.boisson@univ-reims.fr, eric.henon@univ-reims.fr
 *
 * This software is a computer program whose purpose is to
 * detect and quantify interactions from electron density
 * obtained either internally from promolecular density or
 * calculated from an input wave function input file. It also
 * prepares for the visualization of isosurfaces representing
 * several descriptors (dg) coming from the IGM methodology.
 *
 * This software is governed by the CeCILL-C 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-C
 * license as circulated by CEA, CNRS and INRIA at the following URL
 * "http://www.cecill.info".
 *
 * As a counterpart to the access to the source code and  rights to copy,
 * modify and redistribute granted by the license, users are provided only
 * with a limited warranty  and the software's author,  the holder of the
 * economic rights,  and the successive licensors  have only  limited
 * liability.
 *
 * In this respect, the user's attention is drawn to the risks associated
 * with loading,  using,  modifying and/or developing or reproducing the
 * software by the user in light of its specific status of free software,
 * that may mean  that it is complicated to manipulate,  and  that  also
 * therefore means  that it is reserved for developers  and  experienced
 * professionals having in-depth computer knowledge. Users are therefore
 * encouraged to load and test the software's suitability as regards their
 * requirements in conditions enabling the security of their systems and/or
 * data to be ensured and,  more generally, to use and operate it in the
 * same conditions as regards security.
 *
 * The fact that you are presently reading this means that you have had
 * knowledge of the CeCILL-C license and that you accept its terms.
 *
 * */

/**
 * @file output.h
 * @brief Files writing functions.
 * @author Gaetan & Emmanuel */

#ifndef _OUTPUT_H_
#define _OUTPUT_H_

/*
#ifdef WINDOWS
    #include<direct.h>
    #include<windows.h>
    //! The getcwd according to the OS
    #define getDir _getcwd
#else
    #include<unistd.h>
    //! The getcwd according to the OS
    #define getDir getcwd
    #endif*/

// LOCAL
//#include <ProgData.h>
#include <reader.h>
//#include <Results.h>
#include <vmdFileGenerator.h>

//! The cubes' names
const std::string CUBE_NAMES [] =
  {
    "dgIntra",
    "dgInter",
    "dkIntra",
    "dkInter"
  };


//! The VMD script's intern keywords
const std::string KEYWORDS [] =
  {
    "XX_DGINTER_XX",				/**< Path to Delta G inter cube file	*/
    "XX_DGINTRA_XX",				/**< Path to Delta G intra cube file	*/
    "XX_DENS_XX",					/**< Path to rho cube file 				*/
    "XX_RDG_XX",                                    /**< Path to RDG cube file  */
    "XX_PERCENT_XX",				/**< Path to percent data file	 		*/
    "XX_COMPLEX_XX",				/**< Path to the complex file created	*/
    "XX_CUTPLOT1_XX",				/**< cutplot[0] value					*/
    "XX_CUTPLOT2_XX",				/**< cutplot[1] value					*/
    "XX_CUTPLOTIGM1_XX",                            /**< cutplotIGM[0] value                                */
    "XX_CUTPLOTIGM2_XX",                            /**< cutplotIGM[1] value                                */
    "XX_VMDCOLRANGIGM1_XX",                         /**< vmdcolrangIGM[0] value                                */
    "XX_VMDCOLRANGIGM2_XX",                         /**< vmdcolrangIGM[1] value                                */
    "XX_CUTOFFS1_XX",				/**< cutoffs[0] value					*/
    "XX_CUTOFFS2_XX",				/**< cutoffs[1] value					*/
    "XX_FRAG1Def_XX",                           /** Fragment 1 definition   */
    "XX_FRAG2Def_XX",                           /** Fragment 2 definition   */
//  "XX_FIRST_PROT_INDEX_XX",		/**< Index of first atom of molecule B	*/
//  "XX_LAST_COMPLEX_INDEX_XX",		/**< Index of last atom of all complex	*/
//  "XX_LAST_LIG_INDEX_XX",			/**< Index of last atom in molecule A	*/
    "XX_MAX_PERCENT_XX"				/**< Maximum percentage found 			*/
  };


//! TO DOCUMENT
const int SCRIPT_NAMES_LENGTH = 3;

//! The VMD script's type names
const std::string SCRIPT_NAMES [] =
  { /** add extension .tvmd on disk */
    "atContr",
    "nci",
    "igm"
  };

/**
 * @fn void outCube(int cubeType, param_t * params, ProgData * data, double * cubeRho, double * cube)
 * @brief Writes down the given cube and some parameters to help interprete it
 * @param cubeType : the type of the cube
 * @param params : the parameters read at the beginning of the program
 * @param data : the data received at the beginning of the program
 * @param cubeRho : the cubeRho processed during the program
 * @param cube : the cube itself */
void outCube(int cubeType, param_t * params, ProgData * data, double * cubeRho, double * cube);

/**
 * @fn void writeCube(param_t * params, ProgData * data, const char* cubeFileName, double *** rho, double *** cube, const bool usingThreshold=false, const double lowerlimit=0.0, const double upperlimit=0.0, const double defaultValue=0.0)
 * @brief Writes down the given cube and some parameters to help interpreting it
 * @param params the parameters read at the beginning of the program
 * @param data the data received at the beginning of the program
 * @param cubeFileName Specific part of the file name that will contain the cube values (to identify it ). Convention is : params->outputName + "-" + cubeFileName  + ".cube"
 * @param rho the rho values processed during the program
 * @param cube the cube to write itself
 * @param usingThreshold if no need of using threshold, everything is written
 * @param lowerlimit the lower limit of the ED range that allows (or not) writing the cube information
 * @param upperlimit the upper limit of the ED range that allows (or not) writing the cube information
 * @param defaultValue the value if the ED value is out of the [lowerlimit:upperlimit] range
*/
void writeCube(param_t * params, ProgData * data, const char* cubeFileName, double *** rho, double *** cube,  const bool usingThreshold=false, const double lowerlimit=0.0, const double upperlimit=0.0, const double defaultValue=0.0);

/**
 * @fn void outCubeRDG(param_t * params, ProgData * data, double * cube, double * rho, bool * shouldPrint)
 * @brief Writes down the given RDG cube and some parameters to help interpreting it
 * @param params the parameters read at the beginning of the program
 * @param data the data received at the beginning of the program
 * @param cube the cube itself
 * @param rho the density values
 * @param shouldPrint TO DOCUMENT */
void outCubeRDG(param_t * params, ProgData * data, double * cube, double * rho, bool * shouldPrint);

/**
 * @fn void outCubeRho(param_t * params, ProgData * data, double * cube)
 * @brief Writes down the given Rho cube and some parameters to help interpreting it
 * @param params the parameters read at the beginning of the program
 * @param data the data received at the beginning of the program
 * @param cube the cube itself */
void outCubeRho(param_t * params, ProgData * data, double * cube);

/**
 * @fn void outDat(param_t * params, ProgData * data, Results&	results)
 * @brief Writes down the given Rho and RDG cubes
 * @param params the parameters read at the beginning of the program
 * @param data the data received at the beginning of the program
 * @param results the process results */
void outDat(param_t * params, ProgData * data, Results&	results);

/**
 * @fn void outPercent(param_t * params, Results &results, ProgData * data)    
 * @brief Writes down the percentage participation for each atom to the INTER interactions
 * @param params the parameters read at the beginning of the program
 * @param results the results' values, including delta values
 * @param the program's data */
void outPercent(param_t * params, Results &results, ProgData * data);

/**
 * @fn void outPercentQM(param_t params, ProgData *data, double *dgInterAtSum, double dv, unsigned int nbAtoms)
 * @brief Writes down the percentage participation for each atom to the INTER interactions
 * @param params the parameters read at the beginning of the program
 * @param data:  to get atom names
 * @param dgInterAtSum the atomic contribution values 
 * @param dv the elementary volume in the grid 
 * @param data ms the number of atoms in the system */
void outPercentQM(param_t params, ProgData *data, double *dgInterAtSum, double dv, unsigned int nbAtoms); // WFX/N mode



/**
 * @fn void outVMD(param_t * params, ProgData * data, double max, double deltagIntraMaximumValue, double deltagInterMaximumValue, double dgAtWeakMaxValue)
 * @brief Writes down the VM script for visualisation
 * @param params the parameters read at the beginning of the program
 * @param data the program's data
 * @param max the maximum percent found
 * @param deltagIntraMaximumValue The maximum value found in deltagIntra interaction (useful for VMD files) 
 * @param deltagInterMaximumValue The maximum value found in deltagInter interaction (useful for VMD files) 
 * @param dgAtWeakMaxValue The maximum value of the set of atomic contributions to weak interactions */
void outVMD(param_t * params, ProgData * data, double max, double deltagIntraMaximumValue, double deltagInterMaximumValue, double dgAtWeakMaxValue);

/**
 * @fn void writeVMDfiles(param_t * params, ProgData * data, const double deltagIntraMaximumValue=0.08, const double deltagInterMaximumValue=0.01, double dgAtWeakMaxValue, std::vector<criticalpoint>  cpList, double max, double selfmaxrange)
 * @brief Writes down the VM script for visualisation (quantum version)
 * @warning only use for Quantum computation but will be generic at the end
 * @param params the parameters read at the beginning of the program
 * @param data the program's data
 * @param deltagIntraMaximumValue The maximum value found in deltagIntra interaction (useful for VMD files) 
 * @param deltagInterMaximumValue The maximum value found in deltagInter interaction (useful for VMD files) 
 * @param dgAtWeakMaxValue The maximum value of the set of atomic contributions to weak interactions 
 * @param cpList The list of found critical points 
 * @param max the maximum value within the atomic contrib to the INTER interactions 
 * @param selfmaxrange the maximum SELF value to color dg/rho with SELF */
void writeVMDfiles(param_t * params, ProgData * data, double deltagIntraMaximumValue=0.08, 
                   double deltagInterMaximumValue=0.01, double dgAtWeakMaxValue=0.05,
                   std::vector<criticalpoint>  cpList = std::vector<criticalpoint>(), double max=0.0, double selfmaxrange=0.0);

/**
 * @fn string getWorkPath()
 * @brief returns a string with the current working path
 * @return the current path of the execution */
std::string getWorkPath();

/**
 * @fn writeXYZ(param_t &params, ProgData *data, unsigned int nbAtoms, positions_t &atomCoordinates)
 * @brief write xyz atom coordinates using the xyz file format
 * @param params : input --> to retrieve the output filename
 * @param data   : pointer to a structure containing data like getNbSteps0 ...
 * @param nbAtoms : input --> number of atom of the system to be printed
 * @param atomCoordinates : input --> structure containing information about positions of the atoms (xyz) */
void writeXYZ(param_t &params, ProgData *data, unsigned int nbAtoms, positions_t &atomCoordinates);

/**
 * @fn writeCPTXT(param_t &params, std::vector<criticalpoint>  cpList)               
 * @brief write the cp.txt output file after a critical point analysis
 * @param params : input --> to retrieve the output filename
 * @param cpList : input --> structure containing all information about found critical points */
void writeCPTXT(param_t &params, std::vector<criticalpoint>  cpList);


/**
 * @fn writeAtomDOI(param_t params, ProgData *data, double *dgAtSum, double *dgAtSumW, double *dgAtSumW2, double dv, unsigned int nbAtoms)
 * @brief write Atom Degree of Interaction find within the atomi IGM framework
 * @param params : input --> to retrieve the output filename
 * @param data   : pointer to a structure containing data like getNbSteps0 ...
 * @param dgAtSum, dgAtSumW, dgAtSumW2 : input --> atomic scorings
 * @param dv: input --> elementary integration volume 
 * @param nbAtoms: the number of atoms in the system  */
void writeAtomDOI(param_t params, ProgData *data, double *dgAtSum, double *dgAtSumW, 
                  double *dgAtSumW2, double dvi, unsigned int nbAtoms);

/**
 * @fn writeSelfAtomDat(param_t params, ProgData *data, double *pauliAT,unsigned int nbAtoms)
 * @brief write Atom contributions to the Pauli repulsion between two fragments (SELF analysis)
 * @param params : input --> to retrieve the output filename
 * @param data   : pointer to a structure containing data like getNbSteps0 ...
 * @param pauliAT : input --> atomic scorings
 * @param nbAtoms: the number of atoms in the system  */
void writeSelfAtomDat(param_t params, ProgData *data, double *pauliAT,unsigned int nbAtoms);

#endif 



