package com.atmob.keyboard_android.component.base

import android.content.Context
import android.util.AttributeSet
import com.atmob.keyboard_android.component.base.interceptor.InterceptorCallback
import com.atmob.keyboard_android.component.base.interceptor.RouteCallback
import com.atmob.keyboard_android.component.base.interceptor.RouteInterceptorManager

/**
 * 带路由功能的组件
 */
class RouteComponent @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : GroupComponent(context, attrs, defStyleAttr) {
    /**
     * 路由切换子组件，也就是先隐藏掉所有兄弟组件，再显示自己
     *
     * @param mutex 是否互斥，如果为true，则会隐藏其他子组件后，再显示自己，为false则是不隐藏兄弟组件，直接显示自己
     */
    fun <T : IUIComponent> routeChildComponent(
        targetComponentClass: Class<T>,
        mutex: Boolean = false,
        routeCallback: RouteCallback? = null
    ) {
        // 获取所有直接子组件
        val directChildComponentList = getDirectChildComponentList()

        // 找到目标组件
        val targetComponent: IUIComponent? = directChildComponentList.find {
            // 检查当前子View，是否是目标类型
            targetComponentClass.isInstance(it)
        }

        val routeAction = {
            // 找到兄弟组件
            if (mutex) {
                val siblingComponentList = directChildComponentList.filter {
                    !targetComponentClass.isInstance(it)
                }.toList()
                // 先隐藏所有兄弟
                siblingComponentList.forEach {
                    it.hide()
                }
            }
            // 将自己的层级，移动到父View的最顶层，从而覆盖住兄弟组件
            targetComponent?.asView()?.parent?.bringChildToFront(targetComponent.asView())
            // 再显示自己
            targetComponent?.show()
        }

        // 找不到目标组件，路由失败
        if (targetComponent == null) {
            routeCallback?.onLost()
        } else {
            // 找到目标组件
            routeCallback?.onFound(targetComponent)

            // 路由前，执行路由拦截器
            RouteInterceptorManager.executeInterceptors(
                targetComponent,
                object : InterceptorCallback {
                    override fun onContinue() {
                        // 拦截器放行，继续路由
                        routeAction.invoke()
                    }

                    override fun onInterrupt(error: Throwable) {
                        // 路由被拦截器拦截了，回调外部
                        routeCallback?.onInterrupt(targetComponent, error)
                    }
                })
        }
    }
}