/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/**** 
* Classes
****/ 
var Food = Container.expand(function (isBonus) {
	var self = Container.call(this);
	var foodGraphics;
	if (isBonus) {
		foodGraphics = self.attachAsset('bonusFood', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		self.points = 5;
		self.isBonus = true;
	} else {
		foodGraphics = self.attachAsset('food', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		self.points = 1;
		self.isBonus = false;
	}
	self.gridX = 0;
	self.gridY = 0;
	return self;
});
var SnakeSegment = Container.expand(function (isHead) {
	var self = Container.call(this);
	var segmentGraphics;
	if (isHead) {
		segmentGraphics = self.attachAsset('snakeHead', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	} else {
		segmentGraphics = self.attachAsset('snakeBody', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	}
	self.gridX = 0;
	self.gridY = 0;
	return self;
});
var Wall = Container.expand(function () {
	var self = Container.call(this);
	var wallGraphics = self.attachAsset('wall', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.gridX = 0;
	self.gridY = 0;
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x001122
});
/**** 
* Game Code
****/ 
// Game constants
var GRID_SIZE = 40;
var GRID_WIDTH = 48; // 2048 / 40 = 51.2, using 48 for better centering
var GRID_HEIGHT = 60; // 2732 / 40 = 68.3, using 60 for better centering
var MOVE_SPEED = 8; // Ticks between moves
var INITIAL_LENGTH = 3;
// Game variables
var snake = [];
var direction = {
	x: 1,
	y: 0
}; // Moving right initially
var nextDirection = {
	x: 1,
	y: 0
};
var food = null;
var bonusFood = null;
var walls = [];
var moveCounter = 0;
var currentSpeed = MOVE_SPEED;
var bonusFoodTimer = 0;
var speedBoostTimer = 0;
// Calculate grid offset for centering
var gridOffsetX = (2048 - GRID_WIDTH * GRID_SIZE) / 2;
var gridOffsetY = (2732 - GRID_HEIGHT * GRID_SIZE) / 2;
// Score display
var scoreTxt = new Text2('Score: 0', {
	size: 60,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Initialize walls (border)
function createWalls() {
	// Top and bottom walls
	for (var x = 0; x < GRID_WIDTH; x++) {
		// Top wall
		var topWall = new Wall();
		topWall.gridX = x;
		topWall.gridY = 0;
		topWall.x = gridOffsetX + x * GRID_SIZE + GRID_SIZE / 2;
		topWall.y = gridOffsetY + GRID_SIZE / 2;
		walls.push(topWall);
		game.addChild(topWall);
		// Bottom wall
		var bottomWall = new Wall();
		bottomWall.gridX = x;
		bottomWall.gridY = GRID_HEIGHT - 1;
		bottomWall.x = gridOffsetX + x * GRID_SIZE + GRID_SIZE / 2;
		bottomWall.y = gridOffsetY + (GRID_HEIGHT - 1) * GRID_SIZE + GRID_SIZE / 2;
		walls.push(bottomWall);
		game.addChild(bottomWall);
	}
	// Left and right walls
	for (var y = 1; y < GRID_HEIGHT - 1; y++) {
		// Left wall
		var leftWall = new Wall();
		leftWall.gridX = 0;
		leftWall.gridY = y;
		leftWall.x = gridOffsetX + GRID_SIZE / 2;
		leftWall.y = gridOffsetY + y * GRID_SIZE + GRID_SIZE / 2;
		walls.push(leftWall);
		game.addChild(leftWall);
		// Right wall
		var rightWall = new Wall();
		rightWall.gridX = GRID_WIDTH - 1;
		rightWall.gridY = y;
		rightWall.x = gridOffsetX + (GRID_WIDTH - 1) * GRID_SIZE + GRID_SIZE / 2;
		rightWall.y = gridOffsetY + y * GRID_SIZE + GRID_SIZE / 2;
		walls.push(rightWall);
		game.addChild(rightWall);
	}
}
// Initialize snake
function createSnake() {
	var startX = Math.floor(GRID_WIDTH / 2);
	var startY = Math.floor(GRID_HEIGHT / 2);
	for (var i = 0; i < INITIAL_LENGTH; i++) {
		var segment = new SnakeSegment(i === 0);
		segment.gridX = startX - i;
		segment.gridY = startY;
		segment.x = gridOffsetX + segment.gridX * GRID_SIZE + GRID_SIZE / 2;
		segment.y = gridOffsetY + segment.gridY * GRID_SIZE + GRID_SIZE / 2;
		snake.push(segment);
		game.addChild(segment);
	}
}
// Spawn regular food
function spawnFood() {
	if (food) {
		food.destroy();
		food = null;
	}
	var validPositions = [];
	for (var x = 1; x < GRID_WIDTH - 1; x++) {
		for (var y = 1; y < GRID_HEIGHT - 1; y++) {
			var occupied = false;
			// Check snake segments
			for (var i = 0; i < snake.length; i++) {
				if (snake[i].gridX === x && snake[i].gridY === y) {
					occupied = true;
					break;
				}
			}
			// Check bonus food
			if (bonusFood && bonusFood.gridX === x && bonusFood.gridY === y) {
				occupied = true;
			}
			if (!occupied) {
				validPositions.push({
					x: x,
					y: y
				});
			}
		}
	}
	if (validPositions.length > 0) {
		var pos = validPositions[Math.floor(Math.random() * validPositions.length)];
		food = new Food(false);
		food.gridX = pos.x;
		food.gridY = pos.y;
		food.x = gridOffsetX + pos.x * GRID_SIZE + GRID_SIZE / 2;
		food.y = gridOffsetY + pos.y * GRID_SIZE + GRID_SIZE / 2;
		game.addChild(food);
	}
}
// Spawn bonus food
function spawnBonusFood() {
	if (bonusFood) {
		bonusFood.destroy();
		bonusFood = null;
	}
	var validPositions = [];
	for (var x = 1; x < GRID_WIDTH - 1; x++) {
		for (var y = 1; y < GRID_HEIGHT - 1; y++) {
			var occupied = false;
			// Check snake segments
			for (var i = 0; i < snake.length; i++) {
				if (snake[i].gridX === x && snake[i].gridY === y) {
					occupied = true;
					break;
				}
			}
			// Check regular food
			if (food && food.gridX === x && food.gridY === y) {
				occupied = true;
			}
			if (!occupied) {
				validPositions.push({
					x: x,
					y: y
				});
			}
		}
	}
	if (validPositions.length > 0) {
		var pos = validPositions[Math.floor(Math.random() * validPositions.length)];
		bonusFood = new Food(true);
		bonusFood.gridX = pos.x;
		bonusFood.gridY = pos.y;
		bonusFood.x = gridOffsetX + pos.x * GRID_SIZE + GRID_SIZE / 2;
		bonusFood.y = gridOffsetY + pos.y * GRID_SIZE + GRID_SIZE / 2;
		game.addChild(bonusFood);
		// Bonus food flashing effect
		tween(bonusFood, {
			alpha: 0.3
		}, {
			duration: 500,
			easing: tween.easeInOut,
			onFinish: function onFinish() {
				if (bonusFood) {
					tween(bonusFood, {
						alpha: 1
					}, {
						duration: 500,
						easing: tween.easeInOut
					});
				}
			}
		});
	}
}
// Move snake
function moveSnake() {
	// Update direction
	direction.x = nextDirection.x;
	direction.y = nextDirection.y;
	// Calculate new head position
	var head = snake[0];
	var newX = head.gridX + direction.x;
	var newY = head.gridY + direction.y;
	// Check wall collision
	if (newX <= 0 || newX >= GRID_WIDTH - 1 || newY <= 0 || newY >= GRID_HEIGHT - 1) {
		LK.showGameOver();
		return;
	}
	// Check self collision
	for (var i = 0; i < snake.length; i++) {
		if (snake[i].gridX === newX && snake[i].gridY === newY) {
			LK.showGameOver();
			return;
		}
	}
	// Check food collision
	var ateFood = false;
	var ateBonus = false;
	if (food && food.gridX === newX && food.gridY === newY) {
		ateFood = true;
		LK.setScore(LK.getScore() + food.points);
		LK.getSound('eat').play();
		food.destroy();
		food = null;
		spawnFood();
	}
	if (bonusFood && bonusFood.gridX === newX && bonusFood.gridY === newY) {
		ateBonus = true;
		LK.setScore(LK.getScore() + bonusFood.points);
		LK.getSound('bonus').play();
		bonusFood.destroy();
		bonusFood = null;
		bonusFoodTimer = 0;
		// Speed boost
		speedBoostTimer = 300; // 5 seconds at 60fps
		currentSpeed = Math.max(2, MOVE_SPEED - 4);
	}
	// Create new head
	var newHead = new SnakeSegment(true);
	newHead.gridX = newX;
	newHead.gridY = newY;
	newHead.x = gridOffsetX + newX * GRID_SIZE + GRID_SIZE / 2;
	newHead.y = gridOffsetY + newY * GRID_SIZE + GRID_SIZE / 2;
	// Convert old head to body
	var oldHead = snake[0];
	oldHead.removeChild(oldHead.children[0]);
	var bodyGraphics = oldHead.attachAsset('snakeBody', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	snake.unshift(newHead);
	game.addChild(newHead);
	// Remove tail if no food eaten
	if (!ateFood && !ateBonus) {
		var tail = snake.pop();
		tail.destroy();
	}
	// Update score display
	scoreTxt.setText('Score: ' + LK.getScore());
	// Increase speed based on score
	var baseSpeed = Math.max(3, MOVE_SPEED - Math.floor(LK.getScore() / 10));
	if (speedBoostTimer <= 0) {
		currentSpeed = baseSpeed;
	}
}
// Touch controls
var touchStartX = 0;
var touchStartY = 0;
var minSwipeDistance = 50;
game.down = function (x, y, obj) {
	touchStartX = x;
	touchStartY = y;
};
game.up = function (x, y, obj) {
	var deltaX = x - touchStartX;
	var deltaY = y - touchStartY;
	var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
	if (distance >= minSwipeDistance) {
		if (Math.abs(deltaX) > Math.abs(deltaY)) {
			// Horizontal swipe
			if (deltaX > 0 && direction.x !== -1) {
				nextDirection = {
					x: 1,
					y: 0
				}; // Right
			} else if (deltaX < 0 && direction.x !== 1) {
				nextDirection = {
					x: -1,
					y: 0
				}; // Left
			}
		} else {
			// Vertical swipe
			if (deltaY > 0 && direction.y !== -1) {
				nextDirection = {
					x: 0,
					y: 1
				}; // Down
			} else if (deltaY < 0 && direction.y !== 1) {
				nextDirection = {
					x: 0,
					y: -1
				}; // Up
			}
		}
	}
};
// Initialize game elements
createWalls();
createSnake();
spawnFood();
// Play background music
LK.playMusic('gameMusic');
// Game update loop
game.update = function () {
	moveCounter++;
	// Move snake
	if (moveCounter >= currentSpeed) {
		moveSnake();
		moveCounter = 0;
	}
	// Update speed boost timer
	if (speedBoostTimer > 0) {
		speedBoostTimer--;
	}
	// Spawn bonus food occasionally
	bonusFoodTimer++;
	if (bonusFoodTimer >= 600 && !bonusFood && Math.random() < 0.02) {
		// 10 seconds minimum, 2% chance per tick
		spawnBonusFood();
		bonusFoodTimer = 0;
	}
	// Remove bonus food after some time
	if (bonusFood && bonusFoodTimer >= 900) {
		// 15 seconds
		bonusFood.destroy();
		bonusFood = null;
		bonusFoodTimer = 0;
	}
}; /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/**** 
* Classes
****/ 
var Food = Container.expand(function (isBonus) {
	var self = Container.call(this);
	var foodGraphics;
	if (isBonus) {
		foodGraphics = self.attachAsset('bonusFood', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		self.points = 5;
		self.isBonus = true;
	} else {
		foodGraphics = self.attachAsset('food', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		self.points = 1;
		self.isBonus = false;
	}
	self.gridX = 0;
	self.gridY = 0;
	return self;
});
var SnakeSegment = Container.expand(function (isHead) {
	var self = Container.call(this);
	var segmentGraphics;
	if (isHead) {
		segmentGraphics = self.attachAsset('snakeHead', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	} else {
		segmentGraphics = self.attachAsset('snakeBody', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	}
	self.gridX = 0;
	self.gridY = 0;
	return self;
});
var Wall = Container.expand(function () {
	var self = Container.call(this);
	var wallGraphics = self.attachAsset('wall', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.gridX = 0;
	self.gridY = 0;
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x001122
});
/**** 
* Game Code
****/ 
// Game constants
var GRID_SIZE = 40;
var GRID_WIDTH = 48; // 2048 / 40 = 51.2, using 48 for better centering
var GRID_HEIGHT = 60; // 2732 / 40 = 68.3, using 60 for better centering
var MOVE_SPEED = 8; // Ticks between moves
var INITIAL_LENGTH = 3;
// Game variables
var snake = [];
var direction = {
	x: 1,
	y: 0
}; // Moving right initially
var nextDirection = {
	x: 1,
	y: 0
};
var food = null;
var bonusFood = null;
var walls = [];
var moveCounter = 0;
var currentSpeed = MOVE_SPEED;
var bonusFoodTimer = 0;
var speedBoostTimer = 0;
// Calculate grid offset for centering
var gridOffsetX = (2048 - GRID_WIDTH * GRID_SIZE) / 2;
var gridOffsetY = (2732 - GRID_HEIGHT * GRID_SIZE) / 2;
// Score display
var scoreTxt = new Text2('Score: 0', {
	size: 60,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Initialize walls (border)
function createWalls() {
	// Top and bottom walls
	for (var x = 0; x < GRID_WIDTH; x++) {
		// Top wall
		var topWall = new Wall();
		topWall.gridX = x;
		topWall.gridY = 0;
		topWall.x = gridOffsetX + x * GRID_SIZE + GRID_SIZE / 2;
		topWall.y = gridOffsetY + GRID_SIZE / 2;
		walls.push(topWall);
		game.addChild(topWall);
		// Bottom wall
		var bottomWall = new Wall();
		bottomWall.gridX = x;
		bottomWall.gridY = GRID_HEIGHT - 1;
		bottomWall.x = gridOffsetX + x * GRID_SIZE + GRID_SIZE / 2;
		bottomWall.y = gridOffsetY + (GRID_HEIGHT - 1) * GRID_SIZE + GRID_SIZE / 2;
		walls.push(bottomWall);
		game.addChild(bottomWall);
	}
	// Left and right walls
	for (var y = 1; y < GRID_HEIGHT - 1; y++) {
		// Left wall
		var leftWall = new Wall();
		leftWall.gridX = 0;
		leftWall.gridY = y;
		leftWall.x = gridOffsetX + GRID_SIZE / 2;
		leftWall.y = gridOffsetY + y * GRID_SIZE + GRID_SIZE / 2;
		walls.push(leftWall);
		game.addChild(leftWall);
		// Right wall
		var rightWall = new Wall();
		rightWall.gridX = GRID_WIDTH - 1;
		rightWall.gridY = y;
		rightWall.x = gridOffsetX + (GRID_WIDTH - 1) * GRID_SIZE + GRID_SIZE / 2;
		rightWall.y = gridOffsetY + y * GRID_SIZE + GRID_SIZE / 2;
		walls.push(rightWall);
		game.addChild(rightWall);
	}
}
// Initialize snake
function createSnake() {
	var startX = Math.floor(GRID_WIDTH / 2);
	var startY = Math.floor(GRID_HEIGHT / 2);
	for (var i = 0; i < INITIAL_LENGTH; i++) {
		var segment = new SnakeSegment(i === 0);
		segment.gridX = startX - i;
		segment.gridY = startY;
		segment.x = gridOffsetX + segment.gridX * GRID_SIZE + GRID_SIZE / 2;
		segment.y = gridOffsetY + segment.gridY * GRID_SIZE + GRID_SIZE / 2;
		snake.push(segment);
		game.addChild(segment);
	}
}
// Spawn regular food
function spawnFood() {
	if (food) {
		food.destroy();
		food = null;
	}
	var validPositions = [];
	for (var x = 1; x < GRID_WIDTH - 1; x++) {
		for (var y = 1; y < GRID_HEIGHT - 1; y++) {
			var occupied = false;
			// Check snake segments
			for (var i = 0; i < snake.length; i++) {
				if (snake[i].gridX === x && snake[i].gridY === y) {
					occupied = true;
					break;
				}
			}
			// Check bonus food
			if (bonusFood && bonusFood.gridX === x && bonusFood.gridY === y) {
				occupied = true;
			}
			if (!occupied) {
				validPositions.push({
					x: x,
					y: y
				});
			}
		}
	}
	if (validPositions.length > 0) {
		var pos = validPositions[Math.floor(Math.random() * validPositions.length)];
		food = new Food(false);
		food.gridX = pos.x;
		food.gridY = pos.y;
		food.x = gridOffsetX + pos.x * GRID_SIZE + GRID_SIZE / 2;
		food.y = gridOffsetY + pos.y * GRID_SIZE + GRID_SIZE / 2;
		game.addChild(food);
	}
}
// Spawn bonus food
function spawnBonusFood() {
	if (bonusFood) {
		bonusFood.destroy();
		bonusFood = null;
	}
	var validPositions = [];
	for (var x = 1; x < GRID_WIDTH - 1; x++) {
		for (var y = 1; y < GRID_HEIGHT - 1; y++) {
			var occupied = false;
			// Check snake segments
			for (var i = 0; i < snake.length; i++) {
				if (snake[i].gridX === x && snake[i].gridY === y) {
					occupied = true;
					break;
				}
			}
			// Check regular food
			if (food && food.gridX === x && food.gridY === y) {
				occupied = true;
			}
			if (!occupied) {
				validPositions.push({
					x: x,
					y: y
				});
			}
		}
	}
	if (validPositions.length > 0) {
		var pos = validPositions[Math.floor(Math.random() * validPositions.length)];
		bonusFood = new Food(true);
		bonusFood.gridX = pos.x;
		bonusFood.gridY = pos.y;
		bonusFood.x = gridOffsetX + pos.x * GRID_SIZE + GRID_SIZE / 2;
		bonusFood.y = gridOffsetY + pos.y * GRID_SIZE + GRID_SIZE / 2;
		game.addChild(bonusFood);
		// Bonus food flashing effect
		tween(bonusFood, {
			alpha: 0.3
		}, {
			duration: 500,
			easing: tween.easeInOut,
			onFinish: function onFinish() {
				if (bonusFood) {
					tween(bonusFood, {
						alpha: 1
					}, {
						duration: 500,
						easing: tween.easeInOut
					});
				}
			}
		});
	}
}
// Move snake
function moveSnake() {
	// Update direction
	direction.x = nextDirection.x;
	direction.y = nextDirection.y;
	// Calculate new head position
	var head = snake[0];
	var newX = head.gridX + direction.x;
	var newY = head.gridY + direction.y;
	// Check wall collision
	if (newX <= 0 || newX >= GRID_WIDTH - 1 || newY <= 0 || newY >= GRID_HEIGHT - 1) {
		LK.showGameOver();
		return;
	}
	// Check self collision
	for (var i = 0; i < snake.length; i++) {
		if (snake[i].gridX === newX && snake[i].gridY === newY) {
			LK.showGameOver();
			return;
		}
	}
	// Check food collision
	var ateFood = false;
	var ateBonus = false;
	if (food && food.gridX === newX && food.gridY === newY) {
		ateFood = true;
		LK.setScore(LK.getScore() + food.points);
		LK.getSound('eat').play();
		food.destroy();
		food = null;
		spawnFood();
	}
	if (bonusFood && bonusFood.gridX === newX && bonusFood.gridY === newY) {
		ateBonus = true;
		LK.setScore(LK.getScore() + bonusFood.points);
		LK.getSound('bonus').play();
		bonusFood.destroy();
		bonusFood = null;
		bonusFoodTimer = 0;
		// Speed boost
		speedBoostTimer = 300; // 5 seconds at 60fps
		currentSpeed = Math.max(2, MOVE_SPEED - 4);
	}
	// Create new head
	var newHead = new SnakeSegment(true);
	newHead.gridX = newX;
	newHead.gridY = newY;
	newHead.x = gridOffsetX + newX * GRID_SIZE + GRID_SIZE / 2;
	newHead.y = gridOffsetY + newY * GRID_SIZE + GRID_SIZE / 2;
	// Convert old head to body
	var oldHead = snake[0];
	oldHead.removeChild(oldHead.children[0]);
	var bodyGraphics = oldHead.attachAsset('snakeBody', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	snake.unshift(newHead);
	game.addChild(newHead);
	// Remove tail if no food eaten
	if (!ateFood && !ateBonus) {
		var tail = snake.pop();
		tail.destroy();
	}
	// Update score display
	scoreTxt.setText('Score: ' + LK.getScore());
	// Increase speed based on score
	var baseSpeed = Math.max(3, MOVE_SPEED - Math.floor(LK.getScore() / 10));
	if (speedBoostTimer <= 0) {
		currentSpeed = baseSpeed;
	}
}
// Touch controls
var touchStartX = 0;
var touchStartY = 0;
var minSwipeDistance = 50;
game.down = function (x, y, obj) {
	touchStartX = x;
	touchStartY = y;
};
game.up = function (x, y, obj) {
	var deltaX = x - touchStartX;
	var deltaY = y - touchStartY;
	var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
	if (distance >= minSwipeDistance) {
		if (Math.abs(deltaX) > Math.abs(deltaY)) {
			// Horizontal swipe
			if (deltaX > 0 && direction.x !== -1) {
				nextDirection = {
					x: 1,
					y: 0
				}; // Right
			} else if (deltaX < 0 && direction.x !== 1) {
				nextDirection = {
					x: -1,
					y: 0
				}; // Left
			}
		} else {
			// Vertical swipe
			if (deltaY > 0 && direction.y !== -1) {
				nextDirection = {
					x: 0,
					y: 1
				}; // Down
			} else if (deltaY < 0 && direction.y !== 1) {
				nextDirection = {
					x: 0,
					y: -1
				}; // Up
			}
		}
	}
};
// Initialize game elements
createWalls();
createSnake();
spawnFood();
// Play background music
LK.playMusic('gameMusic');
// Game update loop
game.update = function () {
	moveCounter++;
	// Move snake
	if (moveCounter >= currentSpeed) {
		moveSnake();
		moveCounter = 0;
	}
	// Update speed boost timer
	if (speedBoostTimer > 0) {
		speedBoostTimer--;
	}
	// Spawn bonus food occasionally
	bonusFoodTimer++;
	if (bonusFoodTimer >= 600 && !bonusFood && Math.random() < 0.02) {
		// 10 seconds minimum, 2% chance per tick
		spawnBonusFood();
		bonusFoodTimer = 0;
	}
	// Remove bonus food after some time
	if (bonusFood && bonusFoodTimer >= 900) {
		// 15 seconds
		bonusFood.destroy();
		bonusFood = null;
		bonusFoodTimer = 0;
	}
};