import java.util.LinkedList;

public class RandomWall {
	Integer width; // largeur du mur
	CountWall countWall; // champ contenant la liste des rangées possibles, et permettant de calculer les nombres de murs dont la première rangée est row
	LinkedList<Integer> rows; // liste des rangées du mur, de bas en haut, représentées par des entiers 

	/** fill(row, height) : construit un mur aléatoire uniforme de hauteur height dont la première rangée est row, en stockant les rangées dans rows */
	void fill(int row, int height) {
        this.rows.push(row);
		if(height > 1) {
			// on choisit aléatoirement la ligne suivante avec la distribution de probabilité donnée par la fonction count
			int nextRow = 0;
			long n = (long) (Math.random() * this.countWall.count(row, height));
			for(Integer s: this.countWall.allrows) {
				if((row & s) == 0) {
					n -= this.countWall.count(s, height-1);
					if(n <= 0) { nextRow = s; break; }				
				}
			}
			// on tire ensuite récursivement un mur de hauteur height-1 et dont la première ligne est nextRow
			this.fill(nextRow, height-1);
		}
	}

	/** randomWall(height) : construit un mur aléatoire uniforme de largeur width et de hauteur height */
	RandomWall(int width, int height) {
		this.width = width;
		this.countWall = new CountWall(width);
		int row = 0;
		long n = (long) (Math.random() * countWall.count(height));
		for(Integer s: countWall.allrows) {
			n -= countWall.count(s, height);
			if(n <= 0) { row = s; break; }				
		}
		this.rows = new LinkedList<Integer>();
		this.fill(row, height);
	}

	/** toString : affiche un mur aléatoire */
	public String toString() {
		if(this.width == null) throw new Error("Impossible to print a wall without its width!");
		String result = "";
		for(Integer row : rows) {
			// on fait attention à la brique de gauche ...
			result = "|\n" + result;
			row = row >> 1;
			for(int i = 0; i < this.width - 1; i++) {
				if((row & 1) == 1) result = "_|_" + result; else result = "___" + result;
				row = row >> 1;
			}
			// ... et à celle de droite
			result = "|" + result;
		}
		result = "\n" + result;
		for(int i = 0; i < 3 * this.width - 3; i++) result = "_" + result;
		result = " " + result;
		return result;
	}


}
