package com.adealink.weparty.room.sdk.service

import com.adealink.frame.coroutine.dispatcher.Dispatcher
import com.adealink.frame.media.IMediaRtcService
import com.adealink.frame.room.listener.IListener
import com.adealink.frame.room.supplier.IAppSupplier
import com.adealink.weparty.room.sdk.controller.BaseController
import com.adealink.weparty.room.sdk.controller.IAttrController
import com.adealink.weparty.room.sdk.controller.IController
import com.adealink.weparty.room.sdk.controller.IDeviceController
import com.adealink.weparty.room.sdk.controller.IJoinController
import com.adealink.weparty.room.sdk.controller.IMemberController
import com.adealink.weparty.room.sdk.controller.IMessageController
import com.adealink.weparty.room.sdk.controller.ISeatController
import com.adealink.weparty.room.sdk.controller.impl.AttrController
import com.adealink.weparty.room.sdk.controller.impl.DeviceController
import com.adealink.weparty.room.sdk.controller.impl.JoinController
import com.adealink.weparty.room.sdk.controller.impl.MemberController
import com.adealink.weparty.room.sdk.controller.impl.MessageController
import com.adealink.weparty.room.sdk.controller.impl.SeatController
import com.adealink.weparty.room.sdk.listener.IAttrListener
import com.adealink.weparty.room.sdk.listener.IDeviceListener
import com.adealink.weparty.room.sdk.listener.IJoinListener
import com.adealink.weparty.room.sdk.listener.IMemberListener
import com.adealink.weparty.room.sdk.listener.IMessageListener
import com.adealink.weparty.room.sdk.listener.ISeatListener
import com.adealink.weparty.room.sdk.supplier.AppSupplier

/**
 */

val roomService by lazy { RoomService(AppSupplier()).apply { create() } }

class RoomService(override val appSupplier: IAppSupplier) : IRoomService {

    private val serialHandler = Dispatcher.getSerialHandler()

    override val joinController: IJoinController<IJoinListener> by lazy { JoinController(this, serialHandler) }
    override val attrController: IAttrController<IAttrListener> by lazy { AttrController(this, serialHandler) }
    override val memberController: IMemberController<IMemberListener> by lazy { MemberController(this, serialHandler) }
    override val seatController: ISeatController<ISeatListener> by lazy { SeatController(this, serialHandler) }
    override val deviceController: IDeviceController<IDeviceListener> by lazy { DeviceController(this, serialHandler) }

    override val messageController: IMessageController<IMessageListener> by lazy { MessageController(this, serialHandler) }
    override val controllers: MutableList<BaseController<out IListener>> = arrayListOf()

    override val mediaService: IMediaRtcService
        get() = appSupplier.mediaService

    override val roomService: IRoomService
        get() = this

    private var lifecycleState: LifecycleState = LifecycleState.DESTROY

    private fun addController(controller: IController<out IListener>) {
        (controller as? BaseController<out IListener>)?.let { controllers.add(it) }
    }

    override fun create() {
        synchronized(lifecycleState) {
            if (lifecycleState == LifecycleState.DESTROY) {
                lifecycleState = LifecycleState.CREATE
                addController(joinController)
                addController(seatController)
                addController(attrController)
                addController(memberController)
                addController(deviceController)
                addController(messageController)
                controllers.onEach { it.onCreate() }
            }
        }
    }

    override fun resume() {
        synchronized(lifecycleState) {
            if (lifecycleState == LifecycleState.CREATE || lifecycleState == LifecycleState.PAUSE) {
                lifecycleState = LifecycleState.RESUME
                controllers.onEach { it.onResume() }
            }
        }
    }

    override fun pause() {
        synchronized(lifecycleState) {
            if (lifecycleState == LifecycleState.RESUME) {
                lifecycleState = LifecycleState.PAUSE
                controllers.onEach { it.onPause() }
            }
        }
    }

    override fun destroy() {
        synchronized(lifecycleState) {
            if (lifecycleState != LifecycleState.DESTROY) {
                lifecycleState = LifecycleState.DESTROY
                controllers.onEach { it.onDestroy() }
                controllers.clear()
            }
        }
    }

    override fun clear() {
        synchronized(lifecycleState) {
            controllers.onEach { it.onClear() }
        }
    }

}

private enum class LifecycleState {
    CREATE,
    RESUME,
    PAUSE,
    DESTROY
}