SDPTeam15/PolyEvents

View on GitHub
app/src/main/java/com/github/sdpteam15/polyevents/view/fragments/LoginFragment.kt

Summary

Maintainability
A
0 mins
Test Coverage
D
61%
package com.github.sdpteam15.polyevents.view.fragments

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.github.sdpteam15.polyevents.R
import com.github.sdpteam15.polyevents.helper.HelperFunctions
import com.github.sdpteam15.polyevents.model.database.local.room.LocalDatabase
import com.github.sdpteam15.polyevents.model.database.remote.Database.currentDatabase
import com.github.sdpteam15.polyevents.model.database.remote.login.UserLogin
import com.github.sdpteam15.polyevents.model.entity.UserEntity
import com.github.sdpteam15.polyevents.model.observable.Observable
import com.github.sdpteam15.polyevents.view.PolyEventsApplication
import com.github.sdpteam15.polyevents.view.activity.MainActivity
import kotlinx.coroutines.Dispatchers

/**
 * [Fragment] subclass representing the login page allowing the user to connect to the application
 */


class LoginFragment : Fragment() {
    val inDbObservable = Observable<Boolean>()
    val SIGN_IN_RC: Int = 200

    // Return CurrentUser if we are not in test, but we can use a fake user in test this way
    var currentUser: UserEntity? = null
        get() = field ?: currentDatabase.currentUser

    companion object {
        const val TAG = "LoginFragment"
    }

    private var obsInDatabaseEnd = Observable<Boolean>()
    private var obsFirstConnectionEnd = Observable<Boolean>()


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //If the user is already logged in, we redirect him directly to the Profile fragment
        if (currentUser != null) {
            HelperFunctions.changeFragment(
                activity,
                MainActivity.fragments[R.id.id_fragment_profile]
            )
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        // Requested code is the sign in code
        if (requestCode == SIGN_IN_RC) {
            //Redirect the data received to the login object
            // If the task is successful we redirect otherwise we display an error message
            UserLogin.currentUserLogin
                .getResultFromIntent(
                    data,
                    activity as Activity,
                    getString(R.string.login_failed_text)
                )?.addOnCompleteListener(activity as Activity) { task ->
                    if (task.isSuccessful) {
                        Log.d(TAG, "Beginning populating local database")
                        val application = requireActivity().application as PolyEventsApplication
                        application.applicationScope.launch(Dispatchers.IO) {
                            LocalDatabase.populateDatabaseWithUserEvents(
                                application.localDatabase.eventDao(),
                                application.applicationScope
                            )

                            LocalDatabase.populateDatabaseWithUserSettings(
                                application.localDatabase.userSettingsDao(),
                                application.applicationScope
                            )
                        }

                        addIfNotInDB()
                    } else {
                        HelperFunctions.showToast(getString(R.string.login_failed_text), activity)
                    }
                }
        }
    }

    /**
     * This method will call the inDatabase method to check whether the users has already been registered to the database or not
     */
    private fun addIfNotInDB() {
        obsInDatabaseEnd = Observable()
        obsFirstConnectionEnd = Observable()

        //Display a loading screen while the queries with the database are not over
        HelperFunctions.showProgressDialog(
            requireActivity(),
            listOf(obsInDatabaseEnd, obsFirstConnectionEnd),
            requireActivity().supportFragmentManager
        )

        currentDatabase.userDatabase.inDatabase(inDbObservable, currentUser!!.uid)
            .observe(requireActivity()) {
                if (it.value) {
                    // Post the value true otherwise we will fall into an infinite waiting loop
                    obsFirstConnectionEnd.postValue(true, this)

                    //If already in database, redirect to the profile fragment
                    HelperFunctions.changeFragment(
                        activity,
                        MainActivity.fragments[R.id.id_fragment_profile]
                    )
                } else {
                    //If not in DB, i.e. first connection, register it
                    createAccountAndRedirect()
                }
            }.then.updateOnce(requireActivity(), obsInDatabaseEnd)
    }


    /**
     * This method is called when the user log in for the first item with its account
     * It registers the users into the database and redirect him to the ProfileFragment if no problem during the communication with the database
     */
    private fun createAccountAndRedirect() {
        currentDatabase
            .userDatabase
            .firstConnexion(
                currentDatabase.currentUser!!
            ).observe(this) {
                if (it.value) {
                    //If correctly registered, redirect it
                    HelperFunctions.changeFragment(
                        activity,
                        MainActivity.fragments[R.id.id_fragment_profile]
                    )
                } else {
                    //Display error message
                    HelperFunctions.showToast(getString(R.string.login_failed_text), activity)
                }
            }.then.updateOnce(requireActivity(), obsFirstConnectionEnd)
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val rootView = inflater.inflate(R.layout.fragment_login, container, false)
        //Attach an event to sign-in button
        rootView.findViewById<com.google.android.gms.common.SignInButton>(R.id.id_btn_login_button)
            .setOnClickListener {
                if (currentUser == null) {
                    UserLogin.currentUserLogin.signIn(activity as Activity, this, SIGN_IN_RC)
                } else {
                    //This branch allow us to test the communication between ProfileFragment and LoginFragment. During a normal execution, it won't be used.
                    addIfNotInDB()
                }
            }
        return rootView
    }
}