function Cell(centre, side, coloring) {
	var halfSide = side / 2;
	this.centre = centre;
	this.bottomLeft = centre.shift(-halfSide, halfSide);
	this.bottomRight = centre.shift(halfSide, halfSide);
	this.topLeft = centre.shift(-halfSide, -halfSide);
	this.topRight = centre.shift(halfSide, -halfSide);
	this.coloring = coloring;
	this.neighbours = {};
	this.id = ++Cell.ID;
}

var COLOURS = [ "#000000", "#C17D11", "#CC0000", "#F57900", "#EDD400", "#73D216", "#3465A4", "#75507B", "#BABDB6", "#FFFFFF" ]; 

Cell.RELATIONSHIP_OPPOSITES = {north: "south", east: "west", south: "north", west: "east"};
Cell.ID = 0;

Cell.prototype.toString = function() {
	return "{Cell: "+this.id+"}";
}

Cell.prototype.setNeighbour = function(relationship, cell) {
	this.neighbours[relationship] = cell;
	if (cell != null) {
		cell.neighbours[Cell.RELATIONSHIP_OPPOSITES[relationship]] = this;
	}
}

Cell.prototype.matchesNeighbours = function() {
	if (this.coloring == null) {
		return true;
	}
	for (rel in this.neighbours) {
		var matchingNeighbour = this.neighbours[rel];
		if (matchingNeighbour != null) {
			var matchingNeighbourColoring = this.neighbours[rel].coloring;
			if (matchingNeighbourColoring != null) {
				if (this.neighbours[rel].coloring[Cell.RELATIONSHIP_OPPOSITES[rel]] != this.coloring[rel]) {
					return false;
				}
			}
		}
	}
	return true;
}

Cell.prototype.swap = function(otherCell) {
	var tmp = this.coloring;
	this.coloring = otherCell.coloring;
	otherCell.coloring = tmp;

	if (this.matchesNeighbours() == false || otherCell.matchesNeighbours() == false) {
		// Not legal, swap back.
		otherCell.coloring = this.coloring;
		this.coloring = tmp;
		return false;
	}
	return true;
}

Cell.prototype._barycentre = function(p1, p2, p3) {
	return new P((p1.x + p2.x + p3.x) / 3, (p1.y + p2.y + p3.y) / 3);
}

Cell.prototype._drawTri = function(g, p1, p2, p3, colorNo) {
	g.fillStyle = COLOURS[colorNo];
	g.strokeStyle = 'white';
	g.lineWidth = 0.5;
	g.beginPath();
	p1.moveTo(g);
	p2.lineTo(g);
	p3.lineTo(g);
	g.closePath();
	g.fill();
	g.stroke();
	if (colorNo < 4 || colorNo==6 || colorNo == 7) {
		g.fillStyle = "white";
	} else {
		g.fillStyle = "black";
	}
	g.font = "11px sans-serif";
	g.textBaseline = "middle";
	g.textAlign = "center";
	var bary = this._barycentre(p1, p2, p3);
	g.fillText(colorNo, bary.x, bary.y);
}

Cell.prototype.renderBorder = function(g, inset) {
	if (inset == null) {
		inset = 0;
	}
	g.beginPath();
	g.moveTo(this.topLeft.x + inset, this.topLeft.y + inset);
	g.lineTo(this.topRight.x - inset, this.topRight.y + inset);
	g.lineTo(this.bottomRight.x - inset, this.bottomRight.y - inset);
	g.lineTo(this.bottomLeft.x + inset, this.bottomLeft.y - inset);
	g.closePath();
}

Cell.prototype.render = function(g, isSelected) {
	g.fillStyle = "white";
	g.beginPath();
	g.fillRect(this.topLeft.x - 2, this.topLeft.y - 2, this.topRight.x - this.topLeft.x + 4, this.bottomRight.y - this.topRight.y + 4);
	
	if (this.coloring != null) {
		this._drawTri(g, this.centre, this.topLeft, this.topRight, this.coloring.north);
		this._drawTri(g, this.centre, this.topRight, this.bottomRight, this.coloring.east);
		this._drawTri(g, this.centre, this.bottomRight, this.bottomLeft, this.coloring.south);
		this._drawTri(g, this.centre, this.bottomLeft, this.topLeft, this.coloring.west);		
	}

	if (isSelected) {
		g.strokeStyle = "red";
		g.lineWidth = 1.5;
		g.beginPath();
		g.strokeRect(this.topLeft.x - 1, this.topLeft.y - 1, this.topRight.x - this.topLeft.x + 2, this.bottomRight.y - this.topRight.y + 2);
	} else {
		g.strokeStyle = "#c0c0c0";
		g.lineWidth = 1;
		g.beginPath();
		g.strokeRect(this.topLeft.x - 1, this.topLeft.y - 1, this.topRight.x - this.topLeft.x + 2, this.bottomRight.y - this.topRight.y + 2);
	}
}

Cell.prototype.contains = function(p) {
	return (p.x > this.topLeft.x && p.x < this.topRight.x && p.y > this.topLeft.y && p.y < this.bottomLeft.y); 
}

