var PORT = 8080;
var gameMode = true;

var allSockets = {};
var allPlayers = {};
var userCnt = 0;

var express = require('express');
var app = express();
app.use(express.static(__dirname + '/'));
var server = require('http').Server(app);
var io = require('socket.io')(server);
var map = require("./s_map.js");
var mapWidth = 20;
var mapHeight = 20;
var maxX = mapWidth * 32;
var maxY = mapHeight * 32;
var newmap = map.generateMap(mapWidth, mapHeight);
var cssMap = newmap["cssMap"];
var map = newmap["map"];
var utilMap = newmap["utilMap"];
var defaultMvnt = 2;

var items = [
	"boots1",
	"boots2",
	"boots3",
	"boots4",
	"boots5",
];

var itemPlayerChanges = {
	"boots1" : {
		changeMovementLand : 1,
		text : "Geschwindigkeit an Land +1"
	},
	"boots2" : {
		changeMovementLand : 2,
		text : "Geschwindigkeit an Land +2"
	},
	"boots3" : {
		changeMovementLand : 3,
		text : "Geschwindigkeit an Land +3"
	},
	"boots4" : {
		changeMovementLand : 4,
		text : "Geschwindigkeit an Land +4"
	},
	"boots5" : {
		changeMovementLand : 5,
		text : "Geschwindigkeit an Land +5"
	},
}

server.listen(PORT);

console.log("Pirate running on port:" + PORT);
io.on('connection', function (socket) {
	var playerActionTimer = null;
	userCnt++;
	console.log("New user", socket.id);
	allSockets[socket.id] = socket;
	allPlayers[socket.id] = {
		keys: {},
		x: 10,
		y: 10,
		mvnt: defaultMvnt,
		special: {},
		mode: 0, //0 = ship //1 foot
		items: {
			slot1: null,
			slot2: null,
			slot3: null
		} 
	};
	var player = allPlayers[socket.id];
	io.sockets.emit("newPlayer", {
		player: allPlayers[socket.id],
		id: socket.id,
		items: {
			slot1: null,
			slot2: null,
			slot3: null
		}
	});

	socket.on('disconnect', function () {
		userCnt--;
		delete allSockets[socket.id];
		delete allPlayers[socket.id];
		console.log("User Disconnected:", socket.id);
		io.sockets.emit("playerDisc", socket.id);
	});

	socket.on('getmap', function () {

		newmap["allPlayers"] = allPlayers;
		socket.emit("getmap", newmap);
	});

	socket.on('keyUp', function (key) {
		allPlayers[socket.id]["keys"][key] = false;
		if (key == 32) { //space
			player["action"] = false;
			if (playerActionTimer) {
				clearTimeout(playerActionTimer);
				playerActionTimer = null;
			}
			io.sockets.emit("stopAction", socket.id);
		}
	});

	socket.on('keyDown', function (key) {
		allPlayers[socket.id]["keys"][key] = true;
	});

	socket.on('actionKey', function (key) {
		var groundUnder = getGroundUnderPlayer(player["x"], player["y"]);
		if (player["mode"] == 0) { //ship
			if (groundUnder >= 1) { //its nearly land
				player["mode"] = 1;
				player["special"]["modechange"] = true;
			}
		} else {
			if (groundUnder <= 1) { //its water land
				player["mode"] = 0;
				player["special"]["modechange"] = true;
			}
		};
		console.log(player["mode"], groundUnder);
		var obj = getNearestObject(player["x"], player["y"]);
		if (obj) {
			obj["socketId"] = socket.id;
			if (playerActionTimer) {
				clearTimeout(playerActionTimer);
				playerActionTimer = null;
			}
			if (obj["name"] == "forest") {
				playerActionTimer = setTimeout(function () {
					utilMap[obj["mapY"]][obj["mapX"]] = "";
					io.sockets.emit("removeUtil", obj);
					socket.emit("stopAnimation", 2000);
				}, 2000); //2 Secs
				socket.emit("animation", 2000);
			} else if (obj["name"] == "treasure-closed") {
				playerActionTimer = setTimeout(function () {
					utilMap[obj["mapY"]][obj["mapX"]] = "treasure-open";
					obj["newName"] = "treasure-open";
					io.sockets.emit("replaceUtil", obj);
					socket.emit("stopAnimation", 2000);

					let randomItem = getRandomItem();
					let nearFieldCoords = getNearEmptyField(obj["mapX"], obj["mapY"]);

					utilMap[nearFieldCoords["y"]][nearFieldCoords["x"]] = randomItem;
					let newObj = {
						mapY: nearFieldCoords["y"],
						mapX: nearFieldCoords["x"],
						newName: randomItem
					}
					io.sockets.emit("dropItem", newObj);
					console.log("newObj", newObj)
					
				}, 2000); //2 Secs
				socket.emit("animation", 2000);
			}
			io.sockets.emit("objAction", obj);
		}
		player["action"] = true;
	});
});

function getNearEmptyField(x, y) {
	for(var i=-1;i<2;i++) {
		for(var k=-1;k<2;k++) {
			console.log("check",i, k, y+i, x+k, utilMap[y+i][x+k])
			if(utilMap[y+i][x+k] == "") {
				return {
					y : y+i,
					x : x+k
				}
			}
		}
	}
}

function getRandomItem() {
	console.log("rnd", items.length, getRandomNumber(0, items.length), items)
	return items[getRandomNumber(0, items.length)];
}

function getNearestObject(x, y) {
	var mapX = Math.floor(x / 32);
	var mapY = Math.floor(y / 32);
	var obj = null;
	if (utilMap[mapY][mapX] != "") {
		obj = {
			mapX: mapX,
			mapY: mapY,
			name: utilMap[mapY][mapX]
		}
	} else {
		var rX = x % 32;
		var rY = y % 32;
		var sX = 0;
		var sY = 0;
		if (rX > 6 && rX < 26) { //He stands in the middle of the field (left-><-right)
			if (rY < 16) { //go Up
				sY = -1;
			} else { //go Down
				sY = 1;
			}
		} else if (rY > 6 && rY < 26) { //He stands in the middle of the field (up-><-down)
			if (rX < 16) { //go left
				sX = -1;
			} else { //go right
				sX = 1;
			}
		}

		if (utilMap[mapY + sY][mapX + sX] != "") {
			obj = {
				mapY: mapY + sY,
				mapX: mapX + sX,
				name: utilMap[mapY + sY][mapX + sX]
			}
		}
	}

	return obj;

}

setInterval(function () {
	for (var id in allPlayers) {
		var player = allPlayers[id];
		for (var key in player["keys"]) {
			if (player["keys"][key]) { //if key is pressed
				var tx = 0;
				var ty = 0;

				var mvnt = player["mvnt"];
				if (key == 37) { //left
					tx = -1 * mvnt;
				} else if (key == 38) { //top
					ty = -1 * mvnt;
				} else if (key == 39) { //right
					tx = mvnt;
				} else if (key == 40) { //bottom
					ty = mvnt;
				}

				if (!player["action"]) {
					var newX = player["x"] + tx;
					var newY = player["y"] + ty;

					var groundUnderPlayer = getGroundUnderPlayer(newX, newY);
					if (checkPlayerPosition(newX, newY, groundUnderPlayer, player)) {
						player["x"] = newX;
						player["y"] = newY;
						player["mvnt"] = getPlayerMvnt(player, groundUnderPlayer);
					}
				}
			}
		}
	}
	io.sockets.emit("setpos", allPlayers);
	for (var id in allPlayers) {
		allPlayers[id]["special"] = {};
	}
}, 20);

function checkPlayerPosition(newX, newY, groundUnderPlayer, player) {
	if (newX < 0 || newY < 0 || newX > maxX || newY > maxY) {
		return false;
	}
	if (player["mode"] == 0) { //ship
		if (groundUnderPlayer < 0 || groundUnderPlayer > 2) { //dont move with ship on land
			return false;
		}
	} else {
		if (groundUnderPlayer == 7) { //forrest so dont move
			return false;
		}
	}

	return true;
}

function getGroundUnderPlayer(newX, newY) { //0 = water; 10 = hard ground
	if (newX < 0 || newY < 0 || newX > maxX || newY > maxY) {
		return 0;
	}
	var mapX = Math.floor(newX / 32);
	var mapY = Math.floor(newY / 32);
	var ground = cssMap[mapY][mapX];
	var util = utilMap[mapY][mapX];
	if (util == "forest") {
		return 7;
	}
	var groundSplit = ground.split("_");
	if (groundSplit.length != 2) {
		if (ground == "water") {
			return 0;
		}
		return 10; //Ground
	}
	return parseFloat(groundSplit[1]);
}

function getPlayerMvnt(player, groundUnderPlayer) {
	if (player["mode"] == 0) { //ship
		if (groundUnderPlayer === 1) {
			return 0.5;
		} else if (groundUnderPlayer === 2) {
			return 0.1;
		}
	} else {
		if (groundUnderPlayer === 0) {
			return 0.1;
		} else if (groundUnderPlayer === 1) {
			return 0.5;
		} else if (groundUnderPlayer === 2) {
			return 0.8;
		}
		return 1.5;
	}
	return defaultMvnt;
}

function getRandomNumber(min, max) { //min (inclusive) and max (exclusive)
    return Math.floor(Math.random() * (max - min + 1)) + min;
}