import java.util.ArrayList;

public class Personne {
	private final String prenom, nomDeFamille;
	private Personne mere, pere;

	public Personne(String prenom, String nomDeFamille) {
		this.prenom = prenom;
		this.nomDeFamille = nomDeFamille;
		this.mere = null;
		this.pere = null;
	}

	public Personne(String prenom, String nomDeFamille, Personne mere, Personne pere) {
		this.prenom = prenom;
		this.nomDeFamille = nomDeFamille;
		this.mere = mere;
		this.pere = pere;
	}

	public String getPrenom() {
		return this.prenom;
	}

	public String getNomDeFamille() {
		return this.nomDeFamille;
	}

	public void setMere(Personne p) {
		this.mere = p;
	}

	public void setPere(Personne p) {
		this.pere = p;
	}

	public boolean estFrereOuSoeur(Personne p) {
		if(p == null || this == p) {
			return false;
		}
		return (this.mere == p.mere && this.pere == p.pere);
	}

	public boolean estCousinGermain(Personne p) {
		return (this.mere.estFrereOuSoeur(p.mere) || this.mere.estFrereOuSoeur(p.pere) || this.pere.estFrereOuSoeur(p.mere) || this.pere.estFrereOuSoeur(p.pere));
	}

	public int nbAscendants() {
		if(this.mere == null) {
			if(this.pere == null) {
				return 0;
			}
			return 1 + this.pere.nbAscendants();
		}
		if(this.pere == null) {
			return 1 + this.mere.nbAscendants();
		}
		return 2 + this.mere.nbAscendants() + this.pere.nbAscendants();
	}

	public boolean possedeCommeAscendant(Personne p) {
		if(this == p) {
			return true;
		}
		boolean testM = false;
		boolean testP = false;
		if(this.mere != null) {
			testM = this.mere.possedeCommeAscendant(p);
		}
		if(this.pere != null) {
			testP = this.pere.possedeCommeAscendant(p);
		}
		return (testM || testP);
	}

	public int distanceDAscendance(Personne p) {
		if(this == p) {
			return 0;
		}
		if(this.possedeCommeAscendant(p)) {
			if(this.mere.possedeCommeAscendant(p)) {
				return 1 + this.mere.distanceDAscendance(p);
			}
			else {
				return 1 + this.pere.distanceDAscendance(p);
			}
		}
		if(p.possedeCommeAscendant(this)) {
			return p.distanceDAscendance(this);
		}
		return -1;
	}

	public void afficheAscendantUn(Personne p) {
		System.out.print(this.prenom + " " + this.nomDeFamille + ", ");
		if(this.mere.possedeCommeAscendant(p)) {
			this.mere.afficheAscendantUnAux(p);
			System.out.print("enfant de " + p.prenom + " " + p.nomDeFamille + ".");
		}
		else if(this.pere.possedeCommeAscendant(p)) {
			this.pere.afficheAscendantUnAux(p);
			System.out.print("enfant de " + p.prenom + " " + p.nomDeFamille + ".");
		}
		else {
			System.out.print("n'est pas descendant de " + p.prenom + " " + p.nomDeFamille + ".");
		}
	}

	public void afficheAscendantUnAux(Personne p) {
		if(this == p) {
			return;
		}
		System.out.print("enfant de " + this.prenom + " " + this.nomDeFamille + ", ");
		if(this.mere.possedeCommeAscendant(p)) {
			this.mere.afficheAscendantUnAux(p);
		}
		else {
			this.pere.afficheAscendantUnAux(p);
		}
	}

	public int nbDeGenerations() {
		if(this.mere == null && this.pere == null) {
			return 0;
		}
		int nbM = 1 + this.mere.nbDeGenerations();
		int nbP = 1 + this.pere.nbDeGenerations();
		if(nbM >= nbP) {
			return nbM;
		}
		else {
			return nbP;
		}
	}

	public boolean verification() {
		if(this.mere == null && this.pere == null) {
			return true;
		}
		if(this.mere != null && this.pere != null) {
			return (this.mere.verification() && this.pere.verification() && this.nomDeFamille.equals(this.pere.nomDeFamille) && !this.mere.estFrereOuSoeur(this.pere) && !this.mere.estCousinGermain(this.pere));
		}
		if(this.pere != null) {
			return (this.pere.verification() && this.nomDeFamille.equals(this.pere.nomDeFamille));
		}
		return this.mere.verification();
	}

	public ArrayList<Personne> getTousLesAscendants() {
		ArrayList<Personne> x = new ArrayList<Personne>();
		return this.getTousLesAscendantsAux(x);
	}

	public ArrayList<Personne> getTousLesAscendantsAux(ArrayList<Personne> x) {
		x.add(this);
		if(this.mere != null) {
			this.mere.getTousLesAscendantsAux(x);
		}
		if(this.pere != null) {
			this.pere.getTousLesAscendantsAux(x);
		}
		return x;
	}
}
