package com.adealink.weparty.commonui.widget.floatview

import android.app.Activity
import android.os.Build
import com.adealink.frame.log.Log
import com.adealink.frame.util.getDeviceName
import com.adealink.weparty.commonui.widget.floatview.data.FloatWindowType
import com.adealink.weparty.commonui.widget.floatview.data.IFloatData
import com.adealink.weparty.commonui.widget.floatview.data.MODE_APPLICATION
import com.adealink.weparty.commonui.widget.floatview.data.MODE_SYSTEM
import com.adealink.weparty.commonui.widget.floatview.data.TAG_FLOAT_VIEW
import com.adealink.weparty.commonui.widget.floatview.mode.ApplicationModeWindowManager
import com.adealink.weparty.commonui.widget.floatview.mode.SystemModeWindowManager
import com.adealink.weparty.commonui.widget.floatview.mode.fix.Android10FixApplicationModeWindowManager
import com.adealink.weparty.commonui.widget.floatview.mode.fix.Android14ModeWindowManager
import com.adealink.weparty.commonui.widget.floatview.view.BaseFloatView
import java.util.concurrent.CopyOnWriteArrayList

class ModeWindowManagerProxy : BaseWindowManager() {

    private val windowManagerMap = LinkedHashMap<Int, BaseWindowManager>().apply {
        put(MODE_SYSTEM, SystemModeWindowManager())
        put(
            MODE_APPLICATION,
            if (Build.VERSION.SDK_INT == Build.VERSION_CODES.UPSIDE_DOWN_CAKE && getDeviceName().lowercase().startsWith("moto")) {
                Android14ModeWindowManager()
            } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
                Android10FixApplicationModeWindowManager(ApplicationModeWindowManager())
            } else {
                ApplicationModeWindowManager()
            }
        )
    }

    override fun addView(view: BaseFloatView<out IFloatData>) {
        try {
            windowManagerMap[view.baseFloatData.windowMode()]?.addView(view)
        } catch (e: Exception) {
            Log.e(TAG_FLOAT_VIEW, "ModeWindowManagerProxy addView $e")
        }
    }

    override fun removeView(
        view: BaseFloatView<out IFloatData>, reason: String
    ) {
        try {
            windowManagerMap[view.baseFloatData.windowMode()]?.removeView(view, reason)
        } catch (e: Exception) {
            Log.e(TAG_FLOAT_VIEW, "ModeWindowManagerProxy removeView $e")
        }
    }

    override fun findFloatViewByType(type: FloatWindowType): BaseFloatView<out IFloatData>? {
        windowManagerMap.values.forEach {
            val result = it.findFloatViewByType(type)
            if (result != null) {
                return result
            }
        }
        return null
    }

    override fun isFloatViewAdded(type: FloatWindowType): Boolean {
        var isViewAdded = false
        windowManagerMap.values.forEach {
            val result = it.isFloatViewAdded(type)
            isViewAdded = isViewAdded or result
        }
        return isViewAdded
    }

    override fun removeFloatViewByType(type: FloatWindowType, reason: String) {
        windowManagerMap.values.forEach {
            it.removeFloatViewByType(type, reason)
        }
    }

    override fun setFloatViewVisibility(type: FloatWindowType, visibility: Int) {
        windowManagerMap.values.forEach {
            val result = it.findFloatViewByType(type)
            if (result != null) {
                result.visibility = visibility
                Log.i(
                    TAG_FLOAT_VIEW,
                    "setFloatViewVisibility, type: $type, visibility: $visibility, floatView: $result"
                )
                return@forEach
            }
        }
    }

    private fun getActivityName(activity: Activity): String {
        return activity::class.java.simpleName
    }

    override fun onCreate(activity: Activity) {
        Log.i(TAG_FLOAT_VIEW, "[${getActivityName(activity)}]: onCreate")
        windowManagerMap.values.forEach {
            it.onCreate(activity)
        }
    }

    override fun onStart(activity: Activity) {
        Log.i(TAG_FLOAT_VIEW, "[${getActivityName(activity)}]: onStart")
        windowManagerMap.values.forEach {
            it.onStart(activity)
        }
    }

    override fun onResume(activity: Activity) {
        Log.i(TAG_FLOAT_VIEW, "[${getActivityName(activity)}]: onResume")
        windowManagerMap.values.forEach {
            it.onResume(activity)
        }
    }

    override fun onPause(activity: Activity) {
        Log.i(TAG_FLOAT_VIEW, "[${getActivityName(activity)}]: onPause")
        windowManagerMap.values.forEach {
            it.onPause(activity)
        }
    }

    override fun onStop(activity: Activity) {
        Log.i(TAG_FLOAT_VIEW, "[${getActivityName(activity)}]: onStop")
        windowManagerMap.values.forEach {
            it.onStop(activity)
        }
    }

    override fun onDestroy(activity: Activity) {
        super.onDestroy(activity)
        Log.i(TAG_FLOAT_VIEW, "[${getActivityName(activity)}]: onDestroy")
        windowManagerMap.values.forEach {
            it.onDestroy(activity)
        }
    }

    override fun onSaveInstanceState(activity: Activity) {
        Log.i(TAG_FLOAT_VIEW, "[${getActivityName(activity)}]: onSaveInstanceState")
        windowManagerMap.values.forEach {
            it.onSaveInstanceState(activity)
        }
    }

    override fun onScreenOn() {
        Log.i(TAG_FLOAT_VIEW, "onScreenOn")
        windowManagerMap.values.forEach {
            it.onScreenOn()
        }
    }

    override fun onScreenOff() {
        Log.i(TAG_FLOAT_VIEW, "onScreenOff")
        windowManagerMap.values.forEach {
            it.onScreenOff()
        }
    }

    override fun onEnterBackground() {
        Log.i(TAG_FLOAT_VIEW, "onEnterBackground")
        windowManagerMap.values.forEach {
            it.onEnterBackground()
        }
    }

    override fun onEnterForeground() {
        Log.i(TAG_FLOAT_VIEW, "onEnterForeground")
        windowManagerMap.values.forEach {
            it.onEnterForeground()
        }
    }

    override fun notifyWhenActivityChanged(activity: Activity) {
        Log.i(TAG_FLOAT_VIEW, "notifyWhenActivityChanged => $activity")
        windowManagerMap.values.forEach {
            it.notifyWhenActivityChanged(activity)
        }
    }

    override fun removeAllFloatViews(type: FloatWindowType, reason: String) {
        Log.i(TAG_FLOAT_VIEW, "removeAllFloatViews, type: $type, reason: $reason")
        windowManagerMap.values.forEach {
            it.removeAllFloatViews(type, reason)
        }
    }

    override fun findAllFloatViews(type: FloatWindowType): CopyOnWriteArrayList<BaseFloatView<out IFloatData>> {
        val allFloatViews = CopyOnWriteArrayList<BaseFloatView<out IFloatData>>()
        windowManagerMap.values.forEach {
            allFloatViews.addAll(it.findAllFloatViews(type))
        }
        return allFloatViews
    }

    override fun remove(predicate: (BaseFloatView<out IFloatData>) -> Boolean, reason: String) {
        Log.i(TAG_FLOAT_VIEW, "remove, reason: $reason")
        windowManagerMap.values.forEach {
            it.remove(predicate, reason)
        }
    }
}