/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Tile class: represents a single tile on the board
var Tile = Container.expand(function () {
	var self = Container.call(this);
	// Properties
	self.value = 0; // 0 means empty
	self.row = 0;
	self.col = 0;
	self.tileBG = null;
	self.tileText = null;
	// Set up tile
	self.setValue = function (val) {
		self.value = val;
		// Remove previous children if any
		if (self.tileBG) {
			self.removeChild(self.tileBG);
			self.tileBG = null;
		}
		if (self.tileText) {
			self.removeChild(self.tileText);
			self.tileText = null;
		}
		// Choose asset based on value
		var assetId = 'tile';
		if (val === 0) {
			assetId = 'tileBG';
		} else if (val === 2) {
			assetId = 'tile2';
		} else if (val === 4) {
			assetId = 'tile4';
		} else if (val === 8) {
			assetId = 'tile8';
		} else if (val === 16) {
			assetId = 'tile16';
		} else if (val === 32) {
			assetId = 'tile32';
		} else if (val === 64) {
			assetId = 'tile64';
		} else if (val === 128) {
			assetId = 'tile128';
		} else if (val === 256) {
			assetId = 'tile256';
		} else if (val === 512) {
			assetId = 'tile512';
		} else if (val === 1024) {
			assetId = 'tile1024';
		} else if (val === 2048) {
			assetId = 'tile2048';
		}
		self.tileBG = self.attachAsset(assetId, {
			anchorX: 0.5,
			anchorY: 0.5
		});
		if (val > 0) {
			var textColor = "#776e65";
			if (val >= 8) textColor = "#f9f6f2";
			self.tileText = new Text2(val + '', {
				size: 120,
				fill: textColor
			});
			self.tileText.anchor.set(0.5, 0.5);
			self.addChild(self.tileText);
		}
	};
	// Animate pop
	self.pop = function () {
		self.scaleX = 0.7;
		self.scaleY = 0.7;
		tween(self, {
			scaleX: 1,
			scaleY: 1
		}, {
			duration: 120,
			easing: tween.easeOut
		});
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0xfaf8ef
});
/**** 
* Game Code
****/ 
// Tiles: We'll use colored boxes for tiles, and white for empty background.
// Board constants
var GRID_SIZE = 4;
var TILE_SIZE = 400;
var TILE_MARGIN = 20;
var BOARD_SIZE = GRID_SIZE * TILE_SIZE + (GRID_SIZE + 1) * TILE_MARGIN;
var BOARD_X = (2048 - BOARD_SIZE) / 2;
var BOARD_Y = (2732 - BOARD_SIZE) / 2 + 100; // +100 to avoid top menu
// Board background
var boardBG = LK.getAsset('boardBG', {
	anchorX: 0,
	anchorY: 0,
	x: BOARD_X,
	y: BOARD_Y
});
game.addChild(boardBG);
// 2D array of tiles
var tiles = [];
// 2D array of tile values (for logic)
var tileVals = [];
// For swipe detection
var touchStartX = 0,
	touchStartY = 0,
	touchEndX = 0,
	touchEndY = 0,
	isTouching = false;
// Score
var score = 0;
var bestScore = 0;
// Score text
var scoreTxt = new Text2('0', {
	size: 120,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.x = 2048 / 2;
scoreTxt.y = 20;
LK.gui.top.addChild(scoreTxt);
// Best score text
var bestScoreTxt = new Text2('BEST: 0', {
	size: 60,
	fill: 0xFFFFFF
});
bestScoreTxt.anchor.set(0.5, 0);
bestScoreTxt.x = 2048 / 2;
bestScoreTxt.y = 150;
LK.gui.top.addChild(bestScoreTxt);
// Initialize board
function initBoard() {
	// Remove old tiles if any
	for (var r = 0; r < GRID_SIZE; r++) {
		for (var c = 0; c < GRID_SIZE; c++) {
			if (tiles[r] && tiles[r][c]) {
				tiles[r][c].destroy();
			}
		}
	}
	tiles = [];
	tileVals = [];
	for (var r = 0; r < GRID_SIZE; r++) {
		tiles[r] = [];
		tileVals[r] = [];
		for (var c = 0; c < GRID_SIZE; c++) {
			var tile = new Tile();
			tile.row = r;
			tile.col = c;
			tile.setValue(0);
			// Position
			tile.x = BOARD_X + TILE_MARGIN + c * (TILE_SIZE + TILE_MARGIN) + TILE_SIZE / 2;
			tile.y = BOARD_Y + TILE_MARGIN + r * (TILE_SIZE + TILE_MARGIN) + TILE_SIZE / 2;
			tile.scaleX = 1;
			tile.scaleY = 1;
			game.addChild(tile);
			tiles[r][c] = tile;
			tileVals[r][c] = 0;
		}
	}
	score = 0;
	updateScore();
	addRandomTile();
	addRandomTile();
}
// Add a random tile (2 or 4) to an empty spot
function addRandomTile() {
	var empties = [];
	for (var r = 0; r < GRID_SIZE; r++) {
		for (var c = 0; c < GRID_SIZE; c++) {
			if (tileVals[r][c] === 0) {
				empties.push({
					r: r,
					c: c
				});
			}
		}
	}
	if (empties.length === 0) return;
	var idx = Math.floor(Math.random() * empties.length);
	var pos = empties[idx];
	var val = Math.random() < 0.9 ? 2 : 4;
	tileVals[pos.r][pos.c] = val;
	tiles[pos.r][pos.c].setValue(val);
	tiles[pos.r][pos.c].pop();
}
// Update all tile visuals from tileVals
function updateTiles() {
	for (var r = 0; r < GRID_SIZE; r++) {
		for (var c = 0; c < GRID_SIZE; c++) {
			tiles[r][c].setValue(tileVals[r][c]);
		}
	}
}
// Update score display
function updateScore() {
	scoreTxt.setText(score + '');
	if (score > bestScore) {
		bestScore = score;
	}
	bestScoreTxt.setText('BEST: ' + bestScore);
	LK.setScore(score);
}
// Check if any moves are possible
function canMove() {
	for (var r = 0; r < GRID_SIZE; r++) {
		for (var c = 0; c < GRID_SIZE; c++) {
			if (tileVals[r][c] === 0) return true;
			if (c < GRID_SIZE - 1 && tileVals[r][c] === tileVals[r][c + 1]) return true;
			if (r < GRID_SIZE - 1 && tileVals[r][c] === tileVals[r + 1][c]) return true;
		}
	}
	return false;
}
// Check if 2048 tile exists
function has2048() {
	for (var r = 0; r < GRID_SIZE; r++) {
		for (var c = 0; c < GRID_SIZE; c++) {
			if (tileVals[r][c] === 2048) return true;
		}
	}
	return false;
}
// Move logic
function move(direction) {
	// direction: 'left', 'right', 'up', 'down'
	var moved = false;
	var merged = [];
	for (var r = 0; r < GRID_SIZE; r++) {
		merged[r] = [];
		for (var c = 0; c < GRID_SIZE; c++) {
			merged[r][c] = false;
		}
	}
	var start, end, step;
	if (direction === 'left') {
		for (var r = 0; r < GRID_SIZE; r++) {
			for (var c = 1; c < GRID_SIZE; c++) {
				if (tileVals[r][c] === 0) continue;
				var target = c;
				while (target > 0 && tileVals[r][target - 1] === 0) {
					target--;
				}
				if (target > 0 && tileVals[r][target - 1] === tileVals[r][c] && !merged[r][target - 1]) {
					// Merge
					tileVals[r][target - 1] *= 2;
					score += tileVals[r][target - 1];
					tileVals[r][c] = 0;
					merged[r][target - 1] = true;
					moved = true;
					tiles[r][target - 1].pop();
				} else if (target !== c) {
					// Move
					tileVals[r][target] = tileVals[r][c];
					tileVals[r][c] = 0;
					moved = true;
				}
			}
		}
	} else if (direction === 'right') {
		for (var r = 0; r < GRID_SIZE; r++) {
			for (var c = GRID_SIZE - 2; c >= 0; c--) {
				if (tileVals[r][c] === 0) continue;
				var target = c;
				while (target < GRID_SIZE - 1 && tileVals[r][target + 1] === 0) {
					target++;
				}
				if (target < GRID_SIZE - 1 && tileVals[r][target + 1] === tileVals[r][c] && !merged[r][target + 1]) {
					// Merge
					tileVals[r][target + 1] *= 2;
					score += tileVals[r][target + 1];
					tileVals[r][c] = 0;
					merged[r][target + 1] = true;
					moved = true;
					tiles[r][target + 1].pop();
				} else if (target !== c) {
					// Move
					tileVals[r][target] = tileVals[r][c];
					tileVals[r][c] = 0;
					moved = true;
				}
			}
		}
	} else if (direction === 'up') {
		for (var c = 0; c < GRID_SIZE; c++) {
			for (var r = 1; r < GRID_SIZE; r++) {
				if (tileVals[r][c] === 0) continue;
				var target = r;
				while (target > 0 && tileVals[target - 1][c] === 0) {
					target--;
				}
				if (target > 0 && tileVals[target - 1][c] === tileVals[r][c] && !merged[target - 1][c]) {
					// Merge
					tileVals[target - 1][c] *= 2;
					score += tileVals[target - 1][c];
					tileVals[r][c] = 0;
					merged[target - 1][c] = true;
					moved = true;
					tiles[target - 1][c].pop();
				} else if (target !== r) {
					// Move
					tileVals[target][c] = tileVals[r][c];
					tileVals[r][c] = 0;
					moved = true;
				}
			}
		}
	} else if (direction === 'down') {
		for (var c = 0; c < GRID_SIZE; c++) {
			for (var r = GRID_SIZE - 2; r >= 0; r--) {
				if (tileVals[r][c] === 0) continue;
				var target = r;
				while (target < GRID_SIZE - 1 && tileVals[target + 1][c] === 0) {
					target++;
				}
				if (target < GRID_SIZE - 1 && tileVals[target + 1][c] === tileVals[r][c] && !merged[target + 1][c]) {
					// Merge
					tileVals[target + 1][c] *= 2;
					score += tileVals[target + 1][c];
					tileVals[r][c] = 0;
					merged[target + 1][c] = true;
					moved = true;
					tiles[target + 1][c].pop();
				} else if (target !== r) {
					// Move
					tileVals[target][c] = tileVals[r][c];
					tileVals[r][c] = 0;
					moved = true;
				}
			}
		}
	}
	if (moved) {
		addRandomTile();
		updateTiles();
		updateScore();
		if (has2048()) {
			LK.showYouWin();
		} else if (!canMove()) {
			LK.effects.flashScreen(0xff0000, 1000);
			LK.showGameOver();
		}
	}
}
// Touch/drag/swipe handling
game.down = function (x, y, obj) {
	// Only start if inside board area
	if (x >= BOARD_X && x <= BOARD_X + BOARD_SIZE && y >= BOARD_Y && y <= BOARD_Y + BOARD_SIZE) {
		touchStartX = x;
		touchStartY = y;
		isTouching = true;
	}
};
game.move = function (x, y, obj) {
	if (!isTouching) return;
	touchEndX = x;
	touchEndY = y;
};
game.up = function (x, y, obj) {
	if (!isTouching) return;
	var dx = touchEndX - touchStartX;
	var dy = touchEndY - touchStartY;
	var absDx = Math.abs(dx);
	var absDy = Math.abs(dy);
	if (absDx > 50 || absDy > 50) {
		if (absDx > absDy) {
			if (dx > 0) {
				move('right');
			} else {
				move('left');
			}
		} else {
			if (dy > 0) {
				move('down');
			} else {
				move('up');
			}
		}
	}
	isTouching = false;
	touchStartX = 0;
	touchStartY = 0;
	touchEndX = 0;
	touchEndY = 0;
};
// Reset game on game over or win
game.on('reset', function () {
	initBoard();
});
// Initialize
initBoard();
// Play background music
LK.playMusic('arkaplan'); /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Tile class: represents a single tile on the board
var Tile = Container.expand(function () {
	var self = Container.call(this);
	// Properties
	self.value = 0; // 0 means empty
	self.row = 0;
	self.col = 0;
	self.tileBG = null;
	self.tileText = null;
	// Set up tile
	self.setValue = function (val) {
		self.value = val;
		// Remove previous children if any
		if (self.tileBG) {
			self.removeChild(self.tileBG);
			self.tileBG = null;
		}
		if (self.tileText) {
			self.removeChild(self.tileText);
			self.tileText = null;
		}
		// Choose asset based on value
		var assetId = 'tile';
		if (val === 0) {
			assetId = 'tileBG';
		} else if (val === 2) {
			assetId = 'tile2';
		} else if (val === 4) {
			assetId = 'tile4';
		} else if (val === 8) {
			assetId = 'tile8';
		} else if (val === 16) {
			assetId = 'tile16';
		} else if (val === 32) {
			assetId = 'tile32';
		} else if (val === 64) {
			assetId = 'tile64';
		} else if (val === 128) {
			assetId = 'tile128';
		} else if (val === 256) {
			assetId = 'tile256';
		} else if (val === 512) {
			assetId = 'tile512';
		} else if (val === 1024) {
			assetId = 'tile1024';
		} else if (val === 2048) {
			assetId = 'tile2048';
		}
		self.tileBG = self.attachAsset(assetId, {
			anchorX: 0.5,
			anchorY: 0.5
		});
		if (val > 0) {
			var textColor = "#776e65";
			if (val >= 8) textColor = "#f9f6f2";
			self.tileText = new Text2(val + '', {
				size: 120,
				fill: textColor
			});
			self.tileText.anchor.set(0.5, 0.5);
			self.addChild(self.tileText);
		}
	};
	// Animate pop
	self.pop = function () {
		self.scaleX = 0.7;
		self.scaleY = 0.7;
		tween(self, {
			scaleX: 1,
			scaleY: 1
		}, {
			duration: 120,
			easing: tween.easeOut
		});
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0xfaf8ef
});
/**** 
* Game Code
****/ 
// Tiles: We'll use colored boxes for tiles, and white for empty background.
// Board constants
var GRID_SIZE = 4;
var TILE_SIZE = 400;
var TILE_MARGIN = 20;
var BOARD_SIZE = GRID_SIZE * TILE_SIZE + (GRID_SIZE + 1) * TILE_MARGIN;
var BOARD_X = (2048 - BOARD_SIZE) / 2;
var BOARD_Y = (2732 - BOARD_SIZE) / 2 + 100; // +100 to avoid top menu
// Board background
var boardBG = LK.getAsset('boardBG', {
	anchorX: 0,
	anchorY: 0,
	x: BOARD_X,
	y: BOARD_Y
});
game.addChild(boardBG);
// 2D array of tiles
var tiles = [];
// 2D array of tile values (for logic)
var tileVals = [];
// For swipe detection
var touchStartX = 0,
	touchStartY = 0,
	touchEndX = 0,
	touchEndY = 0,
	isTouching = false;
// Score
var score = 0;
var bestScore = 0;
// Score text
var scoreTxt = new Text2('0', {
	size: 120,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.x = 2048 / 2;
scoreTxt.y = 20;
LK.gui.top.addChild(scoreTxt);
// Best score text
var bestScoreTxt = new Text2('BEST: 0', {
	size: 60,
	fill: 0xFFFFFF
});
bestScoreTxt.anchor.set(0.5, 0);
bestScoreTxt.x = 2048 / 2;
bestScoreTxt.y = 150;
LK.gui.top.addChild(bestScoreTxt);
// Initialize board
function initBoard() {
	// Remove old tiles if any
	for (var r = 0; r < GRID_SIZE; r++) {
		for (var c = 0; c < GRID_SIZE; c++) {
			if (tiles[r] && tiles[r][c]) {
				tiles[r][c].destroy();
			}
		}
	}
	tiles = [];
	tileVals = [];
	for (var r = 0; r < GRID_SIZE; r++) {
		tiles[r] = [];
		tileVals[r] = [];
		for (var c = 0; c < GRID_SIZE; c++) {
			var tile = new Tile();
			tile.row = r;
			tile.col = c;
			tile.setValue(0);
			// Position
			tile.x = BOARD_X + TILE_MARGIN + c * (TILE_SIZE + TILE_MARGIN) + TILE_SIZE / 2;
			tile.y = BOARD_Y + TILE_MARGIN + r * (TILE_SIZE + TILE_MARGIN) + TILE_SIZE / 2;
			tile.scaleX = 1;
			tile.scaleY = 1;
			game.addChild(tile);
			tiles[r][c] = tile;
			tileVals[r][c] = 0;
		}
	}
	score = 0;
	updateScore();
	addRandomTile();
	addRandomTile();
}
// Add a random tile (2 or 4) to an empty spot
function addRandomTile() {
	var empties = [];
	for (var r = 0; r < GRID_SIZE; r++) {
		for (var c = 0; c < GRID_SIZE; c++) {
			if (tileVals[r][c] === 0) {
				empties.push({
					r: r,
					c: c
				});
			}
		}
	}
	if (empties.length === 0) return;
	var idx = Math.floor(Math.random() * empties.length);
	var pos = empties[idx];
	var val = Math.random() < 0.9 ? 2 : 4;
	tileVals[pos.r][pos.c] = val;
	tiles[pos.r][pos.c].setValue(val);
	tiles[pos.r][pos.c].pop();
}
// Update all tile visuals from tileVals
function updateTiles() {
	for (var r = 0; r < GRID_SIZE; r++) {
		for (var c = 0; c < GRID_SIZE; c++) {
			tiles[r][c].setValue(tileVals[r][c]);
		}
	}
}
// Update score display
function updateScore() {
	scoreTxt.setText(score + '');
	if (score > bestScore) {
		bestScore = score;
	}
	bestScoreTxt.setText('BEST: ' + bestScore);
	LK.setScore(score);
}
// Check if any moves are possible
function canMove() {
	for (var r = 0; r < GRID_SIZE; r++) {
		for (var c = 0; c < GRID_SIZE; c++) {
			if (tileVals[r][c] === 0) return true;
			if (c < GRID_SIZE - 1 && tileVals[r][c] === tileVals[r][c + 1]) return true;
			if (r < GRID_SIZE - 1 && tileVals[r][c] === tileVals[r + 1][c]) return true;
		}
	}
	return false;
}
// Check if 2048 tile exists
function has2048() {
	for (var r = 0; r < GRID_SIZE; r++) {
		for (var c = 0; c < GRID_SIZE; c++) {
			if (tileVals[r][c] === 2048) return true;
		}
	}
	return false;
}
// Move logic
function move(direction) {
	// direction: 'left', 'right', 'up', 'down'
	var moved = false;
	var merged = [];
	for (var r = 0; r < GRID_SIZE; r++) {
		merged[r] = [];
		for (var c = 0; c < GRID_SIZE; c++) {
			merged[r][c] = false;
		}
	}
	var start, end, step;
	if (direction === 'left') {
		for (var r = 0; r < GRID_SIZE; r++) {
			for (var c = 1; c < GRID_SIZE; c++) {
				if (tileVals[r][c] === 0) continue;
				var target = c;
				while (target > 0 && tileVals[r][target - 1] === 0) {
					target--;
				}
				if (target > 0 && tileVals[r][target - 1] === tileVals[r][c] && !merged[r][target - 1]) {
					// Merge
					tileVals[r][target - 1] *= 2;
					score += tileVals[r][target - 1];
					tileVals[r][c] = 0;
					merged[r][target - 1] = true;
					moved = true;
					tiles[r][target - 1].pop();
				} else if (target !== c) {
					// Move
					tileVals[r][target] = tileVals[r][c];
					tileVals[r][c] = 0;
					moved = true;
				}
			}
		}
	} else if (direction === 'right') {
		for (var r = 0; r < GRID_SIZE; r++) {
			for (var c = GRID_SIZE - 2; c >= 0; c--) {
				if (tileVals[r][c] === 0) continue;
				var target = c;
				while (target < GRID_SIZE - 1 && tileVals[r][target + 1] === 0) {
					target++;
				}
				if (target < GRID_SIZE - 1 && tileVals[r][target + 1] === tileVals[r][c] && !merged[r][target + 1]) {
					// Merge
					tileVals[r][target + 1] *= 2;
					score += tileVals[r][target + 1];
					tileVals[r][c] = 0;
					merged[r][target + 1] = true;
					moved = true;
					tiles[r][target + 1].pop();
				} else if (target !== c) {
					// Move
					tileVals[r][target] = tileVals[r][c];
					tileVals[r][c] = 0;
					moved = true;
				}
			}
		}
	} else if (direction === 'up') {
		for (var c = 0; c < GRID_SIZE; c++) {
			for (var r = 1; r < GRID_SIZE; r++) {
				if (tileVals[r][c] === 0) continue;
				var target = r;
				while (target > 0 && tileVals[target - 1][c] === 0) {
					target--;
				}
				if (target > 0 && tileVals[target - 1][c] === tileVals[r][c] && !merged[target - 1][c]) {
					// Merge
					tileVals[target - 1][c] *= 2;
					score += tileVals[target - 1][c];
					tileVals[r][c] = 0;
					merged[target - 1][c] = true;
					moved = true;
					tiles[target - 1][c].pop();
				} else if (target !== r) {
					// Move
					tileVals[target][c] = tileVals[r][c];
					tileVals[r][c] = 0;
					moved = true;
				}
			}
		}
	} else if (direction === 'down') {
		for (var c = 0; c < GRID_SIZE; c++) {
			for (var r = GRID_SIZE - 2; r >= 0; r--) {
				if (tileVals[r][c] === 0) continue;
				var target = r;
				while (target < GRID_SIZE - 1 && tileVals[target + 1][c] === 0) {
					target++;
				}
				if (target < GRID_SIZE - 1 && tileVals[target + 1][c] === tileVals[r][c] && !merged[target + 1][c]) {
					// Merge
					tileVals[target + 1][c] *= 2;
					score += tileVals[target + 1][c];
					tileVals[r][c] = 0;
					merged[target + 1][c] = true;
					moved = true;
					tiles[target + 1][c].pop();
				} else if (target !== r) {
					// Move
					tileVals[target][c] = tileVals[r][c];
					tileVals[r][c] = 0;
					moved = true;
				}
			}
		}
	}
	if (moved) {
		addRandomTile();
		updateTiles();
		updateScore();
		if (has2048()) {
			LK.showYouWin();
		} else if (!canMove()) {
			LK.effects.flashScreen(0xff0000, 1000);
			LK.showGameOver();
		}
	}
}
// Touch/drag/swipe handling
game.down = function (x, y, obj) {
	// Only start if inside board area
	if (x >= BOARD_X && x <= BOARD_X + BOARD_SIZE && y >= BOARD_Y && y <= BOARD_Y + BOARD_SIZE) {
		touchStartX = x;
		touchStartY = y;
		isTouching = true;
	}
};
game.move = function (x, y, obj) {
	if (!isTouching) return;
	touchEndX = x;
	touchEndY = y;
};
game.up = function (x, y, obj) {
	if (!isTouching) return;
	var dx = touchEndX - touchStartX;
	var dy = touchEndY - touchStartY;
	var absDx = Math.abs(dx);
	var absDy = Math.abs(dy);
	if (absDx > 50 || absDy > 50) {
		if (absDx > absDy) {
			if (dx > 0) {
				move('right');
			} else {
				move('left');
			}
		} else {
			if (dy > 0) {
				move('down');
			} else {
				move('up');
			}
		}
	}
	isTouching = false;
	touchStartX = 0;
	touchStartY = 0;
	touchEndX = 0;
	touchEndY = 0;
};
// Reset game on game over or win
game.on('reset', function () {
	initBoard();
});
// Initialize
initBoard();
// Play background music
LK.playMusic('arkaplan');