package com.adealink.weparty.room.sdk.controller

import android.os.Handler
import androidx.annotation.CallSuper
import com.adealink.frame.coroutine.dispatcher.Dispatcher.remove
import com.adealink.frame.coroutine.dispatcher.Dispatcher.submit
import com.adealink.frame.data.collections.ConcurrentList
import com.adealink.frame.room.data.FlowStateInfo
import com.adealink.frame.room.data.RoomState
import com.adealink.frame.room.listener.IListener
import com.adealink.weparty.room.sdk.context.IRoomContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.android.asCoroutineDispatcher
import java.util.concurrent.atomic.AtomicBoolean

abstract class BaseController<L : IListener>(
    open val ctx: IRoomContext,
    val serialHandler: Handler
) : IController<L>, CoroutineScope {
    override val coroutineContext = SupervisorJob() + serialHandler.asCoroutineDispatcher()
    var dispatch: AtomicBoolean = AtomicBoolean(false)

    val listeners = ConcurrentList<L>()

    override fun addListener(l: L) {
        listeners.add(l)
    }

    override fun removeListener(l: L) {
        listeners.remove(l)
    }

    override fun clearListener() {
        listeners.clear()
    }

    @CallSuper
    open fun onCreate() {
    }

    @CallSuper
    open fun onResume() {
        dispatch = AtomicBoolean(true)
    }

    @CallSuper
    open fun onPause() {
        dispatch = AtomicBoolean(false)
    }

    @CallSuper
    open fun onDestroy() {
    }

    @CallSuper
    open fun onClear() {
    }

    @CallSuper
    override fun onRoomStateChanged(
        fromState: RoomState,
        toState: RoomState,
        flowStateInfo: FlowStateInfo,
    ) {
        when (toState) {
            RoomState.ROOM_IN -> {
                onRoomIn(flowStateInfo)
            }
            RoomState.ROOM_LEAVE -> {
                onRoomLeaved(flowStateInfo)
            }
            else -> {}
        }
    }

    open fun onRoomIn(flowStateInfo: FlowStateInfo) {}

    open fun onRoomLeaved(flowStateInfo: FlowStateInfo) {}

    fun runOnSerialHandler(runnable: Runnable, delay: Long = 0L) {
        serialHandler.submit(runnable, delay)
    }

    fun removeFromSerialHandler(runnable: Runnable) {
        serialHandler.remove(runnable)
    }

}