/* 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.tabstray

import android.app.Dialog
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.style.UnderlineSpan
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import androidx.annotation.VisibleForTesting
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.map
import mozilla.components.browser.state.selector.normalTabs
import mozilla.components.browser.state.state.BrowserState
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.lib.state.helpers.AbstractBinding
import mozilla.components.support.ktx.android.util.dpToPx
import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.infobanner.InfoBanner
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.databinding.ComponentTabstray2Binding
import org.mozilla.fenix.databinding.OnboardingInactiveTabsCfrBinding
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.potentialInactiveTabs
import org.mozilla.fenix.utils.Settings

@OptIn(ExperimentalCoroutinesApi::class)
class TabsTrayInactiveTabsOnboardingBinding(
    private val context: Context,
    private val store: BrowserStore,
    private val tabsTrayBinding: ComponentTabstray2Binding?,
    private val settings: Settings,
    private val navigationInteractor: NavigationInteractor
) : AbstractBinding<BrowserState>(store) {

    @VisibleForTesting
    internal var banner: InfoBanner? = null

    override suspend fun onState(flow: Flow<BrowserState>) {
        flow.map { state -> state.normalTabs.size }
            .ifChanged()
            .collect {
                val inactiveTabsList =
                    if (settings.inactiveTabsAreEnabled) { store.state.potentialInactiveTabs } else emptyList()
                if (inactiveTabsList.isNotEmpty() && shouldShowOnboardingForInactiveTabs()) {
                    createInactiveCFR()
                }
            }
    }

    private fun shouldShowOnboardingForInactiveTabs() =
        settings.shouldShowInactiveTabsOnboardingPopup &&
            settings.canShowCfr

    private fun createInactiveCFR() {
        val context: Context = context
        val metrics = context.components.analytics.metrics
        val anchorPosition = IntArray(2)
        val popupBinding = OnboardingInactiveTabsCfrBinding.inflate(LayoutInflater.from(context))
        val popup = Dialog(context)

        popup.apply {
            setContentView(popupBinding.root)
            setCancelable(false)
            // removing title or setting it as an empty string does not prevent a11y services from assigning one
            setTitle(" ")
        }
        popupBinding.closeInfoBanner.setOnClickListener {
            popup.dismiss()
            settings.shouldShowInactiveTabsOnboardingPopup = false
            metrics.track(Event.TabsTrayInactiveTabsCFRDismissed)
        }

        popupBinding.bannerInfoMessage.setOnClickListener {
            popup.dismiss()
            settings.shouldShowInactiveTabsOnboardingPopup = false
            navigationInteractor.onTabSettingsClicked()
            metrics.track(Event.TabsTrayInactiveTabsCFRGotoSettings)
        }

        val messageText = context.getString(R.string.tab_tray_inactive_onboarding_message)
        val actionText = context.getString(R.string.tab_tray_inactive_onboarding_button_text)
        val spannableStringBuilder = SpannableStringBuilder(messageText)

        spannableStringBuilder.append(" ")
            .append(actionText, UnderlineSpan(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
        popupBinding.bannerInfoMessage.text = spannableStringBuilder

        tabsTrayBinding?.tabsTray?.getLocationOnScreen(anchorPosition)

        val (x, y) = anchorPosition

        if (x == 0 && y == 0) {
            return
        }

        popupBinding.root.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)

        popup.window?.apply {
            val attr = attributes
            setGravity(Gravity.START or Gravity.TOP)
            attr.x = x + 15.dpToPx(context.resources.displayMetrics)
            attr.y = y + 20.dpToPx(context.resources.displayMetrics)
            attributes = attr
            setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
        }
        popup.show()
        metrics.track(Event.TabsTrayInactiveTabsCFRIsVisible)
    }
}
