/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mozilla.fenix.settings

import android.content.Intent
import android.graphics.Color
import android.net.Uri
import android.os.Bundle
import android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS
import org.mozilla.fenix.utils.Settings
import android.text.SpannableString
import android.text.SpannableStringBuilder
import android.text.Spanned.SPAN_EXCLUSIVE_INCLUSIVE
import android.text.style.AbsoluteSizeSpan
import android.text.style.ForegroundColorSpan
import android.view.LayoutInflater
import android.view.View
import android.view.View.VISIBLE
import android.view.ViewGroup
import android.widget.Button
import android.widget.RadioButton
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.text.HtmlCompat
import androidx.core.text.HtmlCompat.FROM_HTML_MODE_COMPACT
import androidx.fragment.app.Fragment
import mozilla.components.feature.sitepermissions.SitePermissionsRules
import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action.BLOCKED
import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action.ASK_TO_ALLOW
import org.mozilla.fenix.R

class SitePermissionsManagePhoneFeature : Fragment() {

    private lateinit var phoneFeature: PhoneFeature
    private lateinit var settings: Settings

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        phoneFeature = SitePermissionsManagePhoneFeatureArgs
            .fromBundle(requireArguments())
            .permission.toPhoneFeature()

        (activity as AppCompatActivity).title = phoneFeature.label
        (activity as AppCompatActivity).supportActionBar?.show()
        settings = Settings.getInstance(requireContext())
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val rootView = inflater.inflate(R.layout.fragment_manage_site_permissions_feature_phone, container, false)

        initAskToAllowRadio(rootView)
        initBlockRadio(rootView)
        initBockedByAndroidContainer(rootView)

        return rootView
    }

    private fun initAskToAllowRadio(rootView: View) {
        val radio = rootView.findViewById<RadioButton>(R.id.ask_to_allow_radio)
        val askToAllowText = getString(R.string.preference_option_phone_feature_ask_to_allow)
        val recommendedText = getString(R.string.phone_feature_recommended)
        val recommendedTextSize = resources.getDimensionPixelSize(R.dimen.phone_feature_label_recommended_text_size)
        val recommendedSpannable = SpannableString(recommendedText)

        recommendedSpannable.setSpan(
            ForegroundColorSpan(Color.GRAY),
            0,
            recommendedSpannable.length,
            SPAN_EXCLUSIVE_INCLUSIVE
        )

        recommendedSpannable.setSpan(
            AbsoluteSizeSpan(recommendedTextSize), 0,
            recommendedSpannable.length,
            SPAN_EXCLUSIVE_INCLUSIVE
        )

        radio.text = with(SpannableStringBuilder()) {
            append(askToAllowText)
            append("\n")
            append(recommendedSpannable)
            this
        }
        radio.setOnClickListener {
            saveActionInSettings(ASK_TO_ALLOW)
        }
        radio.restoreState(ASK_TO_ALLOW)
    }

    private fun RadioButton.restoreState(action: SitePermissionsRules.Action) {
        if (phoneFeature.action == action) {
            this.isChecked = true
        }
    }

    private fun initBlockRadio(rootView: View) {
        val radio = rootView.findViewById<RadioButton>(R.id.block_radio)
        radio.setOnClickListener {
            saveActionInSettings(BLOCKED)
        }
        radio.restoreState(BLOCKED)
    }

    private fun initBockedByAndroidContainer(rootView: View) {
        if (!phoneFeature.isAndroidPermissionGranted) {
            val containerView = rootView.findViewById<View>(R.id.permissions_blocked_container)
            containerView.visibility = VISIBLE

            val descriptionLabel = rootView.findViewById<TextView>(R.id.blocked_by_android_explanation_label)
            val text = getString(R.string.phone_feature_blocked_by_android_explanation, phoneFeature.label)
            descriptionLabel.text = HtmlCompat.fromHtml(text, FROM_HTML_MODE_COMPACT)

            initSettingsButton(rootView)
        }
    }

    private val PhoneFeature.label: String
        get() {
            return when (this) {
                PhoneFeature.CAMERA -> getString(R.string.preference_phone_feature_camera)
                PhoneFeature.LOCATION -> getString(R.string.preference_phone_feature_location)
                PhoneFeature.MICROPHONE -> getString(R.string.preference_phone_feature_microphone)
                PhoneFeature.NOTIFICATION -> getString(R.string.preference_phone_feature_notification)
            }
        }

    private val PhoneFeature.isAndroidPermissionGranted: Boolean
        get() {
            return this.isAndroidPermissionGranted(requireContext())
        }

    private fun Int.toPhoneFeature(): PhoneFeature {
        return requireNotNull(PhoneFeature.values().find { feature ->
            this == feature.id
        }) {
            "$this is a invalid PhoneFeature"
        }
    }

    private val PhoneFeature.action: SitePermissionsRules.Action
        get() {
            return when (phoneFeature) {
                PhoneFeature.CAMERA -> settings.getSitePermissionsPhoneFeatureCameraAction()
                PhoneFeature.LOCATION -> settings.getSitePermissionsPhoneFeatureLocation()
                PhoneFeature.MICROPHONE -> settings.getSitePermissionsPhoneFeatureMicrophoneAction()
                PhoneFeature.NOTIFICATION -> settings.getSitePermissionsPhoneFeatureNotificationAction()
            }
        }

    private fun initSettingsButton(rootView: View) {
        val button = rootView.findViewById<Button>(R.id.settings_button)
        button.setOnClickListener {
            openSettings()
        }
    }

    private fun openSettings() {
        val intent = Intent(ACTION_APPLICATION_DETAILS_SETTINGS)
        val uri = Uri.fromParts("package", requireContext().packageName, null)
        intent.data = uri
        startActivity(intent)
    }

    private fun saveActionInSettings(action: SitePermissionsRules.Action) {
        when (phoneFeature) {
            PhoneFeature.CAMERA -> settings.setSitePermissionsPhoneFeatureCameraAction(action)
            PhoneFeature.LOCATION -> settings.setSitePermissionsPhoneFeatureLocation(action)
            PhoneFeature.MICROPHONE -> settings.setSitePermissionsPhoneFeatureMicrophoneAction(action)
            PhoneFeature.NOTIFICATION -> settings.setSitePermissionsPhoneFeatureNotificationAction(action)
        }
    }

    companion object {
        const val CAMERA_PERMISSION = 0
        const val LOCATION_PERMISSION = 1
        const val MICROPHONE_PERMISSION = 2
        const val NOTIFICATION_PERMISSION = 3
    }
}
