package jp.juggler.subwaytooter.actmain

import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Typeface
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.DrawableCompat
import jp.juggler.subwaytooter.ActMain
import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.api.entity.TootStatus
import jp.juggler.subwaytooter.itemviewholder.ItemViewHolder
import jp.juggler.subwaytooter.pref.PrefB
import jp.juggler.subwaytooter.pref.PrefF
import jp.juggler.subwaytooter.pref.PrefI
import jp.juggler.subwaytooter.pref.PrefS
import jp.juggler.subwaytooter.pref.impl.StringPref
import jp.juggler.subwaytooter.span.MyClickableSpan
import jp.juggler.subwaytooter.stylerBoostAlpha
import jp.juggler.subwaytooter.stylerRoundRatio
import jp.juggler.subwaytooter.util.CustomShare
import jp.juggler.subwaytooter.view.ListDivider
import jp.juggler.util.data.clip
import jp.juggler.util.data.notEmpty
import jp.juggler.util.data.notZero
import jp.juggler.util.log.LogCategory
import jp.juggler.util.ui.attrColor
import jp.juggler.util.ui.getAdaptiveRippleDrawableRound
import org.jetbrains.anko.backgroundDrawable
import java.util.*
import kotlin.math.max

private val log = LogCategory("ActMainStyle")

private fun Float.dpToPx(context: Context) =
    (this * context.resources.displayMetrics.density + 0.5f).toInt()

// initUIから呼ばれる
fun reloadFonts() {
    ActMain.timelineFont = PrefS.spTimelineFont.value.notEmpty()?.let {
        try {
            Typeface.createFromFile(it)
        } catch (ex: Throwable) {
            log.e(ex, "timelineFont load failed")
            null
        }
    } ?: Typeface.DEFAULT

    ActMain.timelineFontBold = PrefS.spTimelineFontBold.value.notEmpty()?.let {
        try {
            Typeface.createFromFile(it)
        } catch (ex: Throwable) {
            log.e(ex, "timelineFontBold load failed")
            null
        }
    } ?: try {
        Typeface.create(ActMain.timelineFont, Typeface.BOLD)
    } catch (ex: Throwable) {
        log.e(ex, "timelineFontBold create from timelineFont failed")
        null
    } ?: Typeface.DEFAULT_BOLD
}

private fun ActMain.parseIconSize(stringPref: StringPref, minDp: Float = 1f) =
    (try {
        stringPref.value
            .toFloatOrNull()
            ?.takeIf { it.isFinite() && it >= minDp }
    } catch (ex: Throwable) {
        log.e(ex, "parseIconSize failed.")
        null
    } ?: stringPref.defVal.toFloat()).dpToPx(this)

// initUIから呼ばれる
fun ActMain.reloadIconSize() {
    avatarIconSize = parseIconSize(PrefS.spAvatarIconSize)
    notificationTlIconSize = parseIconSize(PrefS.spNotificationTlIconSize)
    ActMain.boostButtonSize = parseIconSize(PrefS.spBoostButtonSize)
    ActMain.replyIconSize = parseIconSize(PrefS.spReplyIconSize)
    ActMain.headerIconSize = parseIconSize(PrefS.spHeaderIconSize)
    ActMain.stripIconSize = parseIconSize(PrefS.spStripIconSize)
    ActMain.screenBottomPadding = parseIconSize(PrefS.spScreenBottomPadding, minDp = 0f)

    ActMain.eventFadeAlpha = PrefS.spEventTextAlpha.value
        .toFloatOrNull()
        ?.takeIf { it.isFinite() }
        ?.clip(0f, 1f)
        ?: 1f
}

// initUIから呼ばれる
fun reloadRoundRatio() {
    val sizeDp = when {
        PrefB.bpDontRound.value -> 0f
        else -> PrefS.spRoundRatio.value
            .toFloatOrNull()
            ?.takeIf { it.isFinite() }
            ?: 33f
    }
    stylerRoundRatio = (sizeDp / 100f).clip(0f, 1f) * 0.5f
}

// initUI から呼ばれる
fun reloadBoostAlpha() {
    stylerBoostAlpha = PrefS.spBoostAlpha.value
        .toIntOrNull()
        ?.toFloat()
        ?.let { (it + 0.5f) / 100f }
        ?.takeIf { it > 0f && it < 1f }
        ?: 1f
}

fun ActMain.reloadMediaHeight() {
    appState.mediaThumbHeight = (
            PrefS.spMediaThumbHeight.value
                .toFloatOrNull()
                ?.takeIf { it >= 32f }
                ?: 64f
            ).dpToPx(this)
}

private fun Float.clipFontSize(): Float =
    if (isNaN()) this else max(1f, this)

fun ActMain.reloadTextSize() {
    timelineFontSizeSp = PrefF.fpTimelineFontSize.value.clipFontSize()
    acctFontSizeSp = PrefF.fpAcctFontSize.value.clipFontSize()
    notificationTlFontSizeSp = PrefF.fpNotificationTlFontSize.value.clipFontSize()
    headerTextSizeSp = PrefF.fpHeaderTextSize.value.clipFontSize()
    val fv = PrefS.spTimelineSpacing.value.toFloatOrNull()
    timelineSpacing = if (fv != null && fv.isFinite() && fv != 0f) fv else null
}

fun ActMain.loadColumnMin() =
    (PrefS.spColumnWidth.value
        .toFloatOrNull()
        ?.takeIf { it.isFinite() && it >= 100f }
        ?: ActMain.COLUMN_WIDTH_MIN_DP.toFloat()
            ).dpToPx(this)

fun ActMain.justifyWindowContentPortrait() {
    when (PrefI.ipJustifyWindowContentPortrait.value) {
        PrefI.JWCP_START -> {
            val iconW = (ActMain.stripIconSize * 1.5f + 0.5f).toInt()
            val padding = resources.displayMetrics.widthPixels / 2 - iconW

            fun ViewGroup.addViewBeforeLast(v: View) = addView(v, childCount - 1)
            (svColumnStrip.parent as LinearLayout).addViewBeforeLast(
                View(this).apply {
                    layoutParams = LinearLayout.LayoutParams(padding, 0)
                }
            )
            llQuickPostBar.addViewBeforeLast(
                View(this).apply {
                    layoutParams = LinearLayout.LayoutParams(padding, 0)
                }
            )
        }

        PrefI.JWCP_END -> {
            val iconW = (ActMain.stripIconSize * 1.5f + 0.5f).toInt()
            val borderWidth = 1f.dpToPx(this)
            val padding = resources.displayMetrics.widthPixels / 2 - iconW - borderWidth

            fun ViewGroup.addViewAfterFirst(v: View) = addView(v, 1)
            (svColumnStrip.parent as LinearLayout).addViewAfterFirst(
                View(this).apply {
                    layoutParams = LinearLayout.LayoutParams(padding, 0)
                }
            )
            llQuickPostBar.addViewAfterFirst(
                View(this).apply {
                    layoutParams = LinearLayout.LayoutParams(padding, 0)
                }
            )
        }
    }
}

//////////////////////////////////////////////////////

// onStart時に呼ばれる
fun reloadTimeZone() {
    try {
        var tz = TimeZone.getDefault()
        val tzId = PrefS.spTimeZone.value
        if (tzId.isNotEmpty()) {
            tz = TimeZone.getTimeZone(tzId)
        }
        log.w("reloadTimeZone: tz=${tz.displayName}")
        TootStatus.dateFormatFull.timeZone = tz
    } catch (ex: Throwable) {
        log.e(ex, "getTimeZone failed.")
    }
}

// onStart時に呼ばれる
// カラーカスタマイズを読み直す
fun ActMain.reloadColors() {
    ListDivider.color = PrefI.ipListDividerColor.value
    TabletColumnDivider.color = PrefI.ipListDividerColor.value
    ItemViewHolder.toot_color_unlisted = PrefI.ipTootColorUnlisted.value
    ItemViewHolder.toot_color_follower = PrefI.ipTootColorFollower.value
    ItemViewHolder.toot_color_direct_user = PrefI.ipTootColorDirectUser.value
    ItemViewHolder.toot_color_direct_me = PrefI.ipTootColorDirectMe.value
    MyClickableSpan.showLinkUnderline = PrefB.bpShowLinkUnderline.value
    MyClickableSpan.defaultLinkColor = PrefI.ipLinkColor.value.notZero()
        ?: attrColor(R.attr.colorLink)

    CustomShare.reloadCache(this)
}

fun ActMain.showFooterColor() {
    val footerButtonBgColor = PrefI.ipFooterButtonBgColor.value
    val footerButtonFgColor = PrefI.ipFooterButtonFgColor.value
    val footerTabBgColor = PrefI.ipFooterTabBgColor.value
    val footerTabDividerColor = PrefI.ipFooterTabDividerColor.value
    val footerTabIndicatorColor = PrefI.ipFooterTabIndicatorColor.value

    val colorColumnStripBackground = footerTabBgColor.notZero()
        ?: attrColor(R.attr.colorColumnStripBackground)

    svColumnStrip.setBackgroundColor(colorColumnStripBackground)
    llQuickPostBar.setBackgroundColor(colorColumnStripBackground)

    vBottomPadding.setBackgroundColor(colorColumnStripBackground)

    val colorButtonBg = footerButtonBgColor.notZero()
        ?: colorColumnStripBackground

    val colorButtonFg = footerButtonFgColor.notZero()
        ?: attrColor(R.attr.colorRippleEffect)

    btnMenu.backgroundDrawable =
        getAdaptiveRippleDrawableRound(this, colorButtonBg, colorButtonFg)
    btnToot.backgroundDrawable =
        getAdaptiveRippleDrawableRound(this, colorButtonBg, colorButtonFg)
    btnQuickToot.backgroundDrawable =
        getAdaptiveRippleDrawableRound(this, colorButtonBg, colorButtonFg)
    ivQuickTootAccount.backgroundDrawable =
        getAdaptiveRippleDrawableRound(this, colorButtonBg, colorButtonFg)
    btnQuickPostMenu.backgroundDrawable =
        getAdaptiveRippleDrawableRound(this, colorButtonBg, colorButtonFg)

    var c = footerButtonFgColor.notZero() ?: attrColor(R.attr.colorTextContent)
    val d = ContextCompat.getDrawable(this, R.drawable.ic_question)
        ?.let { DrawableCompat.wrap(it).apply { setTint(c) } }
    ivQuickTootAccount.setDefaultImage(d)

    val csl = ColorStateList.valueOf(
        footerButtonFgColor.notZero() ?: attrColor(R.attr.colorTextContent)
    )
    btnToot.imageTintList = csl
    btnMenu.imageTintList = csl
    btnQuickToot.imageTintList = csl
    btnQuickPostMenu.imageTintList = csl

    c = footerTabDividerColor.notZero() ?: colorColumnStripBackground
    vFooterDivider1.setBackgroundColor(c)
    vFooterDivider2.setBackgroundColor(c)

    llColumnStrip.indicatorColor =
        footerTabIndicatorColor.notZero() ?: attrColor(R.attr.colorTextHelp)
}

fun ActMain.closePopup() {
    try {
        popupStatusButtons?.dismiss()
    } catch (ignored: Throwable) {
    }
    popupStatusButtons = null
}
