package com.omixlab.lckcontrol.ui.clients

import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.IBinder
import androidx.lifecycle.ViewModel
import com.omixlab.lckcontrol.shared.ConnectedClientInfo
import com.omixlab.lckcontrol.shared.ILckControlCallback
import com.omixlab.lckcontrol.shared.ILckControlService
import com.omixlab.lckcontrol.shared.StreamPlan
import com.omixlab.lckcontrol.util.GameInfoProvider
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import javax.inject.Inject

@HiltViewModel
class ActiveClientsViewModel @Inject constructor(
    @ApplicationContext private val context: Context,
    val gameInfoProvider: GameInfoProvider,
) : ViewModel() {

    private var service: ILckControlService? = null

    private val _clients = MutableStateFlow<List<ConnectedClientInfo>>(emptyList())
    val clients: StateFlow<List<ConnectedClientInfo>> = _clients.asStateFlow()

    private val _isConnected = MutableStateFlow(false)
    val isConnected: StateFlow<Boolean> = _isConnected.asStateFlow()

    private val callback = object : ILckControlCallback.Stub() {
        override fun onStreamPlansChanged(plans: List<StreamPlan>) {}

        override fun onStreamPlanUpdated(plan: StreamPlan) {}

        override fun onClientRegistered(clientId: String) {
            refreshClients()
        }

        override fun onClientUnregistered(clientId: String) {
            refreshClients()
        }

        override fun onAuthStateChanged(authenticated: Boolean) {}
    }

    private val connection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, binder: IBinder?) {
            service = ILckControlService.Stub.asInterface(binder)
            service?.registerCallback(callback)
            _isConnected.value = true
            refreshClients()
        }

        override fun onServiceDisconnected(name: ComponentName?) {
            service = null
            _isConnected.value = false
            _clients.value = emptyList()
        }
    }

    init {
        bindToService()
    }

    private fun bindToService() {
        val intent = Intent().apply {
            component = ComponentName(
                context.packageName,
                "com.omixlab.lckcontrol.service.LckControlService",
            )
        }
        context.bindService(intent, connection, Context.BIND_AUTO_CREATE)
    }

    private fun refreshClients() {
        _clients.value = service?.connectedClients ?: emptyList()
    }

    fun createDefaultPlan(clientName: String): StreamPlan? {
        return service?.createDefaultPlan(clientName)
    }

    override fun onCleared() {
        service?.unregisterCallback(callback)
        try {
            context.unbindService(connection)
        } catch (_: IllegalArgumentException) {}
        super.onCleared()
    }
}
