var RubiksCubeConsole = Class.create({
	initialize: function(rootElementId, loadMovesListPanel) {
		this.colors = new Array(
	        "#FFFFFF", "#FFFF00", "#FF6020", "#D00000", "#009000", "#2040D0",
	        "#B0B0B0", "#505050", "#808080", "#FFA0C0", "#00FFFF", "#FF8040",
	        "#FF00FF", "#20FF10", "#000000", "#999999", "#AAAA44", "#BB7744",
	        "#994444", "#447744", "#004477", "#FF0000", "#00FF00", "#0000FF"
	    );
		
		this.letters = new Array(
	        "w", "y", "o", "r", "g", "b", "l", "d", ".", "p", "c", "0",
	        "m", "n", "k", "4", "5", "6", "7", "8", "9", "1", "2", "3"
	    );
		
		this.facelets = "wwwwwwwwwyyyyyyyyygggggggggbbbbbbbbbooooooooorrrrrrrrr";
		this.selectedColor = 0;
		this.selectedColorElement = undefined;
		this.faceletsStringOutputElement = undefined;
		this.movesListOutputElement = undefined;
		this.imageBaseURL = "/CubeImageA?";
		
		this.image = new Image();
		this.realImage = new Image(400, 389);
		
		this.rootElementId = rootElementId;
		this.messageBar = this.createMessageBar();
		this.updateMessageBar("Loading application...");
		this.palette = this.createPalette();
		this.loadMovesListPanel = loadMovesListPanel;
		
		$(rootElementId).insert(this.createFaceletsStringOutput());
		
		if (loadMovesListPanel)
			$(rootElementId).insert(this.createMovesListOutput());
		$(rootElementId).insert(this.palette);
		$(rootElementId).insert(this.messageBar);
		$(rootElementId).insert(this.createImageBlock());
		
		this.updateMessageBar("Ready.");
	},
	
	reset: function() {
		this.facelets = "wwwwwwwwwyyyyyyyyygggggggggbbbbbbbbbooooooooorrrrrrrrr";
        this.updateImage();
        this.updateFaceletsStringOutput(this.facelets);
	},
	
	decolor: function() {
		this.facelets = "......................................................";
        this.updateImage();
        this.updateFaceletsStringOutput(this.facelets);
	},
	
	setColor: function(color) {
		this.selectedColor = color;
		this.selectedColorElement.style.backgroundColor = this.colors[this.selectedColor];
	},
	
	scrambleCube: function() {
		this.updateFaceletsStringOutput("Scrambling...");
        new Ajax.Request('/ajax/functions/scramble_cube.jsp', {
            method: 'post',
            parameters: {
                facelets: this.facelets
            },
            onSuccess: function(transport) {
                var response = transport.responseText.evalJSON();
                this.facelets = response.scrambledFacelets;
                this.updateImage();
                this.updateFaceletsStringOutput(this.facelets);
            }.bind(this)
        });
    },
    
    loadFacelets: function() {
    	this.facelets = this.getFaceletsStringOutput();
    	this.updateImage();
    },
    
    setFacelets: function(facelets) {
    	this.facelets = facelets;
    	this.updateFaceletsStringOutput(facelets);
    	this.updateImage();
    },
    
    executeMoves: function() {
    	this.updateFaceletsStringOutput("Executing moves...");
    	
        var moves = this.getMovesListOutput();
        
        new Ajax.Request('/ajax/functions/execute_moves.jsp', {
            method: 'post',
            parameters: {
                facelets: this.facelets,
                moves: moves
            },
            onSuccess: function(transport) {
                var response = transport.responseText.evalJSON();
                this.facelets = response.returnFacelets;
                this.updateImage();
                this.updateFaceletsStringOutput(this.facelets);
            }.bind(this)
        });
    },
    
    showApplet: function() {
        var s = "/javacube/composition.jsp?";
        s += "init=" + this.getFaceletsStringOutput();
        s += "&moves=" + escape(this.getMovesListOutput());

        w = 300;
        h = 319;
        window.open(s, 'RubikShow', 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=yes, width=' + (w + 50) + ', height=' + (h + 31));
    },
    
    applyAlgorithm: function(algorithm) {
    	this.updateFaceletsStringOutput("Applying algorithm...");
        new Ajax.Request('/ajax/functions/apply_algorithm.jsp', {
            method: 'post',
            parameters: {
                facelets: this.facelets,
                algorithm: algorithm
            },
            onSuccess: function(transport) {
                var response = transport.responseText.evalJSON();
                this.updateMovesListOutput(response.moves);
                this.updateFaceletsStringOutput(this.facelets);
            }.bind(this)
        });
    },

	createImageBlock: function() {
		var coords = new Array(
			"95,84, 126,72, 156,87, 125,100",
	        "133,103, 164,89, 193,103, 163,117",
	        "169,121, 201,106, 230,121, 201,136",
	        "132,70, 163,58, 194,71, 163,84",
	        "170,87, 201,74, 230,87, 200,101",
	        "207,104, 237,89, 268,103, 237,118",
	        "170,56, 200,43, 230,55, 201,68",
	        "208,71, 237,58, 268,70, 238,84",
	        "245,87, 275,72, 305,85, 275,100",
	        "103,329, 132,314, 160,331, 132,347",
	        "137,312, 166,297, 194,312, 166,328",
	        "171,294, 200,280, 230,294, 201,310",
	        "138,350, 166,335, 194,352, 166,368",
	        "171,332, 201,316, 229,331, 201,348",
	        "206,313, 235,297, 263,312, 234,328",
	        "171,372, 200,355, 229,372, 200,389",
	        "206,352, 234,335, 264,351, 235,368",
	        "241,332, 269,314, 298,329, 269,347",
	        "92,90, 123,105, 124,142, 94,127",
	        "95,134, 125,149, 126,187, 97,170",
	        "98,178, 127,195, 128,231, 100,213",
	        "129,108, 160,123, 161,161, 130,145",
	        "131,153, 161,169, 162,207, 132,190",
	        "133,198, 162,215, 163,252, 134,235",
	        "166,126, 197,141, 198,180, 166,164",
	        "167,172, 197,187, 198,228, 168,211",
	        "169,219, 197,235, 197,273, 169,256",
	        "369,28, 400,41, 398,77, 368,65",
	        "367,72, 397,84, 395,121, 366,107",
	        "365,114, 395,128, 393,165, 364,150",
	        "332,14, 363,26, 362,62, 331,49",
	        "331,56, 362,69, 360,105, 330,91",
	        "330,98, 359,111, 358,147, 329,133",
	        "295,0, 326,11, 325,46, 295,34",
	        "295,41, 325,53, 324,88, 295,75",
	        "312,90, 324,95, 323,129, 309,123",
	        "0,41, 31,29, 32,64, 2,77",
	        "37,26, 68,14, 69,49, 38,62",
	        "74,11, 105,0, 105,34, 75,46",
	        "2,85, 32,72, 34,108, 5,121",
	        "38,69, 69,56, 70,91, 40,105",
	        "75,53, 105,41, 105,74, 76,88",
	        "5,128, 35,114, 36,151, 7,165",
	        "41,111, 70,98, 71,133, 42,147",
	        "76,95, 89,90, 91,123, 77,129",
	        "203,180, 204,141, 234,127, 233,165",
	        "203,189, 233,173, 233,211, 203,227",
	        "203,235, 232,219, 232,256, 203,273",
	        "241,123, 271,107, 269,145, 240,160",
	        "239,169, 270,153, 268,190, 239,207",
	        "238,215, 268,198, 266,235, 237,252",
	        "278,105, 308,90, 306,127, 276,142",
	        "276,149, 306,133, 304,170, 274,188",
	        "274,194, 303,177, 301,214, 272,232"
		);
		
		
		var imageBlock = new Element("div", { "align": "center" });
		
		var map = new Element("map", { "name": "faceletsMap" });
		
		for (var i = 0; i < coords.length; i++) {
			var area = new Element("area", { "shape": "poly" });
			
			area.observe("click", function(e) {
				var data = $A(arguments);
		    	data.shift();
		    	var facelet = data[0];
		    	this.facelets = this.facelets.substring(0, facelet) + this.letters[this.selectedColor] + this.facelets.substring(facelet + 1);
		        this.updateImage();
		        this.updateFaceletsStringOutput(this.facelets);
			}.bindAsEventListener(this, i));
			
			area.setAttribute("shape", "poly");
			area.setAttribute("coords", coords[i]);
			area.setAttribute("href", "javascript:void(0);");
			
			// IE7
			//area.shape = "poly";
			//area.href = "javascript:void(0);";
			//area.coords = coords[i];
			
			map.insert(area);
		}
		
		this.image = new Element("img", {
			"width": "400",
			"height": "393",
			"src": "/CubeImageA?facelets=wwwwwwwwwyyyyyyyyygggggggggbbbbbbbbbooooooooorrrrrrrrr",
			"useMap": "#faceletsMap"
		});
		
		imageBlock.insert(map);
		imageBlock.insert(this.image);
		
		
		return imageBlock;
	},
	
	updateFaceletsStringOutput: function(facelets) {
		this.faceletsStringOutputElement.value = facelets;
	},
	
	getFaceletsStringOutput: function() {
		return this.faceletsStringOutputElement.value;
	},
	
	updateMovesListOutput: function(movesList) {
		this.movesListOutputElement.value = movesList;
	},
	
	getMovesListOutput: function() {
		return this.movesListOutputElement.value;
	},
	
	updateImage: function() {
		this.updateMessageBar("Loading image...");
		this.realImage = new Image(400, 389);
		this.realImage.onload = function() {
        	this.image.src = this.realImage.src;
        	this.updateMessageBar("Ready.");
		}.bind(this);
        this.realImage.src = this.imageBaseURL + "facelets=" + this.facelets;
	},
	
	createMessageBar: function() {
		var messageBar = new Element("div");
		messageBar.setStyle({
	        textAlign: 'center',
	        marginTop: '10px'
	    });
		return messageBar;
	},
	
	updateMessageBar: function(text) {
		this.messageBar.update(text);
	},
	
	createFaceletsStringOutput: function() {
		var faceletsStringOutput = new Element("div").setStyle({ marginBottom: "10px" });
		
		faceletsStringOutput.insert(
			new Element("div").insert("Facelets string:")
		);
		
		this.faceletsStringOutputElement = new Element("input", { "type": "text" }).setStyle({ width: "100%" });
		
		faceletsStringOutput.insert(
			new Element("div").insert(
				this.faceletsStringOutputElement
			)
		);
		
		var divElement = new Element("div", { "style": "text-align: center; margin-top: 3px;" });
		divElement.insert(new Element("input", { "type": "button", "value": "Scramble" }).observe("click", function(e) {
			this.scrambleCube();
		}.bindAsEventListener(this)));
		
		divElement.insert(new Element("input", { "type": "button", "value": "Load facelets" }).observe("click", function(e) {
			this.loadFacelets();
		}.bindAsEventListener(this)));
		
		faceletsStringOutput.insert(divElement);
		
		this.updateFaceletsStringOutput(this.facelets);
		
		return faceletsStringOutput;
	},
	
	createMovesListOutput: function() {
		var movesListOutput = new Element("div").setStyle({ marginBottom: "10px" });
		
		movesListOutput.insert(
			new Element("div").insert("Moves list:")
		);
		
		this.movesListOutputElement = new Element("textarea").setStyle({ width: "100%", height: "80px" });
		
		movesListOutput.insert(
			new Element("div").insert(
				this.movesListOutputElement
			)
		);
		
		var divElement = new Element("div", { "style": "text-align: center; margin-top: 3px;" });
		divElement.insert(new Element("input", { "type": "button", "value": "Show applet" }).observe("click", function(e) {
			this.showApplet();
		}.bindAsEventListener(this)));
		
		divElement.insert(new Element("input", { "type": "button", "value": "Execute moves" }).observe("click", function(e) {
			this.executeMoves();
		}.bindAsEventListener(this)));
		/*
		divElement.insert(new Element("input", { "type": "button", "value": "Solve the Cross" }).observe("click", function(e) {
			this.applyAlgorithm("cross");
		}.bindAsEventListener(this)));
		
		divElement.insert(new Element("input", { "type": "button", "value": "Solve pbf_e0e1e2e3_c0c2c3" }).observe("click", function(e) {
			this.applyAlgorithm("pbf_e0e1e2e3_c0c2c3");
		}.bindAsEventListener(this)));
		
		divElement.insert(new Element("input", { "type": "button", "value": "Solve pbf_e0e1e2e3c0c2c3_e8e10e11" }).observe("click", function(e) {
			this.applyAlgorithm("pbf_e0e1e2e3c0c2c3_e8e10e11");
		}.bindAsEventListener(this)));
		
		divElement.insert(new Element("input", { "type": "button", "value": "Solve pbf_e0e1e2e3c0c2c3e8e10e11_c1" }).observe("click", function(e) {
			this.applyAlgorithm("pbf_e0e1e2e3c0c2c3e8e10e11_c1");
		}.bindAsEventListener(this)));
		
		divElement.insert(new Element("input", { "type": "button", "value": "Solve pbf_e0e1e2e3c0c1c2c3e8e10e11_e9" }).observe("click", function(e) {
			this.applyAlgorithm("pbf_e0e1e2e3c0c1c2c3e8e10e11_e9");
		}.bindAsEventListener(this)));
		
		divElement.insert(new Element("input", { "type": "button", "value": "Solve pbf_e0e1e2e3c0c1c2c3e8e9e10e11_e4e5e6e7" }).observe("click", function(e) {
			this.applyAlgorithm("pbf_e0e1e2e3c0c1c2c3e8e9e10e11_e4e5e6e7");
		}.bindAsEventListener(this)));
		
		divElement.insert(new Element("input", { "type": "button", "value": "Solve pbf_e0e1e2e3c0c1c2c3e8e9e10e11e4e5e6e7_c4c5c6c7" }).observe("click", function(e) {
			this.applyAlgorithm("pbf_e0e1e2e3c0c1c2c3e8e9e10e11e4e5e6e7_c4c5c6c7");
		}.bindAsEventListener(this)));
		*/
		
		divElement.insert(new Element("input", { "type": "button", "value": "Solve PBF" }).observe("click", function(e) {
			this.applyAlgorithm("pbf");
		}.bindAsEventListener(this)));
		
		divElement.insert(new Element("input", { "type": "button", "value": "Solve the Cube!" }).observe("click", function(e) {
			this.applyAlgorithm("lbl");
		}.bindAsEventListener(this)));
		
		movesListOutput.insert(divElement);
		
		return movesListOutput;
	},
	
	createPalette: function() {
		var palette = new Element("div");
		palette.setAttribute("align", "center");
		palette.setStyle({
			align: 'center'
	    });
		
		var tableElement = new Element("table");
		tableElement.setStyle({
	        borderSpacing: '2px',
	        padding: '0',
	        border: '0',
	        backgroundColor: '#000000'
	    });
		
		var tBody = new Element("tbody");
		
		var k = 0;
		for (var i = 0; i < 2; i++) {
			var trElement = new Element("tr");
			
			for (var j = 0; j < 12; j++) {
				var tdElement = new Element("td");
				tdElement.setAttribute("width", "25");
				tdElement.setAttribute("height", "25");
				tdElement.setAttribute("bgcolor", this.colors[k]);
				tdElement.setStyle({
			        backgroundColor: this.colors[k]
			    });
				
				tdElement.observe("click", function(e) {
					var data = $A(arguments);
			    	data.shift();
			    	this.setColor(data[0]);
				}.bindAsEventListener(this, k));
				
				var aElement = new Element("a");
				aElement.setAttribute("href", "javascript:void(0);");
				
				var imgElement = new Element("img");
				
				imgElement.setAttribute("width", "25");
				imgElement.setAttribute("height", "25");
				imgElement.setAttribute("border", "0");
				imgElement.setAttribute("src", "/img/layout/clear.gif");
				imgElement.setStyle({
			        width: "25",
			        height: "25"
			    });
				
				aElement.insert(imgElement);
				
				tdElement.insert(aElement);
				trElement.insert(tdElement);
				
				k++;
			}
			
			tBody.insert(trElement);
		}
		
		tableElement.update(tBody);
		palette.update(tableElement);
		
		// La parte pulsanti
		var tableElement2 = new Element("table");
		var tBodyElement2 = new Element("tbody");
		var trElement2 = new Element("tr");
		var tdElement2_1 = new Element("td").update("Selected color:");
		
		this.selectedColorElement = new Element("td", { "width": "12", "height": "12", "style": "background-color: #FFFFFF;" }).update(
				new Element("img", { "width": "12", "height": "12", "border": "0", "src": "/images/clear.gif" })
		);
		
		var tableElement3 = new Element("table").update(
			new Element("tbody").update(
				new Element("tr").update(
					this.selectedColorElement
				)
			)
		);
		tableElement3.setStyle({
	        borderSpacing: '2px',
	        padding: '0',
	        border: '0',
	        backgroundColor: '#000000'
	    });

		var tdElement2_2 = new Element("td").update(tableElement3);
		
		trElement2.insert(tdElement2_1);
		trElement2.insert(tdElement2_2);
		
		trElement2.insert(
			new Element("td").update(
				new Element("input", { "type": "button", "value": "Reset" }).observe("click", function(e) {
					this.reset();
				}.bindAsEventListener(this))
			)
		);
		
		trElement2.insert(
			new Element("td").update(
				new Element("input", { "type": "button", "value": "Decolor" }).observe("click", function(e) {
					this.decolor();
				}.bindAsEventListener(this))
			)
		);
		
		tBodyElement2.insert(trElement2);
		
		tableElement2.insert(tBodyElement2);
		
		palette.insert(tableElement2);
		
		return palette;
	}
});

