import java.awt.Color;

/** Cercle modélise un cercle dans le plan caractérisé
 * par son centre, son rayon et sa couleur. Il peut être
 * construit à partir de son centre et de son rayon ou
 * d'un autre point ou à partir de deux point diamétralement
 * opposés.
 *
 * @author  Édouard Lumet edouard.lumet@etu.enseeiht.fr
 * @version 1.0
 */
public class Cercle implements Mesurable2D {

	// Attributs //

	/** Couleur du cercle. */
	private Color couleur;

	/** Centre du cercle. */
	private Point centre;

	/** Rayon d'un cercle. */
	private double rayon;

	/** Constante PI 3.14159... */
	public static final double PI = Math.PI;

	// Constructeurs //

	/** Construire un cercle bleu à partir d'un centre et d'un rayon.
	 *
	 * @param centre Le centre du cercle
	 * @param rayon Le rayon du cercle
	 */
	public Cercle(Point centre, double rayon) {
		assert centre != null;
		assert rayon > 0;
		this.centre = new Point(centre.getX(), centre.getY());
		this.centre.setCouleur(centre.getCouleur());
		this.rayon = rayon;
		this.couleur = Color.blue;
	}

	/** Construire un cercle bleu à partir de deux points
	 * diamétralement opposés (E12).
	 *
	 * @param point Un point sur la périphérie du cercle
	 * @param pointOppose Un point diamétralement opposé au premier point
	 */
	public Cercle(Point point, Point pointOppose) {
		assert point != null;
		assert pointOppose != null;
		assert point.distance(pointOppose) > 0;
		// Variables temporaires pour le calcul des coordonnées
		double tmpX = (point.getX() + pointOppose.getX()) / 2;
		double tmpY = (point.getY() + pointOppose.getY()) / 2;

		this.centre = new Point(tmpX, tmpY);
		this.rayon = point.distance(pointOppose) / 2;
		this.couleur = Color.blue;
	}

	/** Construire un cercle à partir de deux points diamétralement
	 * opposés et d'une couleur.
	 *
	 * @param point Un point sur la périphérie du cercle
	 * @param pointOppose Un point diamétralement opposé au premier point
	 * @param couleur La couleur du cercle
	 */
	public Cercle(Point point, Point pointOppose, Color couleur) {
		this(point, pointOppose);
		assert couleur != null;
		this.couleur = couleur;
	}

	// Méthodes //

	/** Construire un cercle à partir de deux points, l'un étant le
	 * centre et l'autre étant un point sur la périphérie du cercle.
	 * NB: creerCercle est une méthode de classe.
	 *
	 * @param centre Le centre du cercle
	 * @param extremite Un autre point en périphérie du cercle
	 * @return Un cercle construit à partir d'un point centre et un point
	 * en périphérie du cercle
	 */
	public static Cercle creerCercle(Point centre, Point extremite) {
		assert centre != null;
		assert extremite != null;
		return new Cercle(centre, centre.distance(extremite));
	}

	/** Calcul du périmètre du cercle.
	 *
	 * @return Le périmetre du cercle
	 */
	@Override
	public double perimetre() {
		return PI * this.getDiametre();
	}

	/** Calcul de l'aire du disque délimité par le cercle.
	 *
	 * @return L'aire du disque lié au cercle
	 */
	@Override
	public double aire() {
		return PI * Math.pow(this.getRayon(), 2);
	}

	/** Afficher le cercle sous le format Cr@(a, b).
	 *
	 */
	public void afficher() {
		System.out.print(this.toString());
	}

	/** Indique si le point appartient au cercle (est dans l'aire du disque).
	 *
	 * @param point Un point du repère
	 * @return True si le point appartient au cercle
	 */
	public boolean contient(Point point) {
		assert point != null;
		return this.centre.distance(point) <= this.rayon;
	}

	/** Translater le cercle selon un déplacement suivant.
	 * l'axe des X et suivant l'axe des Y
	 *
	 * @param deplacementX Déplacement suivant l'axe des X
	 * @param deplacementY Déplacement suivant l'axe des Y
	 */
	public void translater(double deplacementX, double deplacementY) {
		this.centre.translater(deplacementX, deplacementY);
	}

	// Getters & Setters //

	/**
	 * @return La couleur du cercle
	 */
	public Color getCouleur() {
		return couleur;
	}

	/**
	 * @param couleur La couleur à affecter
	 */
	public void setCouleur(Color couleur) {
		assert couleur != null;
		this.couleur = couleur;
	}

	/**
	 * @return Le rayon du cercle
	 */
	public double getRayon() {
		return rayon;
	}

	/**
	 * @param rayon Le rayon à affecter
	 */
	public void setRayon(double rayon) {
		assert rayon > 0;
		this.rayon = rayon;
	}

	/**
	 * @return Le centre du cercle
	 */
	public Point getCentre() {
		/* Création d'une "copie" du centre empêchant
		l'accès direct à l'objet Point centre */
		Point tmpCentre = new Point(centre.getX(), centre.getY());
		tmpCentre.setCouleur(centre.getCouleur());

		return tmpCentre;
	}

	/**
	 * @param centre Le centre à modifier
	 */
	public void setCentre(Point centre) {
		assert centre != null;
		this.centre = centre;
	}

	/**
	 * @return Le diamètre du cercle
	 */
	public double getDiametre() {
		return rayon * 2;
	}

	/**
	 * @param diametre Le diamètre à affecter
	 */
	public void setDiametre(double diametre) {
		assert diametre > 0;
		this.rayon = diametre / 2;
	}

	@Override
	public String toString() {
		return "C" + this.rayon + "@" + this.centre;
	}

}
