package com.tomhempel.rbarometer.utils

import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.view.animation.DecelerateInterpolator
import com.tomhempel.rbarometer.R
import com.google.android.material.progressindicator.CircularProgressIndicator

/**
 * Shows the branded loading overlay (view_screen_loading_overlay).
 * Child views are resolved within [overlay]'s subtree only (safe with multiple includes on one screen).
 */
object ScreenLoading {
    private const val TAG = "ScreenLoading"
    private const val SCRIM_FADE_MS = 200L
    private const val PANEL_SCALE_MS = 280L

    private data class OverlayViews(
        val panel: View,
        val indicator: CircularProgressIndicator,
    )

    fun setVisible(overlay: View?, loading: Boolean, vararg contentToDisable: View) {
        if (overlay == null) return
        val views = resolveViews(overlay)
        if (views == null) {
            Log.e(TAG, "loadingPanel/loadingIndicator missing under overlay id=${overlay.id}")
            overlay.visibility = if (loading) View.VISIBLE else View.GONE
            for (view in contentToDisable) {
                view.isEnabled = !loading
            }
            return
        }

        overlay.animate().cancel()
        views.panel.animate().cancel()

        for (view in contentToDisable) {
            view.isEnabled = !loading
        }

        if (loading) {
            show(overlay, views)
        } else {
            hide(overlay, views)
        }
    }

    private fun resolveViews(overlay: View): OverlayViews? {
        val panel = findDescendant(overlay, R.id.loadingPanel) ?: return null
        val indicator = findDescendant(overlay, R.id.loadingIndicator) as? CircularProgressIndicator
            ?: return null
        return OverlayViews(panel, indicator)
    }

    private fun findDescendant(root: View, id: Int): View? {
        if (root.id == id) return root
        if (root is ViewGroup) {
            for (i in 0 until root.childCount) {
                findDescendant(root.getChildAt(i), id)?.let { return it }
            }
        }
        return null
    }

    private fun show(overlay: View, views: OverlayViews) {
        views.panel.visibility = View.VISIBLE
        views.panel.alpha = 1f
        views.panel.scaleX = 0.9f
        views.panel.scaleY = 0.9f
        views.indicator.visibility = View.VISIBLE

        overlay.visibility = View.VISIBLE
        overlay.bringToFront()

        overlay.post {
            if (overlay.visibility != View.VISIBLE) return@post
            views.indicator.show()
            views.panel.animate()
                .scaleX(1f)
                .scaleY(1f)
                .setDuration(PANEL_SCALE_MS)
                .setInterpolator(DecelerateInterpolator())
                .start()

            if (overlay.alpha < 0.99f) {
                overlay.alpha = 0f
                overlay.animate()
                    .alpha(1f)
                    .setDuration(SCRIM_FADE_MS)
                    .setInterpolator(DecelerateInterpolator())
                    .start()
            } else {
                overlay.alpha = 1f
            }
        }
    }

    private fun hide(overlay: View, views: OverlayViews) {
        views.indicator.hide()
        overlay.animate()
            .alpha(0f)
            .setDuration(SCRIM_FADE_MS)
            .withEndAction {
                overlay.visibility = View.GONE
                overlay.alpha = 1f
                views.panel.scaleX = 1f
                views.panel.scaleY = 1f
            }
            .start()
    }
}
