
/***************************************************************************
                          population.cpp  -  Librairie d'objets permettant de manipuler des données
                          						spécifiques aux populations
                             -------------------
    begin                : ven sep 01 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.                                   *
 *                                                                         *
 ***************************************************************************/

#include "population.h"
#include "jeupop.h"

//constructeur
Population::Population(Jeupop * pdonnees):StrucPop(pdonnees){
	// ********************      Traitement des Metapops ***********
	// *********** 5/9/2000
	_Pmetapop = pdonnees->_Pracinepops;  //par défaut
	// 
	//
	//
	//_Pmetapop->AjouterPopulation(this);

}

//constructeur
Population::Population(MetaPop * Pmetapop):StrucPop(Pmetapop->get_Pjeu()){
	// ********************      Traitement des Metapops ***********
	// *********** 5/9/2000
	_Pmetapop = Pmetapop;
	// 
	// 
	//_Pmetapop->AjouterPopulation(this);

}


//constructeur de copies
Population::Population (const StrucPop & popori, MetaPop * Pmetapop):StrucPop(popori, Pmetapop, Pmetapop->get_Pjeu()){
	unsigned long i;
//cerr << "Population::Population construct copie début " << _nom  << endl;
	Individu * Poriind;

	//seulement pour l'objet Population:
//	_nbind = popori.get_nbind();
//cerr << "Population::Population construct copie _nbind " << popori.get_nbind() << endl;

	for (i=0; i < popori.get_nbind(); i++) {
		Poriind =  popori.get_Pind(i);
//cerr << "Population::Population construct copie _nomind " << Poriind->get_nom() << endl;
		Poriind =  new Individu(*Poriind, this);
//cerr << "Population::Population construct copie _nomind " << Poriind->get_nom() << endl;

		AjouterIndividu(Poriind);
	}
//cerr << "Population::Population construct copie fin " << endl;
}


//destructeur
Population::~Population () {

	while (_tabPind.size() > 0) {
//cerr << "Population::~Population " <<_tabPind[0]->get_nom() << endl;
		SupprIndividu(_tabPind[0]);
	}

}

bool Population::DuType(const string & nom) const {
	if (nom == "Population") return(true);
	else return(false);
}

void Population::AjouterIndividu(Individu * Pind) {
	//ajout d'un individu dans une Population
//cerr << "Population::AjouterIndividu(Individu * Pind) début" << endl;
	_tabPind.push_back(Pind);

	_nbind++;
//cerr << "Population::AjouterIndividu " << _nbind << endl;
	_Pmetapop->AjouterIndividu(Pind);
//cerr << "Population::AjouterIndividu(Individu * Pind) fin" << endl;
	
}

void Population::ifAjouterIndividu(const Individu * Pind) {
	//ajout d'un individu dans une Population, avec les alleles correspondants
	// => recherche d'un individu deja définis
	long i, taille(get_nbind()), nbind(-1);
	const string nomind(Pind->get_nom());

	_nbloc = _Pjeu->get_nbloc();

	for (i = 0 ; i < taille; i++) {
		if (nomind == get_nomind(i)) {
			nbind = i;
			break;
		}
	}

	if (nbind >= 0) { //l'individu existe deja
		//il faut ajouter les locus (les alleles) 
		//     que l'original n'a pas
		// pb à résoudre: incohérence entre alleles d'un meme locus,
		//   d'un meme individu...
		get_Pind(nbind)->ifFusionnerIndividu(*Pind);
	}
	else { //il faut creer un nouvel individu
		_tabPind.push_back(new Individu(this, nomind));
		// et le remplir
		_tabPind.back()->ifFusionnerIndividu(*Pind);
	}
}

void Population::get_nomniveauxstruc(Titre & nom_niveaux) const{

	unsigned long niveau(get_niveau());

	if (nom_niveaux.size() < (niveau + 1)) nom_niveaux.push_back(_nom);
	else nom_niveaux[niveau] = nom_niveaux[niveau] + " " + _nom;
		
}

unsigned int Population::get_niveau() const {
	return (_Pmetapop->get_niveau()+1);
}

void Population::set_nploidie() {
	_nploidie = _Pjeu->get_nploidie();
	_nbloc = _Pjeu->get_nbloc();

	unsigned long i;

//cerr << "Population::set_nploidie() " << _nploidie  << endl;
	for (i=0; i < _tabPind.size(); i++) {
		_tabPind[i]->resize_alleles();
	}
//cerr << "Population::set_nploidie() fin" << _nploidie  << endl;
//cin >> i;
}

void Population::set_nploidie(unsigned int nploidie) {
  if (_nploidie == 0) {
    _nploidie = nploidie;
    _Pjeu->set_nploidie(nploidie);
  }
  else if (_nploidie != nploidie) throw Anomalie(2);
  
}

string Population::get_nom_chemin() const {
	MetaPop * Pmetapop(_Pmetapop);

	string nom_complet(_nom);
	string separateur("/");

	while ((Pmetapop != 0) && (Pmetapop->get_niveau() != 0)) {
		nom_complet = Pmetapop->get_nom() + separateur + nom_complet;
		Pmetapop =  Pmetapop->get_Pmetapop();
	}	

	return (nom_complet);
}

void Population::f_rempliTabStrucPop(Vecteur<StrucPop*> & tabStrucPop, unsigned int niveau) {
  tabStrucPop.push_back(this);
}
/** Suppression de la Population */
void Population::SupprPop(StrucPop * Ppop){
	if (Ppop != this) return;

	unsigned long nbind (get_nbind()), i;

	for (i = 0; i < nbind; i++) {
		
 	}	
}
/** Suppression d'un individu dans une Population */
void Population::SupprIndividu(Individu * Pind) {
	SupprtabIndividu(Pind);
	delete (Pind);
//cerr << "Population::SupprIndividu fin" << endl;
}

void Population::oPopulationsXML(unsigned int id, ostream & sortie, ostream & infos) {
  unsigned int i, nbind(get_nbind());
  biolib::vecteurs::ChaineCar idXML;

  sortie << "<population";
  idXML = "p";
  idXML.AjEntier(id);
  idXML += "le";
  idXML.AjEntier(get_niveau());
  set_idXML(idXML);
  sortie << " id=\"" << idXML << "\"";
  sortie << " name=\"" << get_nom() << "\"";
  sortie << ">" << endl;


  for (i=0; i < nbind; i++) {
    get_Pind(i)->oPopulationsXML(i, sortie, infos);
  }

  sortie << "</population>" << endl;

}

Individu * Population::new_individual(string & name, unsigned int nploidie) {
  if (get_nploidie() == 0) set_nploidie(nploidie);
  else if (get_nploidie() != nploidie) {
    throw Anomalie(2);
  }

  Individu * Pind(new Individu(this, name));

  AjouterIndividu(Pind);


  return (Pind);
}

