<commit_before>package circlet.components

import circlet.*
import circlet.login.*
import circlet.utils.*
import com.intellij.concurrency.*
import com.intellij.notification.*
import com.intellij.openapi.components.*
import com.intellij.openapi.project.*
import com.intellij.xml.util.*
import klogging.*
import nl.komponents.kovenant.*
import runtime.*
import runtime.klogger.*
import runtime.lifetimes.*
import runtime.reactive.*
import runtime.random.*
import java.util.concurrent.*

private val log = KLoggers.logger("plugin/IdePluginClient.kt")

enum class ConnectingState {
    Disconnected,
    Connected,
    AuthFailed,
    TryConnect
}

class IdePluginClient(val project : Project) :
    AbstractProjectComponent(project),
    ILifetimedComponent by LifetimedComponent(project) {

    val loginDataComponent = component<CircletLoginComponent>()

    var attemptToConnectNotificationShown = false

    val state = Property(ConnectingState.Disconnected)
    val askPasswordExplicitlyAllowed = Property(false)
    val client = Property<CircletClient?>(null)

    init {

        loginDataComponent.enabled.whenTrue(componentLifetime) { enabledLt ->
            state.value = ConnectingState.TryConnect

            enabledLt.add {
                disconnect()
            }
        }

        state.view(componentLifetime) { lt, state ->
            when(state){
                ConnectingState.TryConnect -> tryReconnect(lt)
                ConnectingState.AuthFailed -> authCheckFailedNotification()
                ConnectingState.Connected -> notifyConnected()
                ConnectingState.Disconnected -> notifyDisconnected(lt)
            }
        }

        loginDataComponent.credentialsUpdated.advise(componentLifetime, {
            state.value = ConnectingState.TryConnect
        })

/*
        ProgressManager.getInstance().run(externalTask(myProject, true, object: IExternalTask {
            override val lifetime: Lifetime get() = connectingProgressLifetimeDef.lifetime
            override val cancel: () -> Unit get() = { disconnect() }
            override val title: String get() = connectionState?.message ?: "Connecting"
            override val header: String get() = connectionState?.message ?: "Connecting"
            override val description: String get() = connectionState?.message ?: "Connecting"
            override val isIndeterminate: Boolean get() = true
            override val progress: Double get() = 0.5
        }))
*/
    }

    fun enable() {
        askPasswordExplicitlyAllowed.value = true
        loginDataComponent.enabled.value = true
    }

    fun disable() {
        loginDataComponent.enabled.value = false
    }

    private fun tryReconnect(lifetime: Lifetime) {

        val ask = askPasswordExplicitlyAllowed.value
        askPasswordExplicitlyAllowed.value = false

        val loginComponent = component<CircletLoginComponent>()
        val modality = application.currentModalityState

        task {
            log.catch {
                loginComponent.
                    getAccessToken(loginComponent.login, loginComponent.pass).
                    thenLater(lifetime, modality) {
                        val errorMessage = it.errorMessage
                        if (errorMessage == null || errorMessage.isEmpty()) {
                            state.value = ConnectingState.Connected
                            val token = it.token!!
                            connectWithToken(lifetime, token)
                        } else {
                            state.value = ConnectingState.AuthFailed
                            if (ask)
                                askPassword()
                        }
                    }. failureLater(lifetime, modality) {
                        notifyReconnect(lifetime)
                        JobScheduler.getScheduler().schedule({
                            if (!lifetime.isTerminated)
                                tryReconnect(lifetime)
                        }, 5000, TimeUnit.MILLISECONDS)
                        state.value = ConnectingState.TryConnect
                }
            }
        }
    }

    fun askPassword() {
        LoginDialog(LoginDialogViewModel(component<CircletLoginComponent>())).show()
    }

    private fun connectWithToken(lifetime : Lifetime, token: String) {
        val clientLocal = CircletClient("ws://localhost:8084/api/v1/connect", token)
        client.value = clientLocal
        clientLocal.services.profile.isMyProfileReady()
            .flatMap {
                if (!it) {
                    clientLocal.services.profile.createMyProfile("Hey! ${Random.nextUID()}")
                } else {
                    clientLocal.services.profile.getMyUid().map {
                        log.debug { "My Profile: $it" }
                    }
                    clientLocal.services.profile.editName("Hey! ${Random.nextUID()}")
                }
            }
            .then {
                log.debug { "Result: $it" }
            }
            .failure {
                log.debug { "Error: $it" }
            }
    }

    fun disconnect() {
        state.value = ConnectingState.Disconnected<commit_msg>use entity ids in urls.<commit_after>package circlet.components

import circlet.*
import circlet.login.*
import circlet.utils.*
import com.intellij.concurrency.*
import com.intellij.notification.*
import com.intellij.openapi.components.*
import com.intellij.openapi.project.*
import com.intellij.xml.util.*
import klogging.*
import nl.komponents.kovenant.*
import runtime.*
import runtime.klogger.*
import runtime.lifetimes.*
import runtime.reactive.*
import runtime.random.*
import java.util.concurrent.*

private val log = KLoggers.logger("plugin/IdePluginClient.kt")

enum class ConnectingState {
    Disconnected,
    Connected,
    AuthFailed,
    TryConnect
}

class IdePluginClient(val project : Project) :
    AbstractProjectComponent(project),
    ILifetimedComponent by LifetimedComponent(project) {

    val loginDataComponent = component<CircletLoginComponent>()

    var attemptToConnectNotificationShown = false

    val state = Property(ConnectingState.Disconnected)
    val askPasswordExplicitlyAllowed = Property(false)
    val client = Property<CircletClient?>(null)

    init {

        loginDataComponent.enabled.whenTrue(componentLifetime) { enabledLt ->
            state.value = ConnectingState.TryConnect

            enabledLt.add {
                disconnect()
            }
        }

        state.view(componentLifetime) { lt, state ->
            when(state){
                ConnectingState.TryConnect -> tryReconnect(lt)
                ConnectingState.AuthFailed -> authCheckFailedNotification()
                ConnectingState.Connected -> notifyConnected()
                ConnectingState.Disconnected -> notifyDisconnected(lt)
            }
        }

        loginDataComponent.credentialsUpdated.advise(componentLifetime, {
            state.value = ConnectingState.TryConnect
        })

/*
        ProgressManager.getInstance().run(externalTask(myProject, true, object: IExternalTask {
            override val lifetime: Lifetime get() = connectingProgressLifetimeDef.lifetime
            override val cancel: () -> Unit get() = { disconnect() }
            override val title: String get() = connectionState?.message ?: "Connecting"
            override val header: String get() = connectionState?.message ?: "Connecting"
            override val description: String get() = connectionState?.message ?: "Connecting"
            override val isIndeterminate: Boolean get() = true
            override val progress: Double get() = 0.5
        }))
*/
    }

    fun enable() {
        askPasswordExplicitlyAllowed.value = true
        loginDataComponent.enabled.value = true
    }

    fun disable() {
        loginDataComponent.enabled.value = false
    }

    private fun tryReconnect(lifetime: Lifetime) {

        val ask = askPasswordExplicitlyAllowed.value
        askPasswordExplicitlyAllowed.value = false

        val loginComponent = component<CircletLoginComponent>()
        val modality = application.currentModalityState

        task {
            log.catch {
                loginComponent.
                    getAccessToken(loginComponent.login, loginComponent.pass).
                    thenLater(lifetime, modality) {
                        val errorMessage = it.errorMessage
                        if (errorMessage == null || errorMessage.isEmpty()) {
                            state.value = ConnectingState.Connected
                            val token = it.token!!
                            connectWithToken(lifetime, token)
                        } else {
                            state.value = ConnectingState.AuthFailed
                            if (ask)
                                askPassword()
                        }
                    }. failureLater(lifetime, modality) {
                        notifyReconnect(lifetime)
                        JobScheduler.getScheduler().schedule({
                            if (!lifetime.isTerminated)
                                tryReconnect(lifetime)
                        }, 5000, TimeUnit.MILLISECONDS)
                        state.value = ConnectingState.TryConnect
                }
            }
        }
    }

    fun askPassword() {
        LoginDialog(LoginDialogViewModel(component<CircletLoginComponent>())).show()
    }

    private fun connectWithToken(lifetime : Lifetime, token: String) {
        val clientLocal = CircletClient("ws://localhost:8084/api/v1/connect", token)
        client.value = clientLocal
        clientLocal.services.profile.isMyProfileReady()
            .flatMap {
                if (!it) {
                    clientLocal.services.profile.createMyProfile("Hey! ${Random.nextUID()}")
                } else {
                    clientLocal.services.profile.getMyUid().map {
                        log.debug { "My Profile: $it" }
                    }
                    clientLocal.services.profile.editNick("Hey! ${Random.nextUID()}")
                }
            }
            .then {
                log.debug { "Result: $it" }
            }
            .failure {
                log.debug { "Error: $it" }
            }
    }

    fun disconnect() {
        state.value = ConnectingState.Disconnected
{'fraction_non_alphanumeric': 0.08961991124831178, 'fraction_numerical': 0.0021223229789697085, 'mean_word_length': 1.8638121546961326, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2370453', 'n_tokens_mistral': 2631, 'n_tokens_neox': 2489, 'n_words': 489}