package com.gogame.minesweeper.swipe

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.media.MediaPlayer
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.ScaleGestureDetector
import android.widget.GridLayout
import com.gogame.minesweeper.bean.CellState
import com.gogame.minesweeper.DifficultyLevel
import com.gogame.minesweeper.bean.GameState
import com.gogame.minesweeper.R
import com.google.gson.Gson
import kotlin.math.abs


class SwipeGridLayout @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0,
    var xLength: Int = 9,   // 网格的行数
    var yLength: Int = 9,   // 网格的列数
    var mineNum: Int = 10    // 地雷的数量
) : GridLayout(context, attrs, defStyleAttr) {
    private val sharedPreferences =
        context.getSharedPreferences("minesweeper_prefs", Context.MODE_PRIVATE)
    private var myLevel = DifficultyLevel.BEGINNER
    private var minutes = 0
    private var seconds = 0

    // 固定格子初始大小
    private var fixedSize = 98

    // 点击音效的MediaPlayer
    private var clickSoundPlayer: MediaPlayer = MediaPlayer.create(context, R.raw.tile)

    // 长按音效的MediaPlayer
    private var clickLongSoundPlayer: MediaPlayer = MediaPlayer.create(context, R.raw.flag)

    private fun playClickSound() {
        if (!clickSoundPlayer.isPlaying) {
            clickSoundPlayer.start()
        }
    }

    private fun playLongClickSound() {
        if (!clickLongSoundPlayer.isPlaying) {
            clickLongSoundPlayer.start()
        }
    }

    var goods: Int//标记剩余未点开的非雷格子，用于判断游戏胜利
    var started = false//是否已经点击过第一个格子
    private var scaleFactor = 1.0f  // 初始缩放比例
    private var scaleGestureDetector: ScaleGestureDetector
    private var isScaling = false // 是否正在缩放

    init {
        goods = xLength * yLength - mineNum// 初始化非雷格子数

        // 初始化缩放手势检测器
        scaleGestureDetector = ScaleGestureDetector(context, ScaleListener())
    }


    private inner class ScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener() {
        override fun onScaleBegin(detector: ScaleGestureDetector): Boolean {
            // 缩放开始时，设置标志位为 true
            isScaling = true
            return super.onScaleBegin(detector)
        }

        override fun onScale(detector: ScaleGestureDetector): Boolean {
            // 更新缩放比例
            scaleFactor *= detector.scaleFactor

            // 限制缩放比例在 0.5x 到 3x 之间
            scaleFactor = scaleFactor.coerceIn(0.5f, 1.5f)

            // 请求重新布局
            requestLayout()
            return true
        }

        override fun onScaleEnd(detector: ScaleGestureDetector) {
            // 缩放结束时，重置标志位为 false
            isScaling = false
            super.onScaleEnd(detector)
        }
    }


    // 在填充格子时，初始化为固定大小
    fun fillAll() {
        removeAllViews()
        rowCount = xLength
        columnCount = yLength
        for (j in 0 until xLength) {
            for (i in 0 until yLength) {
                val one = SingleView(context, i, j, this)
                addView(one, fixedSize, fixedSize) // 使用固定大小
            }
        }
    }

    private var lastX = 0f
    private var lastY = 0f
    override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
        val x = event.x
        val y = event.y


        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                lastX = x
                lastY = y

                Log.d("ocean", "onInterceptTouchEvent ACTION_DOWN")
                Log.d(
                    "ocean",
                    "onInterceptTouchEvent ACTION_DOWN width->${width} height->${height}"
                )
            }

            MotionEvent.ACTION_MOVE -> {
                val deltaX = x - lastX
                val deltaY = y - lastY

                // 判断是否已经拖动，并且是否超过最小拖动距离
                if (abs(deltaX) > 10 || abs(deltaY) > 10) {
                    Log.d("ocean", "onInterceptTouchEvent ACTION_MOVE")
                    // 开始处理拖动时，拦截事件
                    return true
                }
            }
        }
        return super.onInterceptTouchEvent(event)
    }

    override fun onLayout(
        changed: Boolean,
        left: Int,
        top: Int,
        right: Int,
        bottom: Int
    ) {
        super.onLayout(changed, left, top, right, bottom)

        // 遍历所有的子视图，调整每个格子的大小
        val childSize = (fixedSize * scaleFactor).toInt() // 缩放后的格子大小
        for (i in 0 until childCount) {
            val child = getChildAt(i)
            val row = i / columnCount
            val col = i % columnCount

            // 根据缩放后的大小设置每个子视图的位置和大小
            val childLeft = col * childSize
            val childTop = row * childSize
            child.layout(
                childLeft,
                childTop,
                childLeft + childSize,
                childTop + childSize
            )
        }
    }

    override fun requestLayout() {
        super.requestLayout()
        invalidate()
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {

        // 让 scaleGestureDetector 处理缩放事件
        scaleGestureDetector.onTouchEvent(event)
        // 如果正在缩放，阻止其他事件处理
        if (isScaling) {
            return true
        }

        val x = event.x
        val y = event.y

        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                Log.d("ocean", "onTouchEvent ACTION_DOWN")
                lastX = x
                lastY = y
            }

            MotionEvent.ACTION_MOVE -> {
                Log.d("ocean", "onTouchEvent ACTION_MOVE x->${event.x} y->${event.y}")
                Log.d("ocean", "onTouchEvent ACTION_MOVE lastX->${lastX} lastY->${lastY}")
                val dx = event.x - lastX
                val dy = event.y - lastY
                // 移动整个布局
                scrollBy(-dx.toInt(), -dy.toInt())
                lastX = event.x
                lastY = event.y

                Log.d("ocean", "onTouchEvent ACTION_MOVE dx->$dx dy->$dy")
                return true
            }

            MotionEvent.ACTION_UP -> {
                Log.d("ocean", "onTouchEvent ACTION_UP")
            }

            MotionEvent.ACTION_CANCEL -> {
                Log.d("ocean", "onTouchEvent ACTION_CANCEL")
            }
        }
        return super.onTouchEvent(event)
    }

    // 处理网格点击事件
    fun onChildClicked(v: SingleView, x: Int, y: Int) {

        playClickSound()
        // 如果这是第一个点击，初始化游戏
        if (!started) {
            initCurGame(x, y)
            started = true
            listener?.onStart(mineNum)
        }
        // 初始化完游戏之后 每一次（包括第一次）按下之后的逻辑
        when (v.logicState) {
            SingleView.LOGICSTATE_BOMB -> {
                doEachSingle { singleView ->
                    if (singleView.logicState == SingleView.LOGICSTATE_BOMB) {
                        singleView.viewState = SingleView.VIEWSTATE_THUNDER
                    }
                    singleView.enable = false
                }
                v.viewState = SingleView.VIEWSTATE_BOMB
                listener?.defeat()

                clearGameStateSP()
            }

            in 1..8 -> { // 显示周围的雷数
                v.viewState = SingleView.VIEWSTATE_TIP
                goods--
            }

            0 -> {// 如果点击的格子周围没有雷，展开周围的格子
                openAround(v, LogicHelper.getIndexByXY(xLength, yLength, x, y))
            }
        }

        v.enable = false  // 禁止再次点击已经翻开的格子
        doEachSingle { singleView -> singleView.updateInsideImg() }
        // 判断是否胜利
        if (goods <= 0) {
            listener?.victory()
            doEachSingle { singleView -> singleView.enable = false }

            clearGameStateSP()
        }
    }

    // 打开周围的非雷格子
    private fun openAround(v: SingleView, index: Int) {
        v.enable = false
        v.viewState = SingleView.VIEWSTATE_TIP
        goods--
        for (around in LogicHelper.getAroundItems(xLength, yLength, index)) {
            val item = getChildByIndex(around)
            if (item.viewState == SingleView.VIEWSTATE_DEFAULT && item.logicState >= 0) {
                if (item.around == 0) {
                    openAround(getChildByIndex(around), around)
                } else {
                    item.enable = false
                    item.viewState = SingleView.VIEWSTATE_TIP
                    goods--
                }
            }
        }
    }

    // 初始化当前游戏，设置地雷
    private fun initCurGame(firstX: Int, firstY: Int) {
        goods = xLength * yLength - mineNum
        //初始化所有格子
        initAllChildBefore()
        // 随机布雷，确保第一个点击的不是雷
        val randomMines = LogicHelper.randomMines(xLength, yLength, firstX, firstY, mineNum)
        for (i: Int in randomMines) {
            val singleView = getChildByIndex(i)
            singleView.logicState = SingleView.LOGICSTATE_BOMB
            singleView.viewState = SingleView.VIEWSTATE_DEFAULT//test 显示雷
            singleView.updateInsideImg()
        }
        calMinesAround(randomMines)
    }

    // 计算每个格子周围的雷数
    private fun calMinesAround(randomMines: ArrayList<Int>) {
        for (i: Int in randomMines) {
            for (j in LogicHelper.getAroundItems(xLength, yLength, i)) {
                val view = getChildByIndex(j)
                view.around++
                if (view.logicState >= 0)//如果不是雷的话
                    view.logicState = view.around
                view.updateInsideImg()
            }
        }
    }

    private fun getChildByIndex(index: Int): SingleView {
        return getChildAt(index) as SingleView
    }

    private fun initAllChildBefore() {
        doEachSingle { singleView: SingleView ->
            singleView.logicState = 0//初始化逻辑状态 Default
            singleView.viewState = SingleView.VIEWSTATE_DEFAULT//
            singleView.around = 0
            singleView.updateInsideImg()
        }
    }

    var flags = 0
    fun onChildLongClicked(v: SingleView, x: Int, y: Int, viewState: Int) {
        playLongClickSound()
        when (viewState) {
            SingleView.VIEWSTATE_FLAG -> flags++
            SingleView.VIEWSTATE_UNSURE -> flags--
        }
        listener?.onFlagsChange(flags, mineNum - flags)
    }

    fun getChildByXY(x: Int, y: Int): SingleView {
        return getChildAt(y * columnCount + x) as SingleView
    }

    private fun doEachSingle(m: (singleView: SingleView) -> Unit) {
        for (i in 0..childCount - 1) {
            m(getChildByIndex(i))
        }
    }

    //传送难度数据
    fun setDifficulty(level: DifficultyLevel) {
        this.xLength = level.xLength
        this.yLength = level.yLength
        this.mineNum = level.mineNum
        this.myLevel = level
    }

    //传送时间
    fun setTime(min: Int, sec: Int) {
        this.minutes = min
        this.seconds = sec

        //每一秒都进行存储
        saveGameState()
    }

    /**
     * 开始
     */
    fun reset() {
        doEachSingle { singleView ->
            flags = 0
            goods = xLength * yLength - mineNum
            started = false//要点击第一个之后才会变成true
            singleView.reset()
            singleView.updateInsideImg()
        }
    }


    var listener: GameStateChange? = null

    interface GameStateChange {
        fun onStart(rest: Int)
        fun onFlagsChange(flags: Int, rest: Int)
        fun victory()
        fun defeat()
    }

    /**
     * 画分割线
     */
    override fun dispatchDraw(canvas: Canvas) {
        super.dispatchDraw(canvas)
        if (childCount <= 0) return
        val column = columnCount
        val childCount = childCount
        val localPaint = Paint()
        localPaint.style = Paint.Style.STROKE
        localPaint.setColor(Color.parseColor("#303030"))
        localPaint.isAntiAlias = true
        localPaint.strokeWidth = 1f
        for (i in 0 until childCount) {
            val cellView = getChildAt(i)
            if (i < columnCount) {
                canvas.drawLine(
                    cellView.left.toFloat(),
                    cellView.top.toFloat(),
                    cellView.right.toFloat(),
                    cellView.top.toFloat(),
                    localPaint
                )
            }
            if (i % columnCount == 0) {
                canvas.drawLine(
                    cellView.left.toFloat(),
                    cellView.top.toFloat(),
                    cellView.left.toFloat(),
                    cellView.bottom.toFloat(),
                    localPaint
                )
            }
            canvas.drawLine(
                cellView.right.toFloat(),
                cellView.top.toFloat(),
                cellView.right.toFloat(),
                cellView.bottom.toFloat(),
                localPaint
            )
            canvas.drawLine(
                cellView.left.toFloat(),
                cellView.bottom.toFloat(),
                cellView.right.toFloat(),
                cellView.bottom.toFloat(),
                localPaint
            )
        }
        if (childCount % column != 0) {
            for (j in 0 until column - childCount % column) {
                val lastView = getChildAt(childCount - 1)
                canvas.drawLine(
                    (lastView.right + lastView.width * j).toFloat(),
                    lastView.top.toFloat(),
                    (lastView.right + lastView.width * j).toFloat(),
                    lastView.bottom.toFloat(),
                    localPaint
                )
            }
        }
    }

    fun onPlayerRelease() {
        clickSoundPlayer.release() // 释放资源
        clickLongSoundPlayer.release()
    }

    fun clearGameStateSP() {
        val editor = sharedPreferences.edit()
        editor.remove("game_state")
        editor.apply()
    }

    fun saveGameState() {
        val gridState = Array(xLength) {
            Array(yLength) {
                CellState(
                    0,
                    SingleView.VIEWSTATE_DEFAULT, 0
                )
            }
        }

        // 填充格子的状态
        for (y in 0 until xLength) {
            for (x in 0 until yLength) {
                val singleView = getChildByXY(x, y)
                gridState[y][x] =
                    CellState(singleView.logicState, singleView.viewState, singleView.around)
            }
        }

        val gameState = GameState(gridState, goods, myLevel, minutes, seconds)
        val json = Gson().toJson(gameState)


        val editor = sharedPreferences.edit()
        // 保存的游戏状态json
        editor.putString("game_state", json)
        // 提交保存
        editor.apply()
    }

    fun loadGameState() {
        // 获取保存的游戏状态 JSON 字符串
        val gameStateJson = sharedPreferences.getString("game_state", null)
        if (gameStateJson.isNullOrEmpty()) {
            return
        }
        val gameState: GameState = Gson().fromJson(gameStateJson, GameState::class.java)
        //如果保存的难度和进来的难度不一致则不往下执行。
        if (gameState.difficulty != myLevel) {
            return
        }
        // 恢复格子的状态
        for (y in 0 until xLength) {
            for (x in 0 until yLength) {
                val singleView = getChildByXY(x, y)
                val cellState = gameState.grid[y][x]
                singleView.logicState = cellState.logicState
                singleView.viewState = cellState.viewState
                singleView.around = cellState.around
                singleView.updateInsideImg() // 更新格子显示
            }
        }
        goods = gameState.remainingMines
        mineNum = gameState.difficulty.mineNum
        started = true
    }

}