/*
 * © Philippe GENOUD - Université Grenobles Alpes
 * Equipe STeamer - Laboratoire d'Informatique de Grenoble
 *
 * Visage.js : le type objet Visage permettant de définir des
 * visages 'rebondissants'.
 */

export class Visage {
	//----------------------------------------------------------------------------------
	// propriétés statiques associées à la classe Visage
	//----------------------------------------------------------------------------------

	/**
	 * une propriété couleurVisage qui définit la couleur de remplissage des Visages.
	 * Cette propriété sera "héritée" par tous les Visages.
	 * @type String
	 */
	static couleurVisage = "bisque";

	//------------------------------------------------------------------------------
	// Constructeur et méthodes pour les visages rebondissants
	//------------------------------------------------------------------------------

	/**
	 * Constructeur pour des objets Visage
	 * @param {Canvas} canvas le canvas dans lequel le visage se déplace
	 * @param {number} xCentre abscisse du centre du visage
	 * @param {number} yCentre ordonnée du centre du visage
	 * @param {number} [rayon=50] rayon du visage
	 * @param {number} [vx = 5] déplacement horizontal élémentaire du visage
	 * @param {number} [vy = 5] déplacement vertical élémentaire du visage
	 * @returns {Visage}
	 */
	constructor(canvas, xCentre, yCentre, rayon = 50, vx = 5, vy = 5) {
		this.canvas = canvas;
		this.xCentre = xCentre;
		this.yCentre = yCentre;
		this.rayon = rayon;
		this.vx = vx;
		this.vy = vy;
		this.ctx = canvas.getContext("2d");
	}

	/**
	 * Dessine le visage.
	 * @returns {undefined}
	 */
	dessiner() {
		// le cercle délimitant le Visage
		this._dessinerTete();
		// la bouche
		this._dessinerBouche();
		// les yeux
		this._dessinerYeux();
	}

	/**
	 * dessine le disque matérialisant la tête
	 * comme pour _ctx (voir constructeur), on préfixe le nom de la methode par
	 * _ pour indiquer qu'elle est à usage interne.
	 * @returns {undefined}
	 */
	_dessinerTete() {
		this.ctx.beginPath();
		this.ctx.arc(this.xCentre, this.yCentre, this.rayon, 0, Math.PI * 2, true);
		this.ctx.strokeStyle = "coral"; // couleur de tracé des contours

		// fixer la couleur de remplissage
		// si l'objet a sa propre couleur on utilise celle-ci mais si il n'en a pas
		// on utilise la propriété statique de la classe Visage
		this.ctx.fillStyle = this.couleur || Visage.couleurVisage;
		// d'autres manière d'écrire cela
		//
		//avec un if
		//
		// if ("couleur" in this) {
		// 	this.ctx.fillStyle = this.couleur; // couleur associée à ce Visage (this)
		// } else {
		// 	this.ctx.fillStyle = Visage.couleurVisage; // couleur de remplissage par défaut
		// }
		//
		// avec un expression conditionnelle
		//
		// this.ctx.fillStyle = ("couleur" in this)?this.couleur:Visage.couleurVisage;

		this.ctx.fill();
		this.ctx.stroke();
	}

	/**
	 * dessine la bouche
	 * @returns {undefined}
	 */
	_dessinerBouche() {
		this.ctx.beginPath(); // beginPath permet de définir un nouveau chemin de tracé, en
		// l'absence de cette instruction on aurait un trait reliant le point de début de
		// tracé du cercle délimitant le visage au point de début du cercle
		// matérialisant la bouche
		this.ctx.arc(this.xCentre, this.yCentre, this.rayon * 0.6, 0, Math.PI, false);
		this.ctx.strokeStyle = "red";
		this.ctx.stroke();
	}

	/**
	 * dessine les yeux
	 * @returns {undefined}
	 */
	_dessinerYeux() {
		let yYeux = this.yCentre - this.rayon * 0.2;
		let dxYeux = this.rayon * 0.3;
		// les yeux
		this.ctx.beginPath();
		this.ctx.strokeStyle = "#369";
		this.ctx.fillStyle = "#c00";
		this.ctx.arc(this.xCentre + dxYeux, yYeux, this.rayon * 0.1, 0, Math.PI * 2, false);
		this.ctx.stroke();
		this.ctx.beginPath();
		this.ctx.arc(this.xCentre - dxYeux, yYeux, this.rayon * 0.1, 0, Math.PI * 2, false);
		this.ctx.stroke();
	}

	/**
	 * fait effectuer au visage un déplacement élémentaire. Lorsque le visage
	 * atteint l'un des côtés du canvas où il se situe, il rebondit en inversant
	 * son déplacement horizontal si le bord gauche ou droit du canvas est touché
	 * et en inversant son déplacement vertical si le bord haut ou le bord
	 * bas du canvas est touché.
	 *
	 *  @returns {boolean} true si le Visage à tocuhé un bord et doit changer de direction
	 *   false sinon
	 */
	deplacer() {
		this.xCentre += this.vx;
		this.yCentre += this.vy;
		let bordTouche = false;
		if (this.xCentre < this.rayon || this.xCentre > this.canvas.width - this.rayon) {
			// bord gauche ou bord droit du canvas atteint
			this.vx = -this.vx;
			bordTouche = true;
		}
		if (this.yCentre < this.rayon || this.yCentre > this.canvas.height - this.rayon) {
			// bord haut ou bord bas du canvas atteint
			this.vy = -this.vy;
			bordTouche = true;
		}
		return bordTouche;
	}
}
