/*
 * 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 reader.h
 * @brief Tool functions for reading input data.
 * @author Gaetan & Emmanuel */

#ifndef _READER_H_
#define _READER_H_

// LOCAL
//#include <ProgData.h>
#include <Results.h>
#include <WFreader.h>

// JC IBSI
// Already included by Results.h
//#include <vector>

//! The atoms' types
typedef enum ATOM_TYPES
  {
    HYDROGEN, HELIUM, LITHIUM, BERYLLIUM, BORON, CARBON, NITROGEN, OXYGEN, FLUORINE, NEON, SODIUM, MAGNESIUM, ALUMINIUM, SILICON, PHOSPHORUS, SULFUR, CHLORINE, ARGON, POTASSIUM, CALCIUM, SCANDIUM,
    TITANIUM, VANADIUM, CHROMIUM, MANGANESE, IRON, COBALT, NICKEL, COPPER, ZINC, GALLIUM, GERMANIUM, ARSENIC, SELENIUM, BROMINE, KRYPTON, RUBIDIUM, STRONTIUM, YTTRIUM, ZIRCONIUM, NIOBIUM, MOLYBDENUM,
    TECHNETIUM, RUTHENIUM, RHODIUM, PALLADIUM, SILVER, CADMIUM, INDIUM, TIN, ANTIMONY, TELLURIUM, IODINE, XENON, CESIUM, BARIUM, LANTHANUM, CERIUM, PRASEODYMIUM, NEODYMIUM, PROMETHIUM, SAMARIUM, EUROPIUM, GADOLINIUM, TERBIUM, DYSPROSIUM, HOLMIUM, ERBIUM, THULIUM, YTTERBIUM, LUTETIUM, 
    HAFNIUM, TANTALUM, TUNGSTEN, RHENIUM, OSMIUM, IRIDIUM, PLATINIUM, GOLD, MERCURY, THALLIUM, LEAD, BISMUTH, POLONIUM, ASTATINE, RADON, FRANCIUM, RADIUM,
ACTINIUM, THORIUM, PROTACTINIUM, URANIUM, NEPTUNIUM, PLUTONIUM, AMERICIUM, CURIUM, BERKELIUM, CALIFORNIUM, EINSTEINIUM, FERMIUM, MENDELEVIUM, NOVELIUM, LAWRENCIUM, SIZE_ATOM
  }atom_types_t;

//! The atoms' names
// modif Eric : 20/04/2019: atom name list in the range [0:SIZE_ATOM-1]
const std::string ATOM_NAMES [] =
  {
    "H","He","Li","Be","B","C","N","O","F","Ne","Na","Mg","Al","Si","P","S","Cl","Ar","K","Ca","Sc","Ti","V","Cr","Mn","Fe","Co","Ni","Cu","Zn","Ga","Ge","As","Se","Br","Kr","Rb","Sr", "Y","Zr","Nb","Mo","Tc", "Ru","Rh","Pd","Ag","Cd","In","Sn","Sb","Te","I" ,"Xe","Cs","Ba","La","Ce","Pr","Nd","Pm","Sm","Eu","Gd","Tb","Dy","Ho","Er","Tm","Yb","Lu","Hf","Ta","W","Re","Os","Ir","Pt","Au","Hg","Tl","Pb","Bi","Po","At","Rn","Fr","Ra","Ac","Th","Pa","U","Np","Pu","Am","Cm","Bk","Cf","Es","Fm","Md","No","Lr"
  };

//! Number of CORE ORBITALS for each atom ! will serve to compute the BDA for valence MOs
// modif Eric : 04/04/2021:
const unsigned int ATOM_COREORB [] =
  {
     0 , 0  , 1  , 1  , 1 , 1 , 1 , 1 , 1 , 1  , 5  , 5  , 5  , 5  , 5 , 5  , 5  , 5 , 9 , 9  , 9  , 9  , 9 , 9  , 9  , 9  , 9  , 9  , 9  , 9  , 14 , 14 , 14 , 14 , 14 , 14 , 18 , 18 , 18 , 18 , 18 , 18 , 18 ,  18 , 18 , 18 , 18 , 18 , 23 , 23 , 23 , 23 , 23 , 23 ,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE
  };

//! Total number of electrons for each atom
const unsigned int ATOM_ELECTRONS [] =
  {
     1 , 2  , 3  , 4  , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15, 16 , 17 , 18, 19, 20 , 21 , 22 , 23, 24 , 25 , 26 , 27 , 28 , 29 , 30 , 31 , 32 , 33 , 34 , 35 , 36 , 37 , 38 , 39 , 40 , 41 , 42 , 43 ,  44 , 45 , 46 , 47 , 48 , 49 , 50 , 51 , 52 , 53 , 54 ,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE,MAXCORE
  };

/**
 * @fn void setFrag(const std::string definition, const param_types_t FRAG, const int nbAtoms)
 * @brief This function is used to ascribe FRAG atom indexes from string definition given in param.igm input file
 * @param definition : The string defining the fragment (for instance: 1-3; 8; 10-13)
 * @param FRAG       : The selected fragment (FRAG1 or FRAG2) to be associated with string definition
 * @param nbAtoms    : The total number of atoms in the molecular system
*/
void setFrag(const std::string definition, const param_types_t FRAG, const int nbAtoms);


/**
 * @fn bool isANumber(const std::string &s)
 * @brief This function is used to check whether a string is a number or not.
 * @param s : the string to check.
 * @return true if the string was a number, false otherwise.
*/
bool isANumber(const std::string &s);

/**
 * @fn int conversionAtom(std::string& tmp);
 * @brief This function is used to convert an atom name in char into an integer. Note that the integer corresponds to the atomic number of the atom minus one to fit easily with the C indexes.
 * @param tmp : the atomic symbole in char*.
*/
int conversionAtom(std::string& tmp);

/**
 * @fn int conversionParam(std::string& param)
 * @brief This function is used to convert a type of parameter from string to int so it may be used in a switch case.
 * @param param : the parameter as a string.
 * @return the parameter as an integer.
*/
int conversionParam(std::string& param);

/**
 * @fn void readParam(const char* parameterFileName, param_t* params)
 * @brief Read the file param.nci
 * @param parameterFileName The parameter file name
 * @param params the parameters.
*/
void readParam(const char* parameterFileName, param_t* params);

/**
 * @fn ProgData* readxyzMinMax(param_t * params)
 * @brief Reads files (.xyz) and find the Min (MinX,MinY,MinZ) and the Max (MinX,MinY,MinZ)
 * @param params : the read parameters.
 * @return the data to fill.
*/
ProgData* readxyzMinMax(param_t * params);

/**
 * @fn bool isWFmodeActivated()
 * @brief Tool function which indicates if the current calculus is based on wfn/wfx/rkf files
 * @return The value of the corresponding flag 
 */
bool isWFmodeActivated();

/**
 * @fn bool isWFXmodeActivated()
 * @brief Tool function which indicates if the current calculus is based on wfx file
 * @return The value of the corresponding flag 
 */
bool isWFXmodeActivated();


/**
 * @fn bool isWFNmodeActivated()
 * @brief Tool function which indicates if the current calculus is based on wfn file
 * @return The value of the corresponding flag 
 */
bool isWFNmodeActivated();

/**
 * @fn bool isRKFmodeActivated()
 * @brief Tool function which indicates if the current calculus is based on rkf file
 * @return The value of the corresponding flag 
 */
bool isRKFmodeActivated();

/**
 * @fn std::string getMoleculeAatomDefinition()
 * @brief Tool function which returns a string description of the FRAG1 atoms (given in param.igm)
 * @return The string description
 */
std::string getMoleculeAatomDefinition();


/**
 * @fn std::string getMoleculeBatomDefinition()
 * @brief Tool function which returns a string description of the FRAG2 atoms (given in param.igm)
 * @return The string description
 */
std::string getMoleculeBatomDefinition();



/**
 * @fn unsigned int wfn_getMoleculeAnbAtoms()
 * @brief Tool function which indicates the number of atoms in molecule A
 * @return The size of the molecule A
 */
unsigned int wfn_getMoleculeAnbAtoms();

/**
 * @fn unsigned int wfn_getMoleculeBnbAtoms()
 * @brief Tool function which indicates the number of atoms in molecule B
 * @return The size of the molecule B
 */
unsigned int wfn_getMoleculeBnbAtoms();

/**
 * @fn void analyseSetFRAG1FRAG2(const std::string definition1, const std::string definition2, const int nbAtoms)
 * @brief Tool function which decodes how the user defines the two interacting Fragments1 and 2
 * @param definition1 The user definition of molecule 1
 * @param definition2 The user definition of molecule 2
 * @param nbAtoms The total number of atoms   
 * @param params The object gathering data read from param.igm
 */
void analyseSetFRAG1FRAG2(const std::string definition1, const std::string definition2, const int nbAtoms, param_t *params);

/**
 * @fn bool isInMoleculeA(unsigned int atomNaturalIndex)
 * @brief Function which indicated if the given atom (natural index coming from WFN file) belongs to molecule A
 * @param atomNaturalIndex The atom index
 * @return true if the atom is in molecule A */
bool isInMoleculeA(unsigned int atomNaturalIndex);

/**
 * @fn bool isInMoleculeB(unsigned int atomNaturalIndex)
 * @brief Function which indicated if the given atom (natural index coming from WFN file) belongs to molecule B
 * @param atomNaturalIndex The atom index
 * @return true if the atom is in molecule B */
bool isInMoleculeB(unsigned int atomNaturalIndex);


/**
 * @fn std::string getCondensedDescriptionOfMoleculeA()
 * @brief Function which returns the description of atoms included in molecule A
 * @return The wanted description (compute at each call) */
std::string getCondensedDescriptionOfMoleculeA();

/**
 * @fn std::string getCondensedDescriptionOfMoleculeB()
 * @brief Function which returns the description of atoms included in molecule B
 * @return The wanted description (compute at each call) */
std::string getCondensedDescriptionOfMoleculeB();

/**
 *@fn void howUsingIGMplot()
 *@brief Tool function which prints how the application can be launched*/
void howUsingIGMplot();

/**
 * @fn bool isIBSImodeActivated()
 * @brief Tool function which indicates if the current calculus uses IBSI mode
 * @return The value of the corresponding flag 
 */
bool isIBSImodeActivated();

/**
 * @fn bool isELFmodeActivated()
 * @brief Tool function which indicates if ELF analysis is to be performed     
 * @return The value of the corresponding flag 
 */
bool isELFmodeActivated();


/**
 * @fn bool isIGMmodeActivated()
 * @brief Tool function which indicates if IGM analysis is to be performed     
 * @return The value of the corresponding flag 
 */
bool isIGMmodeActivated();

/**
 * @fn bool isfullAOAccActivated()
 * @brief Indicates if full accuracy is used for AO calculations               
 * @return The value of the corresponding flag 
 */
bool isfullAOAccActivated();

/**
 * @fn bool isHirshmodeActivated()
 * @brief Tool function which indicates if the current calculus uses Hirsh mode
 * @return The value of the corresponding flag 
 */
bool isHirshmodeActivated();

/**
 * @fn bool isCriticmodeActivated()
 * @brief Tool function which indicates if the current calculus uses Critic mode
 * @return The value of the corresponding flag 
 */
bool isCriticmodeActivated();


/**
 * @fn bool isParseRKF()
 * @brief Tool function which indicates if RKF has to be parsed without grid calculation
 * @return The value of the corresponding flag 
 */
bool isParseRKF();
// the RKF binary file will be parsed no grid calculation
// useful to read the content of an RKF binary file

/**
 * @fn bool isPauli()
 * @brief Tool function which indicates if The Pauli exchange has to be estimated       
 * @return True if Pauli exchange has to be estimated
 */
bool isPauli();

/**
 * @fn bool isPauliAtomic()
 * @brief Tool function which indicates if The Pauli exchange has to be estimated with atomic contrib.
 * @return True if Pauli exchange has to be estimated
 */
bool isPauliAtomic();


/**
 * @fn bool isPROSELF()
 * @brief Tool function which indicates if the steric effect analysis is requested at the promolecular level
 * @return True if a PROSELF analyis is requested
 */
bool isPROSELF();

/**
 * @fn bool isTOPELF()
 * @brief Tool function which indicates if the topological analysis of ELF basins is requested or not         
 * @return True if an ELF basin  analysis is requested
 */
bool isTOPELF();




/**
 * @fn bool isdgSCALED()
 * @brief Tool function which indicates if the dgSCALED mode is enabled
 * @return The value of the corresponding flag 
 */
bool isdgSCALED();


/**
 * @fn bool isCriticMEDIUMmodeActivated()
 * @brief Tool function which indicates if the current calculus uses CriticMEDIUM mode
 * @return The value of the corresponding flag 
 */
bool isCriticMEDIUMmodeActivated();

/**
 * @fn bool isCriticFINEmodeActivated()
 * @brief Tool function which indicates if the current calculus uses CriticFINE mode
 * @return The value of the corresponding flag 
 */
bool isCriticFINEmodeActivated();

/**
 * @fn bool isCriticULTRAFINEmodeActivated()
 * @brief Tool function which indicates if the current calculus uses CriticULTRAFINE mode
 * @return The value of the corresponding flag 
 */
bool isCriticULTRAFINEmodeActivated();

/**
 * @fn bool isCriticAddSeedsmodeActivated();
 * @brief Tool function which indicates if additional seeds are use for cp search         
 * @return The value of the corresponding flag 
 */
bool isCriticAddSeedsmodeActivated();


/**
 * @fn bool isPeakFocusIntraActivated()
 * @brief Tool function which indicates if a peakFocusIntra has been required by user
 * @return True if PEAKFOCUSINTRA keyword found in param.igm  
 */
bool isPeakFocusIntraActivated();

/**
 * @fn bool isPeakFocusInterActivated()
 * @brief Tool function which indicates if a peakFocusInter has been required by user
 * @return True if PEAKFOCUSINTER keyword found in param.igm  
 */
bool isPeakFocusInterActivated();

/**
 * @fn bool atomBondsHaveBeenRegistered()
 * @brief Tool function which indicates if atom bonds have been registered
 * @return True if one or more bonds have been registered
 */
bool atomBondsHaveBeenRegistered();

/**
 * @fn std::vector< std::pair<unsigned int, unsigned int > > & getChosenBonds()
 * @brief Function to gain access to the chosen bonds
 * @return The wanted registered bonds
 */
std::vector< std::pair< unsigned int,  unsigned int > > & getChosenBonds();

/**
 * @fn void checkKeywords(param_t *params)
 * @brief Function to check the keywords compatibility
 * @param params The object gathering data read from param.igm
 */
void checkKeywords(param_t *params);

#endif 
