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

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.DrawableRes
import androidx.core.content.edit
import androidx.core.view.isVisible
import androidx.core.widget.NestedScrollView
import kotlinx.android.extensions.LayoutContainer
import kotlinx.android.synthetic.main.fragment_browser.*
import kotlinx.android.synthetic.main.layout_quick_action_sheet.*
import kotlinx.android.synthetic.main.layout_quick_action_sheet.view.*
import mozilla.components.support.ktx.android.view.putCompoundDrawablesRelativeWithIntrinsicBounds
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.components.toolbar.BrowserFragmentState

interface QuickActionSheetViewInteractor {
    fun onQuickActionSheetOpened()
    fun onQuickActionSheetClosed()
    fun onQuickActionSheetSharePressed()
    fun onQuickActionSheetDownloadPressed()
    fun onQuickActionSheetBookmarkPressed()
    fun onQuickActionSheetReadPressed()
    fun onQuickActionSheetAppearancePressed()
    fun onQuickActionSheetOpenLinkPressed()
}

/**
 * View for the quick action sheet that slides out from the toolbar.
 */
class QuickActionSheetView(
    override val containerView: ViewGroup,
    private val interactor: QuickActionSheetViewInteractor
) : LayoutContainer, View.OnClickListener {

    val view: NestedScrollView = LayoutInflater.from(containerView.context)
        .inflate(R.layout.component_quick_action_sheet, containerView, true)
        .findViewById(R.id.nestedScrollQuickAction)

    private val quickActionSheet = view.quick_action_sheet as QuickActionSheet
    private val quickActionSheetBehavior = QuickActionSheetBehavior.from(nestedScrollQuickAction)

    init {
        quickActionSheetBehavior.setQuickActionSheetCallback(object :
            QuickActionSheetBehavior.QuickActionSheetCallback {
            override fun onStateChanged(bottomSheet: View, newState: Int) {
                updateImportantForAccessibility(newState)

                if (newState == QuickActionSheetBehavior.STATE_EXPANDED) {
                    interactor.onQuickActionSheetOpened()
                } else if (newState == QuickActionSheetBehavior.STATE_COLLAPSED) {
                    interactor.onQuickActionSheetClosed()
                }
            }

            override fun onSlide(bottomSheet: View, slideOffset: Float) {
                animateOverlay(slideOffset)
            }
        })

        updateImportantForAccessibility(quickActionSheetBehavior.state)

        quick_action_share.setOnClickListener(this)
        quick_action_downloads.setOnClickListener(this)
        quick_action_bookmark.setOnClickListener(this)
        quick_action_read.setOnClickListener(this)
        quick_action_appearance.setOnClickListener(this)
        quick_action_open_app_link.setOnClickListener(this)
    }

    /**
     * Handles clicks from quick action buttons
     */
    override fun onClick(button: View) {
        when (button.id) {
            R.id.quick_action_share -> interactor.onQuickActionSheetSharePressed()
            R.id.quick_action_downloads -> interactor.onQuickActionSheetDownloadPressed()
            R.id.quick_action_bookmark -> interactor.onQuickActionSheetBookmarkPressed()
            R.id.quick_action_read -> interactor.onQuickActionSheetReadPressed()
            R.id.quick_action_appearance -> interactor.onQuickActionSheetAppearancePressed()
            R.id.quick_action_open_app_link -> interactor.onQuickActionSheetOpenLinkPressed()
            else -> return
        }
        quickActionSheetBehavior.state = QuickActionSheetBehavior.STATE_COLLAPSED
    }

    /**
     * Changes alpha of overlay based on new offset of this sheet within [-1,1] range.
     */
    private fun animateOverlay(offset: Float) {
        quick_action_overlay.alpha = (1 - offset)
    }

    /**
     * Updates the important for accessibility flag on the buttons container,
     * depending on if the sheet is opened or closed.
     */
    private fun updateImportantForAccessibility(state: Int) {
        view.quick_action_buttons_layout.importantForAccessibility = when (state) {
            QuickActionSheetBehavior.STATE_COLLAPSED, QuickActionSheetBehavior.STATE_HIDDEN ->
                View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
            else ->
                View.IMPORTANT_FOR_ACCESSIBILITY_AUTO
        }
    }

    fun update(state: BrowserFragmentState) {
        val quickActionSheetState = state.quickActionSheetState
        view.quick_action_read.isVisible = quickActionSheetState.readable
        view.quick_action_read.isSelected = quickActionSheetState.readerActive
        view.quick_action_read.text = view.context.getString(
            if (quickActionSheetState.readerActive) R.string.quick_action_read_close else R.string.quick_action_read
        )
        notifyReaderModeButton(quickActionSheetState.readable)

        view.quick_action_appearance.isVisible = quickActionSheetState.readerActive

        view.quick_action_bookmark.isSelected = quickActionSheetState.bookmarked
        view.quick_action_bookmark.text = view.context.getString(
            if (quickActionSheetState.bookmarked) {
                R.string.quick_action_bookmark_edit
            } else {
                R.string.quick_action_bookmark
            }
        )

        if (quickActionSheetState.bounceNeeded && view.context.settings().shouldAutoBounceQuickActionSheet) {
            quickActionSheet.bounceSheet()
        }

        view.quick_action_open_app_link.apply {
            visibility = if (quickActionSheetState.isAppLink) View.VISIBLE else View.GONE
        }
    }

    private fun notifyReaderModeButton(readable: Boolean) {
        val settings = view.context.settings().preferences
        val shouldNotifyKey = view.context.getString(R.string.pref_key_reader_mode_notification)

        @DrawableRes
        val readerTwoStateDrawableRes = if (readable && settings.getBoolean(shouldNotifyKey, true)) {
            quickActionSheet.bounceSheet()
            settings.edit { putBoolean(shouldNotifyKey, false) }
            R.drawable.reader_two_state_with_notification
        } else {
            R.drawable.reader_two_state
        }

        view.quick_action_read.putCompoundDrawablesRelativeWithIntrinsicBounds(
            top = view.context.getDrawable(readerTwoStateDrawableRes)
        )
    }
}
