package mx.trackermap.TrackerMap.controllers import android.util.Log import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.launch import kotlinx.serialization.json.JsonPrimitive import mx.trackermap.TrackerMap.client.apis.SessionApi import mx.trackermap.TrackerMap.client.apis.UsersApi import mx.trackermap.TrackerMap.client.models.SessionBody import mx.trackermap.TrackerMap.client.models.User @DelicateCoroutinesApi class SessionController( private val sessionApi: SessionApi, private val usersApi: UsersApi ) { sealed class LoginState { object Nothing: LoginState() object Loading: LoginState() object EmailMissing : LoginState() object PasswordMissing : LoginState() object Failure : LoginState() object Success : LoginState() object SignOut : LoginState() } val loginStateFlow = MutableStateFlow(null) val userFlow = MutableStateFlow(null) fun getSession() { loginStateFlow.value = LoginState.Loading GlobalScope.launch { try { userFlow.value = sessionApi.sessionGet() Log.d("LoginViewModel", userFlow.value.toString()) loginStateFlow.value = LoginState.Success } catch (e: Exception) { loginStateFlow.value = LoginState.Failure } } } fun restoreSession() { loginStateFlow.value = LoginState.Loading GlobalScope.launch { try { userFlow.value = sessionApi.sessionGet() Log.d("LoginViewModel", userFlow.value.toString()) loginStateFlow.value = LoginState.Success } catch (e: Exception) { Log.d("LoginViewModel", "No session") loginStateFlow.value = LoginState.Nothing } } } fun login(body: SessionBody) { val email = body.email.trim() val password = body.password.trim() val token = body.fcmToken if (email.isEmpty()) { loginStateFlow.value = LoginState.EmailMissing return } if (password.isEmpty()) { loginStateFlow.value = LoginState.PasswordMissing return } loginStateFlow.value = LoginState.Loading GlobalScope.launch { try { val session = sessionApi.sessionPost(email, password) userFlow.value = session usersApi.token = sessionApi.token token?.let { registerFcmToken(it) } loginStateFlow.value = LoginState.Success } catch (e: Exception) { loginStateFlow.value = LoginState.Failure } } } private suspend fun registerFcmToken(token: String) { print("Register FCM token: $token\n") try { userFlow.value?.let { user -> val attributes = user.attributes.toMutableMap() attributes["notificationTokens"].toString().let { tokens -> if (tokens == "null" || !tokens.contains(token)) { if (tokens == "null") { attributes["notificationTokens"] = JsonPrimitive(token) } else if (!tokens.contains(token)) { attributes["notificationTokens"] = JsonPrimitive("$tokens,$token") } } } usersApi.usersIdPut(user.copy( attributes = attributes ), user.id!!) } } catch (e: Exception) { e.printStackTrace() } } private suspend fun unregisterFcmToken(token: String) { print("Unregister FCM token: $token\n") try { userFlow.value?.let { user -> val attributes = user.attributes.toMutableMap() attributes["notificationTokens"].toString().let { tokens -> if (tokens.contains("$token,")) { attributes["notificationTokens"] = JsonPrimitive(token.replace("$token,", "")) } else if (tokens.contains(token)) { attributes["notificationTokens"] = JsonPrimitive(token.replace(token, "")) } usersApi.usersIdPut(user.copy( attributes = attributes ), user.id!!) } } } catch (e: Exception) { e.printStackTrace() } } fun logout(token: String?) { GlobalScope.launch { loginStateFlow.value = LoginState.Loading token?.let { unregisterFcmToken(it) } sessionApi.sessionDelete() loginStateFlow.value = LoginState.SignOut } } }