package com.sshproxy.vpn.ssh



import com.sshproxy.vpn.util.CallsAvailabilityStatus

import kotlinx.coroutines.CoroutineScope

import kotlinx.coroutines.Dispatchers

import kotlinx.coroutines.Job

import kotlinx.coroutines.delay

import kotlinx.coroutines.isActive

import kotlinx.coroutines.launch

import kotlinx.coroutines.withContext



/**

 * Периодически проверяет доступность UDP-прокси для звонков на SSH-сервере.

 */

class CallsAvailabilityMonitor(

    private val sshManager: SshTunnelManager,

    private val remoteHost: () -> String,

    private val remotePort: () -> Int,

    private val remoteCredentials: () -> SocksAuthCredentials,

    private val formatUnavailableReason: (UdpRelayHealthCheck.Result) -> String,

    private val onAvailabilityChanged: (CallsAvailabilityStatus) -> Unit

) {

    private var job: Job? = null



    fun start(scope: CoroutineScope, intervalMs: Long = DEFAULT_INTERVAL_MS) {

        stop()

        job = scope.launch {

            while (isActive) {

                performCheck()

                delay(intervalMs.coerceAtLeast(MIN_INTERVAL_MS))

            }

        }

    }



    fun stop() {

        job?.cancel()

        job = null

    }



    private suspend fun performCheck() {

        if (!sshManager.isConnected) {

            return

        }

        val result = withContext(Dispatchers.IO) {

            sshManager.checkUdpRelay(

                remoteHost = remoteHost(),

                remotePort = remotePort(),

                credentials = remoteCredentials()

            )

        }

        val status = CallsAvailabilityStatus.fromCheckResult(result, formatUnavailableReason)

        withContext(Dispatchers.Main) {

            onAvailabilityChanged(status)

        }

    }



    companion object {

        const val DEFAULT_INTERVAL_MS = 30_000L

        private const val MIN_INTERVAL_MS = 10_000L

    }

}

