/*
 * 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 ProgData.h
 * @brief Contains parameters of the instance
 * @author Emmanuel */

#ifndef _PROGDATA_H_
#define _PROGDATA_H_

// STL
// transfert to toolbox.h
//#include <cstdlib>
//#include <vector>

// LOCAL
#include <LocalData.h>


/**
 * @brief Class designed to store the program's main dataprovide some utilities concerning those
 * @warning No copy constructor defined, careful when trying to pass this by value */
class ProgData
{

 private :
		
  // Program data

  //! Number of atoms in molecule A
  int nbAtomMolA;

  //! Number of atoms in molecule B
  int nbAtomMolB;

  //! Number of the ligand ; if none : -1
  int numLigand;

  //! Number of atoms in both molecule (if two)
  int nbAtom;

  //! Number of bonds studied (QM treatment)
  unsigned int nbBond;

  //! Max coordinates
  double maxCoordinates[3];
  double maxCoordinatesA[3];
  double maxCoordinatesB[3];

  //!  Min coordinates
  double minCoordinates[3];
  double minCoordinatesA[3];
  double minCoordinatesB[3];

  //! Number of steps in loop for all three axis
  int nbSteps[3];
	
  // Other utilities' variables

  //! Used to iterate through the arrays
  int cursor;

  //! Used to check whether CUBE option has been used
  bool boxSet;

  //! Used to check whether RADIUS option has been used
  bool radiusSet;

  //! TO DOCUMENT
  int cnt;

  //! 
		
 public :

  //! arry of atom's type
  int * atomTypes; // in the range [0:nbAtoms-1]

  //! Each atom's position
  positions_t atomPositions;

  //! array of studied bonds (QM treatment)
  bond_t * bonds; 


  
  /**
   * @fn  ProgData(int nbAtomMolAParam, int nbAtomMolBParam, int nbTotalAtomParam, int numLigandParam, std::vector<std::pair< unsigned int,  unsigned int> > &chosenBondsParam);
   * @brief Constructor
   * @param nbAtomMolAParam : the number of atoms in molecule A
   * @param nbAtomMolBParam : the number of atoms in molecule B
   * @param nbTotalAtomParam,: the total number of atoms 
   * @param numLigandParam : the molecule index corresponding to the ligand 
   * @param chosenBondsParam    : the studied bonds (only for QM treatment) */
  //ProgData(int nbAtomMolAParam, int nbAtomMolBParam, int numLigandParam, int nbBondParam);
  ProgData(int nbAtomMolAParam, int nbAtomMolBParam, int nbTotalAtomParam, int numLigandParam, std::vector<std::pair< unsigned int,  unsigned int> > &chosenBondsParam);

  /**
   * @fn ~ProgData()
   * @brief Destructor */
  ~ProgData();
		
  /**
   * @fn void addAtom(int type, double posx, double posy, double posz, bool WFNmode)
   * @brief Adds an atom with the given properties to the atom's array
   * @param type the type of the atom
   * @param posx the position of the atom on the x axis
   * @param posy the position of the atom on the y axis
   * @param posz the position of the atom on the z axis
   * @param setLIGAND : input --> says if the user has supplied or not the index of the ligand within the two fragments
   * @param WFNmode indicates if we are using WFN file (not by default) 
   * @param HirshMode indicates if we are using the Hirshfeld partition (not by default) */
  void addAtom(int type, double posx, double posy, double posz, bool setLIGAND=false, bool WFNmode=false, bool HirshMode=false);
		
  /**
   * @fn void validate(double * increments, double ligandRadius, bool setLIGAND)
   * @brief Ends the atom adding and update the coordinates before reporting whether the values are consistent
   * @param increments the increments values
   * @param ligandRadius the radius around the ligand that has been provided 
   * @param setLIGAND : input --> to tell if the index of the ligand has been supplied or not by user 
   * @param QMmode    : input --> to tell if the QUANTUM mode is enabled or not  */
   
  void validate(double * increments, double ligandRadius, bool setLIGAND, bool QMmode);
		
  /**
   * @fn void setCube( double * cubeParam )
   * @brief Sets the given cube has the reference cube to the problem
   * @param cubeParam the cube */
  void setCube( double * cubeParam );
				
  /**
   * @fn void setRadius( double * radiusParam )
   * @brief Sets the given radius has the reference cube to the problem
   * @param radiusParam : the radius */
  void setRadius( double * radiusParam );

  /**
   * @fn int getNbBond()
   * @brief Gets the number of studied bonds
   * @return the number of studied bonds */
  unsigned int getNbBond();

  /**
   * @fn int getNbAtom()
   * @brief Gets the number of atom
   * @return the number of atom */
  int getNbAtom();
		
  /**
   * @fn int getNbAtomMolA()
   * @brief Gets the number of atom in molecule A
   * @return the number of atom in molecule A */
  int getNbAtomMolA();

  /**
   * @fn int getNbAtomMolB()
   * @brief Gets the number of atom in molecule B
   * @return the number of atom in molecule B */
  int getNbAtomMolB();
		
  /**
   * @fn double getMaxCoord(int axis)
   * @brief Gets the max coordinate for the given axis
   * @param axis the given axis
   * @return the max coordinate for the given axis */
  double getMaxCoord(int axis);
		
  /**
   * @fn double getMinCoord(int axis)
   * @brief Gets the min coordinate for the given axis
   * @param axis : the given axis
   * @return the min coordinate for the given axis */
  double getMinCoord(int axis);

  /**
   * @fn int getNbSteps(int axis)
   * @brief Gets the number of steps for the given axis
   * @param axis : the given axis
   * @return the number of steps for the given axis */
  int getNbSteps(int axis);

  /**
   * @fn string  getGridBoxDefinition()
   * @brief Gets the way the box was deinied by user
   * @return the grid Box definition */
  std::string getGridBoxDefinition();
		
  /**
   * @fn void setNbAtomMolA(int newValue)
   * @brief setter for nbAtomMolA variable
   * @param newValue The new value for this variable */
  void setNbAtomMolA(int newValue);

  /**
   * @fn void setNbAtomMolB(int newValue)
   * @brief setter for nbAtomMolB variable
   * @param newValue The new value for this variable */
  void setNbAtomMolB(int newValue);

  /**
   * @fn void setNbSteps(int nbStepsX, int nbStepsY, int nbStepsZ)
   * @brief Function to manually set the number of steps of each axis (IBSI case)
   * @param nbStepsX The number of steps for X axis
   * @param nbStepsY The number of steps for Y axis
   * @param nbStepsZ The number of steps for Z axis*/
  void setNbSteps(int nbStepsX, int nbStepsY, int nbStepsZ);

  /**
   * @fn void storeBondLength(unsigned int ibond, double length)
   * @brief Function to manually store the length of a studied bond (IBSI case)
   * @param ibond The bond index 
   * @param length The bond length                */
  void storeBondLength( unsigned int ibond, double length);

  /**
   * @fn void storeBondVector(unsigned int ibond, double ABx, double ABy, double ABz)
   * @brief Function to manually store the vector components of the AB bond    
   * @param ibond index for storing the vector components   
   * @param ABx the x component   
   * @param ABy the y component 
   * @param ABz the z component                 */
  void storeBondVector(unsigned int ibond, double ABx, double ABy, double ABz);

  /**
   * @fn void setIBSI(unsigned int ibond, double newValue)
   * @brief Function to manually set the IBSI score of a studied bond (IBSI case)
   * @param ibond The bond index 
   * @param newValue The IBSI score                 */
  void setIBSI(unsigned int ibond, double newValue);

  /**
   * @fn void setBAF(unsigned int ibond, double newValue)
   * @brief Function to manually set the BDA score of a studied bond (IBSI case)
   * @param ibond The bond index 
   * @param newValue The BDA  score                 */
  void setBAF(unsigned int ibond, double newValue);

  /**
   * @fn double getIBSI(int ibond)
   * @brief Function to manually get the IBSI score of a studied bond (IBSI case)
   * @param ibond The bond index */
  double getIBSI(int ibond);

  /**
   * @fn double getBAF(int ibond)
   * @brief Function to manually get the BDA score of a studied bond (IBSI case)
   * @param ibond The bond index */
  double getBAF(int ibond);



};

#endif
