package com.dong.maxhap.demos.game

import kotlin.random.Random

data class Game2048State(
    val grid: List<List<Int>>,
    val score: Int,
    val gameOver: Boolean,
    val won: Boolean
)

class Game2048Logic {
    
    companion object {
        const val GRID_SIZE = 4
        const val WIN_VALUE = 2048
    }
    
    fun doInitGrid(): List<List<Int>> {
        val grid = List(GRID_SIZE) { List(GRID_SIZE) { 0 } }
        return addRandomTile(addRandomTile(grid))
    }
    
    fun moveLeft(grid: List<List<Int>>): Pair<List<List<Int>>, Int> {
        var score = 0
        val newGrid = grid.map { row ->
            val filteredRow = row.filter { it != 0 }
            val mergedRow = mutableListOf<Int>()
            var i = 0
            while (i < filteredRow.size) {
                if (i < filteredRow.size - 1 && filteredRow[i] == filteredRow[i + 1]) {
                    val mergedValue = filteredRow[i] * 2
                    mergedRow.add(mergedValue)
                    score += mergedValue
                    i += 2
                } else {
                    mergedRow.add(filteredRow[i])
                    i++
                }
            }
            // 填充到GRID_SIZE长度
            while (mergedRow.size < GRID_SIZE) {
                mergedRow.add(0)
            }
            mergedRow
        }
        return Pair(newGrid, score)
    }
    
    fun moveRight(grid: List<List<Int>>): Pair<List<List<Int>>, Int> {
        val reversedGrid = grid.map { it.reversed() }
        val (movedGrid, score) = moveLeft(reversedGrid)
        val newGrid = movedGrid.map { it.reversed() }
        return Pair(newGrid, score)
    }
    
    fun moveUp(grid: List<List<Int>>): Pair<List<List<Int>>, Int> {
        val transposedGrid = transpose(grid)
        val (movedGrid, score) = moveLeft(transposedGrid)
        val newGrid = transpose(movedGrid)
        return Pair(newGrid, score)
    }
    
    fun moveDown(grid: List<List<Int>>): Pair<List<List<Int>>, Int> {
        val transposedGrid = transpose(grid)
        val (movedGrid, score) = moveRight(transposedGrid)
        val newGrid = transpose(movedGrid)
        return Pair(newGrid, score)
    }
    
    private fun transpose(grid: List<List<Int>>): List<List<Int>> {
        return List(GRID_SIZE) { col ->
            List(GRID_SIZE) { row ->
                grid[row][col]
            }
        }
    }
    
    fun addRandomTile(grid: List<List<Int>>): List<List<Int>> {
        val emptyCells = mutableListOf<Pair<Int, Int>>()
        for (i in grid.indices) {
            for (j in grid[i].indices) {
                if (grid[i][j] == 0) {
                    emptyCells.add(Pair(i, j))
                }
            }
        }
        
        if (emptyCells.isEmpty()) return grid
        
        val (row, col) = emptyCells.random()
        val newValue = if (Random.nextFloat() < 0.9f) 2 else 4
        return grid.mapIndexed { i, gridRow ->
            if (i == row) {
                gridRow.mapIndexed { j, cell ->
                    if (j == col) newValue else cell
                }
            } else {
                gridRow
            }
        }
    }
    
    fun hasEmptyCell(grid: List<List<Int>>): Boolean {
        return grid.any { row -> row.any { it == 0 } }
    }
    
    fun canMerge(grid: List<List<Int>>): Boolean {
        // 检查水平方向
        for (i in 0 until GRID_SIZE) {
            for (j in 0 until GRID_SIZE - 1) {
                if (grid[i][j] != 0 && grid[i][j] == grid[i][j + 1]) {
                    return true
                }
            }
        }
        
        // 检查垂直方向
        for (j in 0 until GRID_SIZE) {
            for (i in 0 until GRID_SIZE - 1) {
                if (grid[i][j] != 0 && grid[i][j] == grid[i + 1][j]) {
                    return true
                }
            }
        }
        
        return false
    }
    
    fun checkWin(grid: List<List<Int>>): Boolean {
        return grid.any { row -> row.any { it >= WIN_VALUE } }
    }
    
    fun checkGameOver(grid: List<List<Int>>): Boolean {
        return !hasEmptyCell(grid) && !canMerge(grid)
    }
}