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

/**
* author: PengWuliang
* date: 2025/9/8
* desc: 
*/
import android.app.Activity
import android.content.Context
import android.os.Build
import android.provider.Settings
import android.view.WindowManager
import com.adealink.frame.log.Log
import com.adealink.frame.util.AppUtil
import com.adealink.weparty.commonui.widget.floatview.BaseWindowManager
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.TAG_FLOAT_VIEW
import com.adealink.weparty.commonui.widget.floatview.view.BaseFloatView
import com.adealink.weparty.commonui.widget.floatview.view.BaseWindowFloatView
import java.util.concurrent.CopyOnWriteArrayList
import java.util.concurrent.CopyOnWriteArraySet

class SystemModeWindowManager : BaseWindowManager() {

    companion object {
        private const val SUB_TAG = "SystemModeWindowManager"
    }

    private val globalWindowManager =
        AppUtil.appContext.getSystemService(Context.WINDOW_SERVICE) as WindowManager
    private val viewList = mutableListOf<BaseFloatView<out IFloatData>>()
    private val viewTags = CopyOnWriteArraySet<String>()
    private val viewTypes = CopyOnWriteArraySet<FloatWindowType>()

    override fun addView(view: BaseFloatView<out IFloatData>) {
        val mView = view as? BaseWindowFloatView ?: return
        if ((Build.VERSION.SDK_INT < Build.VERSION_CODES.M
                    || Settings.canDrawOverlays(AppUtil.appContext)).not()
        ) {
            return
        }

        if (viewTags.contains(mView.baseFloatData.windowTag())) {
            Log.w(TAG_FLOAT_VIEW, "${mView.baseFloatData.windowTag()} is exist")
            return
        }
        viewTypes.add(mView.baseFloatData.windowType())
        viewTags.add(mView.baseFloatData.windowTag())
        viewList.add(mView)
        mView.setupWindowManager(this)
        mView.windowParams.type =
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
            else WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
        globalWindowManager.addView(mView, mView.windowParams)
        mView.onCreate()
        mView.onStart()
        mView.onResume()
        Log.i(TAG_FLOAT_VIEW, "$SUB_TAG, addView, view: $mView")
    }

    override fun removeView(
        view: BaseFloatView<out IFloatData>, reason: String
    ) {
        val mView = view as? BaseWindowFloatView ?: return
        if (!checkHasView(mView)) {
            return
        }
        globalWindowManager.removeViewImmediate(mView)
        viewTypes.remove(mView.baseFloatData.windowType())
        viewTags.remove(mView.baseFloatData.windowTag())
        viewList.remove(mView)
        mView.windowParams.token = null
        mView.onPause()
        mView.onStop()
        mView.onDestroy()
        Log.i(TAG_FLOAT_VIEW, "$SUB_TAG, removeView, reason: $reason, view: $mView")
    }

    override fun findFloatViewByType(type: FloatWindowType): BaseFloatView<out IFloatData>? {
        viewList.forEach {
            if (it.baseFloatData.windowType() == type) {
                return it
            }
        }
        return null
    }

    override fun isFloatViewAdded(type: FloatWindowType): Boolean {
        return findFloatViewByType(type) != null
    }

    override fun removeFloatViewByType(type: FloatWindowType, reason: String) {
        findFloatViewByType(type)?.removeSelf(reason)
    }

    override fun setFloatViewVisibility(type: FloatWindowType, visibility: Int) {
        findFloatViewByType(type)?.visibility = visibility
    }

    override fun removeAllFloatViews(type: FloatWindowType, reason: String) {
        viewList.forEach {
            if (it.baseFloatData.windowType() == type) {
                it.removeSelf(reason)
            }
        }
    }

    override fun findAllFloatViews(type: FloatWindowType): CopyOnWriteArrayList<BaseFloatView<out IFloatData>> {
        val allFloatViews = CopyOnWriteArrayList<BaseFloatView<out IFloatData>>()
        viewList.forEach {
            if (it.baseFloatData.windowType() == type) {
                allFloatViews.add(it)
            }
        }
        return allFloatViews
    }

    override fun remove(predicate: (BaseFloatView<out IFloatData>) -> Boolean, reason: String) {
        viewList.filter(predicate).forEach { view ->
            removeView(view, reason)
        }
    }

    private fun checkHasView(view: BaseFloatView<out IFloatData>): Boolean {
        if (!viewList.contains(view)) {
            Log.w(
                TAG_FLOAT_VIEW,
                "$SUB_TAG, checkHasView ${view.baseFloatData.windowTag()} is not exist maybe have bug"
            )
            return false
        }
        return true
    }

    override fun onScreenOn() {
        super.onScreenOn()
        viewList.forEach {
            it.onResume()
        }
    }

    override fun onScreenOff() {
        super.onScreenOff()
        viewList.forEach {
            it.onPause()
        }
    }

    override fun onActivityChange(activity: Activity) {
        viewList.forEach { floatView ->
            floatView.onActivityChange(activity)
        }
    }

    override fun onEnterBackground() {
        super.onEnterBackground()
        viewList.forEach { floatView ->
            floatView.onEnterBackground()
        }
    }

    override fun onEnterForeground() {
        super.onEnterForeground()
        viewList.forEach { floatView ->
            floatView.onEnterForeground()
        }
    }
}