SettingsFragment.kt

package chat.rocket.android.settings.ui

import android.content.ActivityNotFoundException
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.net.toUri
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import chat.rocket.android.BuildConfig
import chat.rocket.android.R
import chat.rocket.android.analytics.AnalyticsManager
import chat.rocket.android.analytics.event.InviteType
import chat.rocket.android.analytics.event.ScreenViewEvent
import chat.rocket.android.core.behaviours.AppLanguageView
import chat.rocket.android.helper.TextHelper.getDeviceAndAppInformation
import chat.rocket.android.settings.presentation.SettingsPresenter
import chat.rocket.android.settings.presentation.SettingsView
import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.invalidateFirebaseToken
import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.app_bar.*
import kotlinx.android.synthetic.main.dialog_delete_account.*
import kotlinx.android.synthetic.main.fragment_settings.*
import timber.log.Timber
import javax.inject.Inject

internal const val TAG_SETTINGS_FRAGMENT = "SettingsFragment"

fun newInstance(): Fragment = SettingsFragment()

class SettingsFragment : Fragment(), SettingsView, AppLanguageView {
    @Inject
    lateinit var analyticsManager: AnalyticsManager
    @Inject
    lateinit var presenter: SettingsPresenter
    private val locales = arrayListOf(
        "en",
        "ar",
        "de",
        "es",
        "fa",
        "fr",
        "hi,IN",
        "it",
        "ja",
        "pt,BR",
        "pt,PT",
        "ru,RU",
        "tr",
        "uk",
        "zh,CN",
        "zh,TW"
    )

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        AndroidSupportInjection.inject(this)
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? = container?.inflate(R.layout.fragment_settings)

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        setupListeners()
        setupToolbar()
        presenter.setupView()
        analyticsManager.logScreenView(ScreenViewEvent.Settings)
    }

    override fun setupSettingsView(
        avatar: String,
        displayName: String,
        status: String,
        isAdministrationEnabled: Boolean,
        isAnalyticsTrackingEnabled: Boolean,
        isDeleteAccountEnabled: Boolean,
        serverVersion: String
    ) {
        image_avatar.setImageURI(avatar)

        text_display_name.text = displayName

        text_status.text = status

        text_app_version.text =
            getString(R.string.msg_app_version, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE)

        text_server_version.text = getString(R.string.msg_server_version, serverVersion)

        text_administration.isVisible = isAdministrationEnabled

        with(switch_crash_report) {
            isChecked = isAnalyticsTrackingEnabled
            isEnabled = BuildConfig.FLAVOR == "play"
        }

        text_delete_account.isVisible = isDeleteAccountEnabled
    }

    override fun updateLanguage(language: String, country: String?) {
        presenter.saveLocale(language, country)
        presenter.recreateActivity()
    }

    override fun invalidateToken(token: String) = invalidateFirebaseToken(token)

    override fun showLoading() {
        view_loading.isVisible = true
    }

    override fun hideLoading() {
        view_loading.isVisible = false
    }

    override fun showMessage(resId: Int) {
        showToast(resId)
    }

    override fun showMessage(message: String) {
        showToast(message)
    }

    override fun showGenericErrorMessage() = showMessage(getString(R.string.msg_generic_error))

    private fun setupListeners() {
        profile_container.setOnClickListener { presenter.toProfile() }

        text_contact_us.setOnClickListener { contactSupport() }

        text_language.setOnClickListener { changeLanguage() }

        text_review_this_app.setOnClickListener { showAppOnStore() }

        text_share_this_app.setOnClickListener { shareApp() }

        text_license.setOnClickListener {
            presenter.toLicense(getString(R.string.license_url), getString(R.string.title_license))
        }

        text_administration.setOnClickListener { presenter.toAdmin() }

        switch_crash_report.setOnCheckedChangeListener { _, isChecked ->
            presenter.enableAnalyticsTracking(isChecked)
        }

        text_logout.setOnClickListener { showLogoutDialog() }

        text_delete_account.setOnClickListener { showDeleteAccountDialog() }
    }

    private fun setupToolbar() {
        with((activity as AppCompatActivity)) {
            with(toolbar) {
                setSupportActionBar(this)
                title = getString(R.string.title_settings)
                setNavigationIcon(R.drawable.ic_arrow_back_white_24dp)
                setNavigationOnClickListener { activity?.onBackPressed() }
            }
        }
    }

    private fun contactSupport() {
        val uriText = "mailto:${"support@rocket.chat"}" +
                "?subject=" + Uri.encode(getString(R.string.msg_android_app_support)) +
                "&body=" + Uri.encode(getDeviceAndAppInformation())

        with(Intent(Intent.ACTION_SENDTO)) {
            data = uriText.toUri()
            try {
                startActivity(Intent.createChooser(this, getString(R.string.msg_send_email)))
            } catch (ex: ActivityNotFoundException) {
                Timber.e(ex)
            }
        }
    }

    private fun changeLanguage() {
        context?.let {
            val selectedLocale = presenter.getCurrentLocale(it)
            var localeIndex = -1
            locales.forEachIndexed { index, locale ->
                val array = locale.split(",")
                val language = array[0]
                val country = if (array.size > 1) array[1] else ""
                // If language and country are specified, return the respective locale, else return
                // the first locale found if the language is as specified regardless of the country.
                if (language == selectedLocale.language) {
                    if (country == selectedLocale.country) {
                        localeIndex = index
                        return@forEachIndexed
                    } else if (localeIndex == -1) {
                        localeIndex = index
                    }
                }
            }
            AlertDialog.Builder(it)
                .setTitle(R.string.title_choose_language)
                .setSingleChoiceItems(
                    resources.getStringArray(R.array.languages), localeIndex
                ) { dialog, option ->
                    val array = locales[option].split(",")
                    if (array.size > 1) {
                        updateLanguage(array[0], array[1])
                    } else {
                        updateLanguage(array[0])
                    }
                    dialog.dismiss()
                }
                .create()
                .show()
        }
    }

    private fun showAppOnStore() {
        try {
            startActivity(Intent(Intent.ACTION_VIEW, getString(R.string.market_link).toUri()))
        } catch (error: ActivityNotFoundException) {
            startActivity(Intent(Intent.ACTION_VIEW, getString(R.string.play_store_link).toUri()))
        }
    }

    private fun shareApp() {
        // We can't know for sure at this point that the invitation was sent successfully since they will now be outside our app
        analyticsManager.logInviteSent(InviteType.ViaApp)
        presenter.shareViaApp(context)
    }

    private fun showLogoutDialog() {
        context?.let {
            val builder = AlertDialog.Builder(it)
            builder.setTitle(R.string.title_are_you_sure)
                .setPositiveButton(R.string.action_logout) { _, _ -> presenter.logout() }
                .setNegativeButton(android.R.string.no) { dialog, _ -> dialog.cancel() }
                .create()
                .show()
        }
    }

    private fun showDeleteAccountDialog() {
        context?.let {
            val dialogLayout = layoutInflater.inflate(R.layout.dialog_delete_account, null)
            val editText = dialogLayout.findViewById<EditText>(R.id.text_password)

            AlertDialog.Builder(it)
                .setView(dialogLayout)
                .setPositiveButton(R.string.msg_delete_account) { _, _ ->
                    presenter.deleteAccount(editText.text.toString())
                }.setNegativeButton(android.R.string.no) { dialog, _ -> dialog.cancel() }
                .create()
                .show()
        }
    }
}