package com.atmob.keyboard_android.util.bridge

import com.atmob.keyboard_android.constant.FlutterHostConstants
import com.atmob.keyboard_android.enums.FlutterMethod
import com.atmob.keyboard_android.enums.host.HostMainTab
import com.atmob.keyboard_android.util.FlutterEngineHolder
import com.atmob.keyboard_android.util.FlutterPageLaunchUtil
import com.atmob.keyboard_android.util.bridge.event.DefaultKeyboardNativeEventHandler
import com.atmob.keyboard_android.util.bridge.method.KeyboardExposeNativeMethodHandler
import com.atmob.keyboard_android.util.bridge.model.base.EmptyResp
import com.atmob.keyboard_android.util.bridge.model.req.SuperReplyReq
import com.atmob.keyboard_android.util.bridge.model.req.SuperSpeakReq
import com.atmob.keyboard_android.util.bridge.model.resp.CharacterListResp
import com.atmob.keyboard_android.util.bridge.model.resp.KeyboardInfo
import com.atmob.keyboard_android.util.bridge.model.resp.KeyboardListResp
import com.atmob.keyboard_android.util.bridge.model.resp.PrologueListResp
import com.atmob.keyboard_android.util.bridge.model.resp.PrologueResp
import com.atmob.keyboard_android.util.bridge.model.resp.SuperReplyResp
import com.atmob.keyboard_android.util.bridge.model.resp.SuperSpeakResp
import com.atmob.keyboard_android.util.bridge.util.FlutterMethodCaller
import com.atmob.keyboard_android.util.bridge.util.NativeEventRegistry
import com.atmob.keyboard_android.util.bridge.util.NativeMethodRegistry

/**
 * 交互管理器，封装原生端和Flutter端的交互方法
 */
object FlutterBridgeManager : IBridgeApi {
    /**
     * 原生调Flutter
     */
    private val mFlutterMethodCaller = FlutterMethodCaller()

    /**
     * 暴露原生方法给Flutter调用
     */
    private val mNativeMethodRegistry = NativeMethodRegistry()

    /**
     * 暴露原生事件给Flutter接收
     */
    private val mNativeEventRegistry = NativeEventRegistry()

    /**
     * 键盘原生方法
     */
    private val mKeyboardNativeMethodHandler = KeyboardExposeNativeMethodHandler()

    init {
        val flutterEngine = FlutterEngineHolder.getFlutterEngine()
        if (flutterEngine == null) {
            throw IllegalArgumentException("FlutterEngine 未找到，MethodChannel 无法初始化")
        }
        mFlutterMethodCaller.init(flutterEngine)
        mNativeMethodRegistry.init(flutterEngine)
        mNativeEventRegistry.init(flutterEngine)
    }

    override fun isLogin(
        onSuccess: (Boolean) -> Unit,
        onFail: (errorCode: Int, errorMsg: String) -> Unit
    ) {
        mFlutterMethodCaller.callMethod<Boolean>(
            FlutterMethod.IS_LOGIN.methodName,
            isReturnJson = false,
            modelClazz = Boolean::class.java,
            onSuccess = onSuccess,
            onFail = onFail
        )
    }

    override fun isMember(
        onSuccess: (Boolean) -> Unit,
        onFail: (errorCode: Int, errorMsg: String) -> Unit
    ) {
        mFlutterMethodCaller.callMethod<Boolean>(
            FlutterMethod.IS_MEMBER.methodName,
            isReturnJson = false,
            modelClazz = Boolean::class.java,
            onSuccess = onSuccess,
            onFail = onFail
        )
    }

    override fun jump2SplashPage(quiesceJump: Boolean) {
        val path = FlutterHostConstants.PAGE_SPLASH
        if (quiesceJump) {
            FlutterPageLaunchUtil.onlyFlutterJumpPage(path)
        } else {
            FlutterPageLaunchUtil.jumpFlutterPage(path)
        }
    }

    override fun jump2LoginPage() {
        FlutterPageLaunchUtil.jumpFlutterPage(FlutterHostConstants.PAGE_LOGIN)
    }

    override fun jump2MainPage(mainTab: HostMainTab) {
        FlutterPageLaunchUtil.jumpFlutterPage(
            FlutterHostConstants.PAGE_MAIN, mapOf(
                FlutterHostConstants.KEY_TAB_NAME to mainTab.tabName
            ),
            // 因为是跳转到首页，所以清空上层页面
            offAll = true
        )
    }

    override fun jump2CustomCharacterPage() {
        FlutterPageLaunchUtil.jumpFlutterPage(FlutterHostConstants.PAGE_CHARACTER_CUSTOM)
    }

    override fun jump2VipStore() {
        FlutterPageLaunchUtil.jumpFlutterPage(FlutterHostConstants.PAGE_STORE)
    }

    override fun jump2IntimacyPage() {
        FlutterPageLaunchUtil.jumpFlutterPage(FlutterHostConstants.PAGE_INTIMACY_SCALE)
    }

    override fun getKeyboardList(
        onSuccess: (resultObj: KeyboardListResp) -> Unit,
        onFail: (errorCode: Int, errorMsg: String) -> Unit
    ) {
        mFlutterMethodCaller.callMethod<KeyboardListResp>(
            FlutterMethod.GET_KEYBOARD_LIST.methodName,
            modelClazz = KeyboardListResp::class.java,
            onSuccess = onSuccess,
            onFail = onFail
        )
    }

    override fun selectedKeyboard(
        keyboardId: String,
        onSuccess: (EmptyResp) -> Unit,
        onFail: (errorCode: Int, errorMsg: String) -> Unit
    ) {
        mFlutterMethodCaller.callMethod<EmptyResp>(
            FlutterMethod.SELECTED_KEY_BOARD.methodName,
            // 传递参数
            args = mapOf("keyboardId" to keyboardId),
            modelClazz = EmptyResp::class.java,
            onSuccess = onSuccess,
            onFail = onFail
        )
    }

    override fun getCurrentKeyboardInfo(
        onSuccess: (KeyboardInfo) -> Unit,
        onFail: (errorCode: Int, errorMsg: String) -> Unit
    ) {
        mFlutterMethodCaller.callMethod<KeyboardInfo>(
            FlutterMethod.GET_CURRENT_KEYBOARD_INFO.methodName,
            modelClazz = KeyboardInfo::class.java,
            onSuccess = onSuccess,
            onFail = onFail
        )
    }

    override fun getCharacterList(
        keyboardId: String,
        onSuccess: (CharacterListResp) -> Unit,
        onFail: (errorCode: Int, errorMsg: String) -> Unit
    ) {
        mFlutterMethodCaller.callMethod<CharacterListResp>(
            FlutterMethod.GET_CHARACTER_LIST.methodName,
            args = mapOf("keyboardId" to keyboardId),
            modelClazz = CharacterListResp::class.java,
            onSuccess = onSuccess,
            onFail = onFail
        )
    }

    override fun getPrologueList(
        onSuccess: (PrologueListResp) -> Unit,
        onFail: (errorCode: Int, errorMsg: String) -> Unit
    ) {
        mFlutterMethodCaller.callMethod<PrologueListResp>(
            FlutterMethod.GET_PROLOGUE_LIST.methodName,
            modelClazz = PrologueListResp::class.java,
            onSuccess = onSuccess,
            onFail = onFail
        )
    }

    override fun chatSuperReply(
        req: SuperReplyReq,
        onSuccess: (SuperReplyResp) -> Unit,
        onFail: (errorCode: Int, errorMsg: String) -> Unit
    ) {
        mFlutterMethodCaller.callMethod<SuperReplyResp>(
            FlutterMethod.CHAT_SUPER_REPLY.methodName,
            args = mapOf(
                "keyboardId" to req.keyboardId,
                "characterId" to req.characterId,
                "content" to req.content,
            ),
            modelClazz = SuperReplyResp::class.java,
            onSuccess = onSuccess,
            onFail = onFail
        )
    }

    override fun chatSuperSpeak(
        req: SuperSpeakReq,
        onSuccess: (SuperSpeakResp) -> Unit,
        onFail: (errorCode: Int, errorMsg: String) -> Unit
    ) {
        mFlutterMethodCaller.callMethod<SuperSpeakResp>(
            FlutterMethod.CHAT_SUPER_SPEAK.methodName,
            args = mapOf(
                "keyboardId" to req.keyboardId,
                "characterId" to req.characterId,
                "content" to req.content,
            ),
            modelClazz = SuperSpeakResp::class.java,
            onSuccess = onSuccess,
            onFail = onFail
        )
    }

    override fun chatPrologue(
        name: String,
        onSuccess: (PrologueResp) -> Unit,
        onFail: (errorCode: Int, errorMsg: String) -> Unit
    ) {
        mFlutterMethodCaller.callMethod<PrologueResp>(
            FlutterMethod.CHAT_PROLOGUE.methodName,
            args = mapOf(
                "name" to name,
            ),
            modelClazz = PrologueResp::class.java,
            onSuccess = onSuccess,
            onFail = onFail
        )
    }

    override fun exposeKeyboardOptMethod() {
        mNativeMethodRegistry.registerNativeMethod(mKeyboardNativeMethodHandler)
    }

    override fun cancelExposeKeyboardOptMethod() {
        mNativeMethodRegistry.unRegisterNativeMethod(mKeyboardNativeMethodHandler)
    }

    override fun registerDefaultKeyboardChangeEvent() {
        val eventChannelHandler = DefaultKeyboardNativeEventHandler()
        mNativeEventRegistry.registerNativeEvent(
            eventChannelHandler.onGetEventChannelName(),
            eventChannelHandler
        )
    }
}