package com.rosetta.messenger.network

import android.content.Context
import com.rosetta.messenger.network.connection.AuthRestoreService
import com.rosetta.messenger.network.connection.ProtocolInstanceManager
import com.rosetta.messenger.network.connection.RuntimeInitializationCoordinator
import com.rosetta.messenger.network.connection.RuntimeShutdownCoordinator
import com.rosetta.messenger.network.connection.SyncCoordinator

class RuntimeConnectionControlFacade(
    private val postConnectionEvent: (ConnectionEvent) -> Unit,
    private val initializationCoordinator: RuntimeInitializationCoordinator,
    private val syncCoordinator: SyncCoordinator,
    private val authRestoreService: AuthRestoreService,
    private val runtimeShutdownCoordinator: RuntimeShutdownCoordinator,
    private val protocolInstanceManager: ProtocolInstanceManager,
    private val subscribePushTokenIfAvailable: (String?) -> Unit
) {
    fun initialize(context: Context) {
        initializationCoordinator.initialize(context)
    }

    fun initializeAccount(publicKey: String, privateKey: String) {
        postConnectionEvent(
            ConnectionEvent.InitializeAccount(publicKey = publicKey, privateKey = privateKey)
        )
    }

    fun connect() {
        postConnectionEvent(ConnectionEvent.Connect(reason = "api_connect"))
    }

    fun reconnectNowIfNeeded(reason: String = "foreground_resume") {
        postConnectionEvent(ConnectionEvent.FastReconnect(reason = reason))
    }

    fun syncOnForeground() {
        syncCoordinator.syncOnForeground()
    }

    fun forceSynchronize(backtrackMs: Long) {
        if (!isAuthenticated()) {
            reconnectNowIfNeeded("manual_sync_button")
            return
        }
        syncCoordinator.forceSynchronize(backtrackMs)
    }

    fun authenticate(publicKey: String, privateHash: String) {
        postConnectionEvent(
            ConnectionEvent.Authenticate(publicKey = publicKey, privateHash = privateHash)
        )
    }

    fun restoreAuthFromStoredCredentials(
        preferredPublicKey: String? = null,
        reason: String = "background_restore"
    ): Boolean {
        return authRestoreService.restoreAuthFromStoredCredentials(preferredPublicKey, reason)
    }

    fun subscribePushToken(forceToken: String? = null) {
        subscribePushTokenIfAvailable(forceToken)
    }

    fun disconnect() {
        postConnectionEvent(
            ConnectionEvent.Disconnect(
                reason = "manual_disconnect",
                clearCredentials = true
            )
        )
    }

    fun destroy() {
        runtimeShutdownCoordinator.destroy()
    }

    fun isAuthenticated(): Boolean = protocolInstanceManager.isAuthenticated()

    fun isConnected(): Boolean = protocolInstanceManager.isConnected()

    fun setAppInForeground(foreground: Boolean) {
        runCatching { protocolInstanceManager.getOrCreateProtocol().setAppInForeground(foreground) }
    }

    fun getPrivateHashOrNull(): String? {
        return runCatching { protocolInstanceManager.getOrCreateProtocol().getPrivateHash() }.getOrNull()
    }
}
