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

import android.app.Dialog
import android.graphics.Color
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.LinearLayout
import androidx.appcompat.app.AppCompatDialogFragment
import androidx.appcompat.view.ContextThemeWrapper
import androidx.core.graphics.drawable.toDrawable
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import mozilla.components.concept.base.crash.Breadcrumb
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.ext.components
import com.google.android.material.R as materialR

/**
 * Base [AppCompatDialogFragment] that adds behaviour to create a top or bottom dialog.
 */
abstract class FenixDialogFragment : AppCompatDialogFragment() {
    /**
     * Indicates the position of the dialog top or bottom.
     */
    abstract val gravity: Int

    /**
     * The layout id that will be render on the dialog.
     */
    abstract val layoutId: Int

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        context?.components?.analytics?.crashReporter?.recordCrashBreadcrumb(
            Breadcrumb("FenixDialogFragment onCreateDialog Gravity $gravity"),
        )
        return if (gravity == Gravity.BOTTOM) {
            BottomSheetDialog(requireContext(), this.theme).apply {
                setOnShowListener {
                    val bottomSheet = findViewById<View>(materialR.id.design_bottom_sheet) as FrameLayout
                    val behavior = BottomSheetBehavior.from(bottomSheet)
                    behavior.state = BottomSheetBehavior.STATE_EXPANDED
                }
            }
        } else {
            Dialog(requireContext()).applyCustomizationsForTopDialog(inflateRootView())
        }
    }

    private fun Dialog.applyCustomizationsForTopDialog(rootView: View): Dialog {
        addContentView(
            rootView,
            LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.MATCH_PARENT,
            ),
        )

        window?.apply {
            setGravity(gravity)
            setBackgroundDrawable(Color.TRANSPARENT.toDrawable())
            // This must be called after addContentView, or it won't fully fill to the edge.
            setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
        }
        return this
    }

    fun inflateRootView(container: ViewGroup? = null): View {
        val contextThemeWrapper = ContextThemeWrapper(
            activity,
            (activity as HomeActivity).themeManager.currentThemeResource,
        )
        return LayoutInflater.from(contextThemeWrapper).inflate(
            layoutId,
            container,
            false,
        )
    }
}
