package com.adealink.weparty.im.session.comp.input

import com.adealink.frame.log.Log
import com.adealink.frame.mvvm.livedata.ExtMutableLiveData
import com.adealink.frame.util.isMainThread
import com.adealink.weparty.module.im.data.TAG_IM_INPUT_FLOW


//输入行为
enum class InputAction {
    //    MORE_CLICKED,//点击更多
    CLICK_INPUT, //点击输入框
    CLICK_EMOJI_BUTTON, //点击表情按钮
    CLICK_AUDIO, //点击录音
    CANCEL_AUDIO, //取消录音

    CLICK_IMAGE,
    EMPTY_CLICKED//空白状态

}

/**
 * 输入状态
 * @param priority 优先级,不能同一个操作导致多个相同优先级的事件
 */
enum class InputState(val priority: Int) {
    STATE_NONE(0),

    //    STATE_MORE_INPUT,
    STATE_SOFT_INPUT(1),
    STATE_EMOJI_INPUT(1),
    STATE_AUDIO_INPUT(1),
    STATE_IMAGE_INPUT(2),
}

class SessionInputMachine(
    private var currentState: InputState,
    private val transactionList: MutableList<InputMachineTransaction>,

    private val onTransaction: (transaction: InputMachineTransaction) -> Unit,
    private val onStateChanged: (lastState: InputState, state: InputState) -> Unit
) {

    fun getCurrentState(): InputState {
        return currentState
    }

    fun registerTransaction(
        page:String,
        currentState: InputState,
        action: InputAction,
        nextState: InputState
    ): InputMachineTransaction {
        val transaction = transactionList.find {
            it.currentState == currentState && it.action == action && it.nextState == nextState
        }
        if (transaction == null) {
            val newTransaction = InputMachineTransaction(page, currentState, action, nextState)
            transactionList.add(newTransaction)
            return newTransaction
        } else {
            return transaction
        }
    }

    fun execute(action: InputAction) {
        val nextStates = mutableSetOf<InputState>()
        val pendingTransactions = mutableListOf<InputMachineTransaction>()
        for (transaction in transactionList) {
            if (transaction.currentState == currentState && transaction.action == action) {
                Log.d(
                    TAG_IM_INPUT_FLOW,
                    "SessionInputMachine, ${transaction.page}, action:$action, $currentState => ${transaction.nextState}"
                )
                transaction.runEvent()
                pendingTransactions.add(transaction)
                nextStates.add(transaction.nextState)
            }
        }

        var nextState: InputState? = null
        for (state in nextStates) {
            if (nextState == null) {
                nextState = state
            } else if (nextState.priority < state.priority) {
                nextState = state
            } else if (nextState != state
                && nextState.priority > 0
                && nextState.priority == state.priority
            ) {
                throw IllegalStateException(
                    "InputMachineTransaction define error, action(${action}) => nextState(${
                        nextStates.joinToString(
                            separator = ","
                        )
                    })"
                )
            }
        }
        if (nextState != null) {
            notifyStateChanged(nextState)
        } else {
            Log.w(
                TAG_IM_INPUT_FLOW,
                "SessionInputMachine, action:$action can not find nextState(currentState:$currentState)"
            )
        }
//        for (transaction in pendingTransactions) {
//            transaction.runEvent()
//        }

    }

    private fun notifyStateChanged(nextState: InputState) {
        val lastState = currentState
        currentState = nextState
        onStateChanged.invoke(lastState, nextState)
    }

    fun clean() {
        currentState = InputState.STATE_NONE
    }
}

data class InputMachineTransaction(
    val page: String,
    val currentState: InputState,
    val action: InputAction,
    val nextState: InputState,
) {
    val event = ExtMutableLiveData<Unit>()

    init {
        if (currentState == InputState.STATE_NONE && nextState == InputState.STATE_NONE) {
            //重置操作
        } else if (currentState == nextState) {
            throw IllegalStateException("InputMachineTransaction define error, currentState(${currentState}) == nextState(${nextState})")
        }
    }

    fun runEvent() {
        if (isMainThread()) {
            event.setValue(Unit)
        } else {
            event.postValue(Unit)
            event.postValue(Unit)
        }
    }

    override fun hashCode(): Int {
        return "${currentState.ordinal}_${action.ordinal}_${nextState.ordinal}".hashCode()
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false

        other as InputMachineTransaction

        if (currentState != other.currentState) return false
        if (action != other.action) return false
        if (nextState != other.nextState) return false

        return true
    }
}