package com.atmob.keyboard_android.util.bridge.util

import android.os.Handler
import android.os.Looper
import com.atmob.keyboard_android.constant.PluginConfig
import com.atmob.keyboard_android.util.JsonUtil
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

/**
 * Flutter方法调用者
 */
class FlutterMethodCaller {
    /**
     * 用于与 Flutter 端通信的 MethodChannel
     */
    private lateinit var mMethodChannel: MethodChannel

    /**
     * 主线程Handler，用于Flutter回调安卓端时，在主线程回调外部
     */
    private val mMainHandler = Handler(Looper.getMainLooper())

    /**
     * 初始化
     */
    fun init(engine: FlutterEngine) {
        mMethodChannel = MethodChannel(
            engine.dartExecutor.binaryMessenger,
            PluginConfig.FLUTTER_METHOD_CHANNEL_NAME
        )
    }

    /**
     * 调用Flutter方法
     *
     * @param methodName 方法名
     * @param modelClazz 方法返回值类型
     * @param isReturnJson 方法是否返回json格式
     * @param onSuccess 成功回调
     * @param onFail 失败回调
     */
    fun <T> callMethod(
        methodName: String,
        args: Any? = null,
        modelClazz: Class<T>,
        isReturnJson: Boolean = true,
        onSuccess: ((resultObj: T) -> Unit)? = null,
        onFail: ((msg: String) -> Unit)? = null
    ) {
        mMethodChannel.invokeMethod(methodName, args, object : MethodChannel.Result {
            override fun success(result: Any?) {
                if (isReturnJson) {
                    try {
                        val resultJson = result.toString()
                        val resultObj = JsonUtil.parseJsonByClass<T>(resultJson, modelClazz)
                        runOnUIThread {
                            onSuccess?.invoke(resultObj)
                        }
                    } catch (e: Throwable) {
                        runOnUIThread {
                            onFail?.invoke(e.message ?: "call error")
                        }
                    }
                } else {
                    // 返回值，不是json，那么直接返回对象
                    runOnUIThread {
                        onSuccess?.invoke(result as T)
                    }
                }
            }

            override fun error(errorCode: String, errorMessage: String?, errorDetails: Any?) {
                runOnUIThread {
                    onFail?.invoke(errorMessage ?: "call error")
                }
            }

            override fun notImplemented() {
                runOnUIThread {
                    onFail?.invoke("method not implemented")
                }
            }
        })
    }

    /**
     * 在主线程运行回调
     */
    private fun runOnUIThread(callback: () -> Unit) {
        // 如果已经在主线程了，直接回调
        if (Looper.getMainLooper().thread == Thread.currentThread()) {
            callback.invoke()
        } else {
            // 不在主线程，则切到主线程后，再回调
            mMainHandler.post {
                callback.invoke()
            }
        }
    }
}