/***************************************************************************
                          jeupop.h  -  Librairie d'objets permettant de manipuler des donn�es
                          						sp�cifiques aux populations
                             -------------------
    begin                : ven sep 06 10:25:55 CEST 2000
    copyright            : (C) 2000 by Olivier Langella CNRS UPR9034
    email                : Olivier.Langella@pge.cnrs-gif.fr
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef JEUPOP_H
#define JEUPOP_H

//#include"internat.h"

#include "matrices.h"
#include "allele.h"
#include "individu.h"
#include "strucpop.h"
#include "metapop.h"
#include "population.h"
#include "locus.h"

#include "chaineficpop.h"

#include "arbre.h"

//# ifdef XmlParse_INCLUDED
//# include "xmlreadpopulations.h"
//# endif
//#include "vecteurs.h"

//typedef biolib::arbres::ArbrePlus ArbrePlus;
typedef biolib::arbres::Arbre Arbre;
//typedef biolib::vecteurs::ChaineCar ChaineCar;
//class Arbre;

// jeu de populations
class Jeupop {
public :
	Jeupop();//npop, nloc
	//Jeupop(long nbpop, long nbloc);//npop, nloc

	Jeupop(const Jeupop&); //constructeur de copies

	~Jeupop();

	Population * NewPop(const biolib::vecteurs::ChaineCar &);
	Locus * new_locus(const string &);

	void reset();//npop, nloc
	Population* get_pop(unsigned long) const;
	//mieux en inline
	unsigned int get_nploidie() const;
	unsigned long get_nbloc() const;
	unsigned long get_nbpop() const;
	//unsigned long Jeupop::get_nbpop() const {
	
	unsigned long get_nbstrucpopVcalc() const {return (_VcalcStrucPop.size());};
	MetaPop * get_Pracinepop() const {return (_Pracinepops);};
	const StrucPop * get_PstrucpopVcalc(unsigned int numpop) const {return (_VcalcStrucPop[numpop]);};
	unsigned long get_nbind() const;
	//inline Allele* get_Pall(int loc, int all) const;
	Allele* get_Pall(unsigned long loc, unsigned long all) const;

	void AjouterPopulation(Population * Ppop);
	void AjouterTabPop(Population * Ppop);

	Locus* get_Plocus(const string &) const;
	Locus* get_Plocus(unsigned long i) const;
	Population* get_Ppop(string &) const;
	Population* get_Ppop(unsigned long p) const;
	const string & get_nomlocus(long nblocus) const;
	const string & get_nompop(long nbpop) const;
	signed long get_numloc(Locus * Ploc) const {return((signed long)_tabPloc.Position(Ploc));};
	signed long get_numpop(Population * Ppop) const {return((signed long)_tabPpop.Position(Ppop));};
//	long get_numloc(Locus * Ploc) const;
	void get_nomniveauxstruc(Titre & nom_niveaux) const;
	const Titre & get_commentaires() const {return(_commentaires);};

	void set_nploidie(unsigned int nploidie);
  void set_commentaires(const string & commentaires);

	void iFichier(istream & entree, int i);

	void iIntrogression(istream&);
	void oPopulations(ostream& sortie) const;
	void oGenepop(ostream&) const;
	void oGenepopCano(ostream&) const;

	void oImmanc(ostream&) const;
	//Immanc - detects individual that are immigrants or have recent immigrant ancestry
    //by using multilocus genotypes. 
    //Version 5.0, released October 8, 1998    
    //Reference: Rannala, B., and J.L., Mountain. 1997. Detecting immigration by using
    //multilocus genotypes. Proceedings of the National Academy of Sciences USA 94:
    //9197-9201. 

	void oMsat(ostream&) const;
	void oMsatFreq(ostream&) const;
	 //       microsat.c version 1.5e
      //  Eric Minch
     //   Dept. of Genetics
     //   Stanford University Medical Center
     //   Stanford, CA 94305
      //  minch@lotka.stanford.edu
	//http://lotka.stanford.edu/microsat/microsat.html

	void affind(int, int) const; //num�ro de la pop, num�ro de l'ind

// g�n�tique

	void f_trad2Gpop(ostream&);

	//calcul de la nouvelle diversit� all�lique, pour un �chantillon
	// r�duit: r�sultats stock�s dans Matrice, int => effectif r�duit
	void f_rarefaction(MatriceLD &, int) const;

	// calcul de distance g�n�tique entre Populations sur tous les individus, 2 a 2 
	void f_distgntpop (MatriceLD &resultat, int methode, bool square_distance, unsigned int niveau=100, Vecteur<unsigned int> * PVcalcLocus = NULL);
	// calcul de distance g�n�tique sur tous les individus, 2 a 2
	void f_distgnt (MatriceLD &resultat, int methode, bool square_distance, Vecteur<unsigned int> * PVcalcLocus = NULL);

	// V�rification du type de num�rotation des all�les
	bool f_verifnum (int) const;

	// Boostrap sur les locus => arbre d'individus ou populations
	void f_BootstrapLocus(Arbre & arbreRef, int methodeArbre, int methodeDist, bool square_distance, int nbrepet, bool sur_ind=true , Vecteur<unsigned int> * PVcalcLocus = NULL);
	void f_BootstrapIndividus(Arbre & arbreRef, int methodeArbre, int methodeDist, bool square_distance, int nbrepet , Vecteur<unsigned int> * PVcalcLocus = NULL);
//	void f_BootstrapLocus(Arbre & arbreRef, int methodeArbre, int methodeDist, int nbrepet , Vecteur<int> * PVcalcLocus = NULL);
//	void f_BootstrapLocuspop(Arbre & arbreRef, int methodeArbre, int methodeDist, int nbrepet , Vecteur<int> * PVcalcLocus = NULL);

	void f_rempliVcalcStrucPop(unsigned int niveau=100);
	void f_resetVcalcStrucPop() {_VcalcStrucPop.resize(0);};

	friend class Population;
	friend class DistancesGnt;
	friend class Fstat;
///	friend class Locus;

//	static int _tmot;

//	const Jeupop& operator= (const Jeupop &);
	Jeupop operator+ (const Jeupop &rval) const;
  /** Suppression de la population p du Jeupop */
  void SupprPop(StrucPop * Ppop);
  /** D�place la pop a � la position b */
  void f_deplacePop(Population * Ppop, unsigned long b);
  /** enl�ve les all�les qui ne sont pas repr�sent�s dans les populations
 */
  void f_nettoieAlleles();
  /** Retourne vrai, si l'allele n'est pas pr�sent dans jeupop */
  bool r_allelenonpresent(Allele * Pall) const;
  /** construit le vecteur Vlocus avec les numeros de tous les locus */
  void f_selectlocustous(vector<unsigned int> & Vlocus) const;
  /** Suppression des locus qui ne sont pas pr�sents dans Vnumloc */
  void GarderVlocus(Vecteur<unsigned int> & Vnumloc);
  /** obtenir le num�ro d'un locus avec son nom */
  signed int get_numloc(const string &) const;

private :
	MetaPop * _Pracinepops;

	Titre _commentaires;
	void iGenetix(istream&);
	void iGenepop(istream&);
	void iPopulations(istream&);
	void ifAjouterLocus(const Locus * Ploc);
  void iPopulationsXML(istream &fichier);
//	void ifAjouterPop(const Population * Ppop);
	//nombre d'alleles en commun sur un locus
//	int r_allcommun(Individu *, Individu *, unsigned int) const; //renvoi du nombre d'all�les en commun
//	int r_allcommunnul(Individu *, Individu *, int) const; //renvoi du nombre d'all�les en commun
//	long r_allcommunnul(Individu *, Individu *) const; //renvoi du nombre d'all�les en commun
//	long double r_allsimilnul(Individu *, Individu *) const;
	//distance entre 2 individus
//	double r_dist2ind(Individu *, Individu *, int) const; //renvoi de la distance
	
	unsigned int _nploidie; // haploide=1 diploide=2...
	unsigned int _nbpop; //nb de populations dans ce jeu
	Vecteur<Population*> _tabPpop;
	unsigned int _nbloc; //nb de loci dans ce jeu
	Vecteur<Locus*> _tabPloc;

	Vecteur<unsigned int> _VcalcLocus;
	Vecteur<StrucPop*> _VcalcStrucPop;

protected: // Protected methods
  /** Suppression d'un locus */
  void supprLocus(unsigned int);
  /** R�affectation du nombre de locus */
  void set_nbloc();

public :
	struct Anomalie{
		// 1-> op�ration possible seulement sur les diploides
		// 2-> les num�ros d'all�les format genepop ne sont pas pr�sents
		// 3-> donnee erronee dans le fichier d'entree
		// 4-> format Genepop incorrect en entree
		// 5-> format de fichier non reconnu
		// 6-> calcul de similitude impossible
		// 7-> op�ration impossible sur des populations de ploidie differentes
		// 8-> Locus introuvable
		// 9-> Population introuvable
		// 101-> erreur dans un calcul de distances
		// 201-> erreur de lecture dans un fichier G�n�tix

		unsigned int le_pb;
		Anomalie (unsigned int i):le_pb(i){};
	};

};



istream& operator>>(istream& ientree,Jeupop& LesPops);



#endif

