// list of destinations
var destinations = [{
	name: "SOUTHSIDE",
	num: 0,
}, {
	name: "FRANCE",
	num: 0,
}, {
	name: "TADS",
	num: 0,
}, {
	name: "SAVOYS",
	num: 0,
}, {
	name: "PIZZA",
	num: 0,
}, {
	name: "KITCHEN",
	num: 0,
}, ];

var title = "FOODICATOR: RELOADED";
var titlefont = "40px Arial";
var destfont = "25px Arial";
var winningfont = "30px Arial";

// to block until ready
var ready = false;

// My ID
var myId;

// List of other players
var playerList = {};

// Set up the eureca server
var eurecaServer;

// Client setup function
var eurecaClientSetup = function() {

	// create an instance of eureca.io client
	var eurecaClient = new Eureca.Client();

	// Ready function for getting the server
	eurecaClient.ready(function(proxy) {
		eurecaServer = proxy;
	});

	// export functions can be called on the server side

	// Handshake function to hand over ID
	eurecaClient.exports.handshake = function(id) {
		//create() is moved here to make sure nothing is created before uniq id assignation
		myId = id;
		create();

		state = {
			x: player.sprite.x,
			y: player.sprite.y
		}
		eurecaServer.updateMe(state);

		ready = true;
	}

	// close a connection
	eurecaClient.exports.kill = function(id) {
		var pl = playerList[id];
		// if we have this player
		if (pl) {

			// Kill the player and log
			pl.kill();
			console.log(id, " disconnected ", pl);
		}
	}

	// Spawn another player
	eurecaClient.exports.spawnPlayer = function(i, x, y) {

		if (i === myId) return; // do nothing for me

		// log and create the player
		console.log(i, " connected");
		var player = new Player(i, x, y);

		// add to our list
		playerList[i] = player;
	}

	// Update a player state
	eurecaClient.exports.updateState = function(id, state) {
		if (id === myId) return; // do nothing for me

		var pl = playerList[id];

		// if we have this player update it's pos
		if (pl) {
			pl.sprite.x = state.x;
			pl.sprite.y = state.y;
		} else {
			// If we don't have it, we probably should so add it
			var player = new Player(id, state.x, state.y);

			// add to our list
			playerList[i] = player;
		}

	}
}

var width = 800;
var height = 540;

// Create the game
var game = new Phaser.Game(width, height,
	Phaser.AUTO,
	'', {
		preload: preload,
		create: eurecaClientSetup,
		update: update
	});


// get the length of a vector
function lengthV(vec) {
	return length(vec.x, vec.y);
}

function length(x, y) {
	return Math.sqrt((x * x) + (y * y));
}

// get the length of a vector
function distance(x1, y1, x2, y2) {
	return length(x1 - x2, y1 - y2);
}

// Normalise a vector
function normaliseV(vec) {
	var len = lengthV(vec);
	vec.x = (vec.x / len);
	vec.y = (vec.y / len);
}

// Player object
Player = function(id, x, y) {

	// Constants
	this.id = id;
	this.topSpeed = 5;
	this.acceleration = 2;
	this.friction = 0.6;
	this.alive = false;

	// varying
	this.velocity = {
		x: 0,
		y: 0
	};

	// Create a sprite
	this.sprite = game.add.sprite(x, y, 'dude');

	// set alive
	this.alive = true;
}

// Update a player
Player.prototype.update = function() {

	// early out if dead
	if (!this.alive) return;

	// control force
	var force = {
		x: 0.0,
		y: 0.0
	}

	// Grab the members, javascript is weird?
	var sprite = this.sprite;
	var velocity = this.velocity;
	var topSpeed = this.topSpeed;
	var acceleration = this.acceleration;
	var friction = this.friction;

	// Left and right
	if (controls.left.isDown) {
		//  Move to the left
		force.x = -1.0;
	} else if (controls.right.isDown) {
		//  Move to the right
		force.x = 1.0;
	}

	// Up and down
	if (controls.up.isDown) {
		//  Move up
		force.y = -1.0;
	} else if (controls.down.isDown) {
		//  Move down
		force.y = 1.0;
	}

	// normalise and apply acceleration
	if (lengthV(force) !== 0) normaliseV(force);
	force.x = force.x * acceleration;
	force.y = force.y * acceleration;

	// apply the force
	velocity.x += force.x;
	velocity.y += force.y;

	// apply friction when no force
	if (force.x === 0.0) {
		// if no force, then apply friction
		velocity.x = velocity.x * friction;
	}

	if (force.y === 0.0) {
		velocity.y = velocity.y * friction;
	}

	// limit speed
	if (lengthV(velocity) > 0.1) {

		// Limit to pos
		velocity.x = Math.min(velocity.x, topSpeed);
		velocity.y = Math.min(velocity.y, topSpeed);

		// Limit to neg
		velocity.x = Math.max(velocity.x, -topSpeed);
		velocity.y = Math.max(velocity.y, -topSpeed);
	} else { 
		velocity.x = 0.0;
		velocity.y = 0.0;
	}

	// set sprite position and update server
	if (lengthV(velocity) !== 0.0) {

		sprite.position.x = sprite.position.x + velocity.x;
		if (sprite.position.x < -50) sprite.position.x = width;
		if (sprite.position.x > width) sprite.position.x = -50;

		sprite.position.y = sprite.position.y + velocity.y;
		if (sprite.position.y < -50) sprite.position.y = height;
		if (sprite.position.y > height) sprite.position.y = -50;

		var state = {
			x: sprite.position.x,
			y: sprite.position.y
		}
		eurecaServer.updateMe(state)
	}
}

// Kill a player
Player.prototype.kill = function() {
	// The player and its settings
	this.sprite.kill();
	this.alive = false;
}

function createDests() {
	var minX = 0;
	var maxX = width - minX;
	var minY = 150;
	var maxY = height + 100;

	var len = destinations.length;

	// we need 3 columns max
	var numCols = 3;
	var numRows = len / numCols;

	var colsep = ((maxX - minX) * (1 / numCols));
	var rowsep = ((maxY - minY) * (1 / numRows));

	var num = 0;
	var row = 0;
	var col = 0;
	for (var i = 0; i < len; ++i) {
		var dest = destinations[i];

		var posX = minX + (colsep * col) + (colsep * 0.5);
		var posY = minY + (rowsep * row);

		// Create our destination text
		var destText = game.add.text(posX, posY, dest.name, {
			font: destfont,
			fill: "#FFFFFF"
		});
		destText.anchor.x = Math.round(destText.width * 0.5) / destText.width;

		// Add to our group
		textGroup.add(destText);
		dest.text = destText;

		// increment num, rows and cols
		num++;
		col = num % numCols;
		if (col === 0) row++;
	}
}


function updateDests() {

	var votingRange = 100;

	// Get number of voters
	var len = destinations.length
	for (var i = 0; i < len; ++i) {
		var dest = destinations[i];
		dest.num = 0;
		dest.vote = false;

		// For each external player
		for (var p in playerList) {
			var dist = distance(playerList[p].sprite.x, playerList[p].sprite.y, dest.text.x, dest.text.y);
			if (dist < votingRange) dest.num++;
		}

		// Add for the current player
		var dist = distance(player.sprite.x, player.sprite.y, dest.text.x, dest.text.y);
		if (dist < votingRange) {
			dest.num++;
			dest.vote = true;
		}
	}



	// Set the texts
	var winners = [];
	for (var i = 0; i < len; ++i) {
		var dest = destinations[i];
		dest.text.setText(dest.name + " HAS " + dest.num);

		// add to the array
		if ((winners.length === 0) || (dest.num == winners[0].num)) {
			winners.push(dest);
		} else if ((dest.num > winners[0].num)) // clear array and add
		{
			winners = [];
			winners.push(dest);
		}
	}

	var wintext;
	if (winners.length === 0) {
		wintext = "NO WINNER";
	} else if (winners.length === 1) {
		wintext = winners[0].name + " IS WINNINGS";
	} else {
		wintext = "DRAW BETWEEN " + winners[0].name;
		var left = winners.length;
		for (var i = 1; i < left; ++i) {
			wintext += " AND " + winners[i].name;
		}
	}

	winningText.setText(wintext);
}

// Phaser functions

// preload all assets
function preload() {

	// Set centered
	game.scale.pageAlignHorizontally = true;
	game.scale.pageAlignVertically = true;

	// load the background
	game.load.image("bg", "assets/bg.png");

	// Load the dude  
	game.load.image('dude', 'assets/dude.png', 50, 50);
}

// Create the game
function create() {

	// Add the background sprite
	var background = game.add.sprite(0, 0, "bg");

	// create our player
	player = new Player(myId, game.world.centerX + (25 - Math.random() * 50), game.world.centerY + (25 - Math.random() * 50));

	//  Get controls
	controls = game.input.keyboard.createCursorKeys();

	// Create the text group
	textGroup = game.add.group();

	// Create our title text
	var titleText = game.add.text(game.world.centerX, 20, title, {
		font: titlefont,
		fill: "#FFFFFF"
	});
	titleText.anchor.x = Math.round(titleText.width * 0.5) / titleText.width;

	// Add to our group
	textGroup.add(titleText);

	createDests();

	winningText = game.add.text(game.world.centerX, height - 60, "NO WINNER", {
		font: winningfont,
		fill: "#FFFFFF"
	});
	winningText.anchor.x = Math.round(winningText.width * 0.5) / winningText.width;
}

// On update
function update() {

	// do nothing if not ready yet
	if (!ready) return;

	// update our player
	player.update();

	// Bring the text group to the top
	game.world.bringToTop(textGroup);

	// Update our destinations
	updateDests();
}