var canvasSupportsText = document.createElement("canvas").getContext("2d").fillText;

function buttonFactory(container, caption, width, height, colorMap, action) {
	if (canvasSupportsText) {
		return new Button(container, caption, width, height, colorMap, action);
	} else {
		return fallbackButton(container, caption, action);
	}
}

function Button(container, caption, width, height, colorMap, action) {

	var button = this.button = document.createElement("canvas");
	button.width = width;
	button.height = height;
	var buttonContext = button.getContext("2d");
	container.appendChild(button);
	
	var buttonAction = this.action = action;
	var caption = caption;
	var span = 2;
	
	var useImage = caption.substr(0, 7) == "http://" || caption.substr(0, 1) == "/" || caption.substr(0, 2) == "./";
	var imageLoaded = false;
	this.isMouseDown = false;
	
	if (useImage) {
		var image = new Image();
		image.src = caption;
		image.onload = function() { imageLoaded = true; button.onmouseout();};
	} else {
		var fontColor = colorMap["font"]["color"];
		var fontStyle = colorMap["font"]["style"];
	}
			
	function draw(border, background) {
		
		buttonContext.beginPath();
		buttonContext.strokeStyle = border;

		var gradient = buttonContext.createLinearGradient(10, 4, 10, 20);
		gradient.addColorStop(1, background[0]);
		gradient.addColorStop(0, background[1]);
		buttonContext.fillStyle = gradient;
		
		var r = button.height/2 - span;
		buttonContext.arc(r+span, r+span, r, Math.PI/2, 3*Math.PI/2, false);
		buttonContext.lineTo(button.width-r-span, span);
		buttonContext.arc(button.width-r-span, r+span, r, 3*Math.PI/2, Math.PI/2, false);
		buttonContext.lineTo(r+span, 2*r+span);
		buttonContext.fill();
		buttonContext.stroke();
		buttonContext.closePath();
		if (useImage) {
			if (imageLoaded) buttonContext.drawImage(image, 0, 0);
		} else {
			buttonContext.fillStyle = fontColor;
			buttonContext.font = fontStyle;
			buttonContext.textAlign = "center";
			buttonContext.textBaseline = "middle";
			buttonContext.fillText(caption, button.width / 2 - 1, button.height / 2 + 1);
		}
	}
	
	button.onmouseover = function() {
		draw(colorMap.hover.border, colorMap.hover.bg);
	}
	
	button.onmouseout = function() {
		this.isMouseDown = false;
		draw(colorMap.def.border, colorMap.def.bg);
	}
	
	button.onmousedown = function() {
		this.isMouseDown = true;
		draw(colorMap.click.border, colorMap.click.bg);
	}
	
	button.onmouseup = function(btn){ 
		return function() {
			if (!this.isMouseDown) return;
			draw(colorMap.hover.border, colorMap.hover.bg);
			if (btn.action) btn.action();
		}
	}(this);

	if (!useImage) draw(colorMap.def.border, colorMap.def.bg);
}

function fallbackButton(container, caption, action) {
	var button = document.createElement("button");
	button.onclick = action;
	button.innerHTML = caption;
	container.appendChild(button);
	
	return button;
}

