var QPlace = function(template) {
	this.node = document.createElement("form");
	this.nodePanel = document.createElement("div");
	this.nodeImg = document.createElement("img");
	this.nodeStock = document.createElement("div");
	this.result = new ExerciceResult();

	this.items = [];
	this.targets = [];
	this.drag = null;
	this.debug = (template.getAttribute("debug") == "true");
	this.shuffle = (template.getAttribute("shuffle") != "false");
	this.init(template);
};

QPlace.prototype.selectTarget = function(item) {
	var result = null;
	var distance = null;
	for (var i = 0; i < this.targets.length; i++) {
		var target = this.targets[i];
		var d = target.distanceFrom(item.node);
		if (!result || d < distance) {
			distance = d;
			result = target;
		}
	}
	return distance && distance < 64 ? result : null;
};

QPlace.prototype.getErrorItem = function() {
	for (var i = 0; i < this.items.length; i++) {
		var item = this.items[i];
		if (!item.value())
			return item;
	}
	return null;
};

QPlace.prototype.associated = function() {
	for (var i = 0; i < this.items.length; i++) {
		var item = this.items[i];
		if (!item.associated())
			return false;
	}
	return true;
};

QPlace.prototype.append = function(item) {
	this.items.push(item);
	this.nodeStock.appendChild(item.node);

	this.targets.push(item.target);
	this.nodePanel.appendChild(item.target.node);
};

QPlace.prototype.setPos = function(node, x, y) {
	this.nodePanel.appendChild(node);
	node.style.left = x + "px";
	node.style.top = y + "px";
	node.style.position = "absolute";
};

QPlace.prototype.shuffleChilds = function(parent) {
	var nodes = [];
	for (var node = parent.firstChild; node != null; node = node.nextSibling) {
		nodes.push(node);
	}
	nodes.shuffle();
	for (var i = 0; i < nodes.length; i++) {
		parent.appendChild(nodes[i]);
	}
};

QPlace.prototype.init = function(template) {
	var self = this;
	this.node.className = "qplace";
	if (this.debug) this.node.style.cursor = "crosshair";

	this.nodePanel.className = "panel";
	this.nodePanel.appendChild(this.nodeImg);
	this.nodeImg.src = template.getAttribute("image");

	this.nodePanel.appendChild(this.nodeStock);
	this.nodeStock.className = "stock";

	var items = document.getChildsByTagName(template, "item");
	for (var i = 0; i < items.length; i++) {
		var item = new QPlaceItem(this, items[i]);
		this.append(item);
	}
	if (this.shuffle) this.shuffleChilds(this.nodeStock);

	this.nodePanel.onmousemove = function(e) { self.onmousemove(e); }
	this.nodePanel.onmouseup = function(e) { self.onmouseup(e); }
	this.node.appendChild(this.nodePanel);

	//bouton
	var button = document.createElement("button");
	button.appendChild(document.createTextNode("Ok"));
	this.node.appendChild(button);

	this.node.appendChild(this.result.node);
	this.node.onsubmit = function() { self.onsubmit(); return false; };
};

QPlace.prototype.onmousemove = function(e) {
	if (this.debug) {
		var rect = this.node.getBoundingClientRect();
		console.log("(" + (e.clientX - rect.left) + ", " + (e.clientY - rect.top) + ")");
	}
	if (this.drag) this.drag.onmousemove(e);
};

QPlace.prototype.onmouseup = function(e) {
	if (this.drag) this.drag.stop();
	this.drag = null;
};

QPlace.prototype.onmousedown = function(item, e) {
	if (!this.drag)	this.drag = new QPlaceItemDrag(item, e);
};

QPlace.prototype.onsubmit = function() {
	var associated = this.associated();
	if (!associated) {
		this.result.set(false, "Vous devez placer tous les items !");
		return;
	}

	var item = this.getErrorItem();
	if (item) {
		this.result.set(false, item.msg ? item.msg : "Pas tout à fait");
		return;
	}

	this.result.set(true, "Bravo !");
};

//---QPlaceItem
QPlaceItem = function(parent, template) {
	this.parent = parent;
	this.node = document.createElement("div");
	this.drag = null;
	this.msg = template.getAttribute("message");
	this.target = new QPlaceTarget(parseInt(template.getAttribute("x")), parseInt(template.getAttribute("y")), template.getAttribute("align"));
	this.setAssocTarget(null);
	this.init(template);
};

QPlaceItem.prototype.setAssocTarget = function(target) {
	this.assocTarget = target;
	if (target) {
		this.setBasePos(target.x, target.y, target.align);
	}
};

QPlaceItem.prototype.value = function() {
	return this.target == this.assocTarget;
};

QPlaceItem.prototype.associated = function() {
	return this.assocTarget != null;
};

QPlaceItem.prototype.setBasePos = function(x, y, align) {
	var rect = this.node.getBoundingClientRect();
	var coord = false;

	switch (align) {
	case "bottom":
		coord = [x - rect.width / 2, y];
		break;

	case "top":
		coord = [x - rect.width / 2, y - rect.height];
		break;

	case "right":
		coord = [x, y - rect.height / 2];
		break;

	case "left":
		coord = [x - rect.width, y - rect.height / 2];
		break;

	case "middle":
	default:
		coord = [x - rect.width / 2, y - rect.height / 2];
		break;
	}

	if (coord) this.setPos(coord[0], coord[1]);
};

QPlaceItem.prototype.setPos = function(x, y) {
	this.x = x;
	this.y = y;
	this.parent.setPos(this.node, x, y);
};

QPlaceItem.prototype.selectTarget = function() {
	return this.parent.selectTarget(this);
};

QPlaceItem.prototype.init = function(template) {
	var self = this;
	this.node.className = "item";
	document.moveChilds(template, this.node);
	this.node.onmousedown = function(e) { self.onmousedown(e); }
};

QPlaceItem.prototype.onmousedown = function(e) {
	this.parent.onmousedown(this, e);
};

//--- QPlaceTarget
var QPlaceTarget = function(x, y, align) {
	this.x = x;
	this.y = y;
	this.align = align ? align : "bottom";
	this.node = document.createElement("div");
	this.init();
};

QPlaceTarget.prototype.init = function() {
	this.setActivated(false);
	this.node.style.left = this.x + "px";
	this.node.style.top = this.y + "px";
	this.node.style.position = "absolute";
};

QPlaceTarget.prototype.setActivated = function(value) {
	this.node.className = value ? "target selected" : "target";
};

QPlaceTarget.prototype.distanceFrom = function(node) {
	var rect = this.node.getBoundingClientRect();
	rectX = rect.left + rect.width / 2;
	rectY = rect.top + rect.height / 2;

	var rectFrom = node.getBoundingClientRect();
	rectFromX = rectFrom.left + rectFrom.width / 2;
	rectFromY = rectFrom.top + rectFrom.height / 2;

	return Math.sqrt(Math.pow(rectFromX - rectX, 2) + Math.pow(rectFromY - rectY, 2));
};

//--- QPlaceItemDrag
var QPlaceItemDrag = function(item, e) {
	item.setAssocTarget(null);
	this.target = null;
	this.item = item;
	this.fromX = e.clientX;
	this.fromY = e.clientY;
	var rectItem = item.node.getBoundingClientRect();
	var rectParent = item.parent.node.getBoundingClientRect();
	this.x = rectItem.left - rectParent.left;
	this.y = rectItem.top - rectParent.top;
};

QPlaceItemDrag.prototype.onmousemove = function(e) {
	this.item.setPos(this.x + e.clientX - this.fromX, this.y + e.clientY - this.fromY);
	this.setTarget(this.item.selectTarget())
};

QPlaceItemDrag.prototype.setTarget = function(target) {
	if (this.target) {
		this.target.setActivated(false);
		this.target = null;
	}
	if (target) {
		target.setActivated(true);
		this.target = target;
	}
}

QPlaceItemDrag.prototype.stop = function() {
	this.item.setAssocTarget(this.target);
	if (this.target) this.item.setAssocTarget(this.target);
	this.setTarget(null);
}
