package com.tomhempel.rbarometer.ui

import android.content.Context
import android.content.res.ColorStateList
import android.util.TypedValue
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.content.ContextCompat
import com.google.android.material.card.MaterialCardView
import com.tomhempel.rbarometer.R
import com.tomhempel.rbarometer.utils.ViewUtils

object SessionMeasureUi {

    fun indicatorSymbol(checked: Boolean, isCurrent: Boolean = false): String = when {
        checked -> "\u2713"
        isCurrent -> "\u2022"
        else -> "\u25CB"
    }

    fun measureRow(
        context: Context,
        label: String,
        checked: Boolean,
        isCurrent: Boolean = false,
        verticalPaddingDp: Int = 7,
        labelTextSizeSp: Float = 14f,
        highlightCurrentRow: Boolean = false,
        selectable: Boolean = false,
        onSelect: (() -> Unit)? = null,
        statusText: String? = null,
    ): View {
        if (highlightCurrentRow) {
            return cardMeasureRow(
                context = context,
                label = label,
                checked = checked,
                isCurrent = isCurrent,
                selectable = selectable,
                onSelect = onSelect,
                statusText = statusText,
            )
        }
        return compactMeasureRow(
            context = context,
            label = label,
            checked = checked,
            isCurrent = isCurrent,
            verticalPaddingDp = verticalPaddingDp,
            labelTextSizeSp = labelTextSizeSp,
        )
    }

    private fun cardMeasureRow(
        context: Context,
        label: String,
        checked: Boolean,
        isCurrent: Boolean,
        selectable: Boolean,
        onSelect: (() -> Unit)?,
        statusText: String?,
    ): View {
        val root = LayoutInflater.from(context).inflate(R.layout.item_session_measure_row, null, false)
        val card = root.findViewById<MaterialCardView>(R.id.sessionMeasureCard)
        val indicatorWrap = root.findViewById<FrameLayout>(R.id.sessionMeasureIndicatorWrap)
        val indicator = root.findViewById<TextView>(R.id.sessionMeasureIndicator)
        val title = root.findViewById<TextView>(R.id.sessionMeasureTitle)
        val status = root.findViewById<TextView>(R.id.sessionMeasureStatus)

        title.text = label
        indicator.text = indicatorSymbol(checked, isCurrent)

        when {
            isCurrent && checked -> {
                card.setCardBackgroundColor(color(context, R.color.brand_questionnaire_highlight_bg))
                card.strokeWidth = ViewUtils.dp(context, 2)
                card.setStrokeColor(ColorStateList.valueOf(color(context, R.color.brand_purple)))
                indicatorWrap.setBackgroundResource(R.drawable.bg_measure_row_done)
                indicator.setTextColor(color(context, R.color.brand_text_on_dark))
            }
            isCurrent -> {
                card.setCardBackgroundColor(color(context, R.color.brand_questionnaire_highlight_bg))
                card.strokeWidth = ViewUtils.dp(context, 2)
                card.setStrokeColor(ColorStateList.valueOf(color(context, R.color.brand_purple)))
                indicatorWrap.setBackgroundResource(R.drawable.bg_measure_row_pending)
                indicator.setTextColor(color(context, R.color.brand_purple))
            }
            checked -> {
                card.setCardBackgroundColor(color(context, R.color.brand_header_surface))
                card.strokeWidth = ViewUtils.dp(context, 1)
                card.setStrokeColor(ColorStateList.valueOf(color(context, R.color.brand_purple)))
                indicatorWrap.setBackgroundResource(R.drawable.bg_measure_row_done)
                indicator.setTextColor(color(context, R.color.brand_text_on_dark))
            }
            else -> {
                card.setCardBackgroundColor(color(context, R.color.brand_header_surface))
                card.strokeWidth = ViewUtils.dp(context, 1)
                card.setStrokeColor(ColorStateList.valueOf(color(context, R.color.brand_card_stroke)))
                indicatorWrap.setBackgroundResource(R.drawable.bg_measure_row_pending)
                indicator.setTextColor(color(context, R.color.brand_text_muted))
            }
        }

        if (statusText.isNullOrBlank()) {
            status.visibility = View.GONE
        } else {
            status.visibility = View.VISIBLE
            status.text = statusText
            status.setTextColor(
                color(
                    context,
                    when {
                        isCurrent -> R.color.brand_purple
                        checked -> R.color.brand_text_muted
                        else -> R.color.brand_text_muted
                    },
                ),
            )
            if (isCurrent) status.setTypeface(status.typeface, android.graphics.Typeface.BOLD)
        }

        if (selectable) {
            card.isClickable = true
            card.isFocusable = true
            val ripple = TypedValue()
            if (context.theme.resolveAttribute(android.R.attr.selectableItemBackground, ripple, true)) {
                card.foreground = ContextCompat.getDrawable(context, ripple.resourceId)
            }
            card.setOnClickListener { onSelect?.invoke() }
        }
        return root
    }

    private fun compactMeasureRow(
        context: Context,
        label: String,
        checked: Boolean,
        isCurrent: Boolean,
        verticalPaddingDp: Int,
        labelTextSizeSp: Float,
    ): View = LinearLayout(context).apply {
        orientation = LinearLayout.HORIZONTAL
        gravity = Gravity.CENTER_VERTICAL
        setPadding(0, ViewUtils.dp(context, verticalPaddingDp), 0, 0)
        val indicatorSize = ViewUtils.dp(context, 22)
        addView(TextView(context).apply {
            gravity = Gravity.CENTER
            text = indicatorSymbol(checked, isCurrent)
            minWidth = indicatorSize
            minHeight = indicatorSize
            setTextSize(TypedValue.COMPLEX_UNIT_SP, if (checked) 14f else 16f)
            setTypeface(typeface, android.graphics.Typeface.BOLD)
            setTextColor(
                color(
                    context,
                    when {
                        checked -> R.color.brand_purple
                        isCurrent -> R.color.brand_purple
                        else -> R.color.brand_text_muted
                    },
                ),
            )
        })
        addView(TextView(context).apply {
            text = label
            setPadding(ViewUtils.dp(context, 8), 0, 0, 0)
            setTextSize(TypedValue.COMPLEX_UNIT_SP, labelTextSizeSp)
            setLineSpacing(0f, 1.2f)
            setTextColor(color(context, R.color.brand_text_dark))
            if (isCurrent) setTypeface(typeface, android.graphics.Typeface.BOLD)
        })
    }

    private fun color(context: Context, res: Int) = ContextCompat.getColor(context, res)
}
