package com.gh.common.browse

import android.os.Handler
import android.os.Looper
import android.os.Message
import androidx.lifecycle.*
import androidx.lifecycle.Lifecycle.Event

/**
 * 浏览时长计时器核心接口类，用于页面浏览时长相关埋点上报
 */
interface IBrowseTimerCore {
    /**
     * 开始计时
     */
    fun start()

    /**
     * 结束计时
     */
    fun stop()
}

/**
 * 浏览时长计时器核心实现类
 */
class BrowseTimerCore internal constructor() : IBrowseTimerCore {

    /**
     * 延迟执行的时间
     */
    var delayInMills: Long = 3000L

    /**
     * 开始计时函数回调
     */
    var onStart: (() -> Unit)? = null

    /**
     * 结束计时函数回调
     */
    var onResult: ((Long) -> Unit)? = null

    /**
     * 开始计时的时间点
     */
    private var startTimeInMills: Long = 0L

    /**
     * Handler操作类
     */
    private val handler = object : Handler(Looper.getMainLooper()) {
        override fun handleMessage(msg: Message) {
            if (msg.what == MESSAGE_START) {
                dispatchOnStart()
            }
        }
    }

    /**
     * 延迟执行开始计时
     * @see delayInMills
     * @see onStart
     */
    override fun start() {
        if (delayInMills <= 0) {
            dispatchOnStart()
        } else {
            handler.sendEmptyMessageDelayed(MESSAGE_START, delayInMills)
        }
    }

    /**
     * 结束计时，统计浏览时长并回调结束计时函数
     * @see onResult
     */
    override fun stop() {
        handler.removeMessages(MESSAGE_START)
        if (startTimeInMills > 0L) {
            onResult?.invoke(System.currentTimeMillis() - startTimeInMills)
            startTimeInMills = 0L
        }
    }

    /**
     * 开始计时，回调开始计时函数
     */
    private fun dispatchOnStart() {
        startTimeInMills = System.currentTimeMillis()
        onStart?.invoke()
    }

    companion object {
        private const val MESSAGE_START = 1
    }
}

/**
 * 无数据浏览计时器接口类
 */
interface IBrowseTimer : IBrowseTimerCore {

    fun withDelayInMills(delayInMills: Long): IBrowseTimer

    fun withStart(onStart: () -> Unit): IBrowseTimer

    fun withResult(onResult: (Long) -> Unit): IBrowseTimer
}

/**
 * 无数据的浏览计时器实现类
 */
class BrowseTimer : IBrowseTimer {

    private val core = BrowseTimerCore()

    private var isStarted: Boolean = false

    override fun withDelayInMills(delayInMills: Long): IBrowseTimer {
        core.delayInMills = delayInMills
        return this
    }

    override fun withStart(onStart: () -> Unit): IBrowseTimer {
        core.onStart = onStart
        return this
    }

    override fun withResult(onResult: (Long) -> Unit): IBrowseTimer {
        core.onResult = onResult
        return this
    }

    override fun start() {
        if (isStarted) return

        isStarted = true
        core.start()
    }

    override fun stop() {
        if (!isStarted) return

        core.stop()
        isStarted = false
    }

}

/**
 * 支持Lifecycle的无数据的浏览计时器
 */
class LifecycleBoundBrowseTimer internal constructor(
    private val base: IBrowseTimer,
    private val onStateChanged: (IBrowseTimer, Event) -> Unit
) : IBrowseTimer, LifecycleEventObserver {
    override fun withDelayInMills(delayInMills: Long): IBrowseTimer {
        return base.withDelayInMills(delayInMills)
    }

    override fun withStart(onStart: () -> Unit): IBrowseTimer {
        return base.withStart(onStart)
    }

    override fun withResult(onResult: (Long) -> Unit): IBrowseTimer {
        return base.withResult(onResult)
    }

    override fun start() {
        base.start()
    }

    override fun stop() {
        base.stop()
    }

    override fun onStateChanged(source: LifecycleOwner, event: Event) {
        onStateChanged.invoke(this, event)
    }

}

fun IBrowseTimer.withLifecycle(
    owner: LifecycleOwner,
    onStateChanged: (IBrowseTimer, Event) -> Unit = { timer, event ->
        when(event) {
            Event.ON_START -> timer.start()
            Event.ON_STOP -> timer.stop()
            else -> {}
        }
    }
): LifecycleBoundBrowseTimer = LifecycleBoundBrowseTimer(this, onStateChanged).apply {
    owner.lifecycle.addObserver(this)
}

/**
 * 带数据的浏览计时器接口类
 */
interface IValueBrowseTimer<T> : IBrowseTimerCore {

    fun withDelayInMills(delayInMills: Long): IValueBrowseTimer<T>

    fun withStart(onStart: (T?) -> Unit): IValueBrowseTimer<T>

    fun withResult(onResult: (T?, Long) -> Unit): IValueBrowseTimer<T>

    fun dispatchValue(value: T?)
}

/**
 * 带数据的浏览计时器实现类
 */
class ValueBrowseTimer<T> : IValueBrowseTimer<T> {

    private val core = BrowseTimerCore()

    private var isDispatchValue: Boolean = false

    private var isStarted: Boolean = false

    private var value: T? = null

    override fun withDelayInMills(delayInMills: Long): IValueBrowseTimer<T> {
        core.delayInMills = delayInMills
        return this
    }

    override fun withStart(onStart: (T?) -> Unit): IValueBrowseTimer<T> {
        core.onStart = { onStart.invoke(value) }
        return this
    }

    override fun withResult(onResult: (T?, Long) -> Unit): IValueBrowseTimer<T> {
        core.onResult = { onResult.invoke(value, it) }
        return this
    }

    override fun start() {
        if (isStarted) return

        isStarted = true

        if (isDispatchValue) {
            core.start()
        }
    }

    override fun stop() {
        if (!isStarted) return

        core.stop()
        isStarted = false
    }

    override fun dispatchValue(value: T?) {
        this.value = value

        if (isStarted && !isDispatchValue) {
            core.start()
        }
        isDispatchValue = true
    }

}

/**
 * 支持LiveData的带数据的浏览计时器
 */
class ObserverBoundValueBrowseTimer<T> internal constructor(private val base: IValueBrowseTimer<T>) : IValueBrowseTimer<T>, Observer<T> {
    override fun withDelayInMills(delayInMills: Long): IValueBrowseTimer<T> {
        return base.withDelayInMills(delayInMills)
    }

    override fun withResult(onResult: (T?, Long) -> Unit): IValueBrowseTimer<T> {
        return base.withResult(onResult)
    }

    override fun withStart(onStart: (T?) -> Unit): IValueBrowseTimer<T> {
        return base.withStart(onStart)
    }

    override fun start() {
        base.start()
    }

    override fun stop() {
        base.stop()
    }

    override fun dispatchValue(value: T?) {
        base.dispatchValue(value)
    }

    override fun onChanged(t: T) {
        dispatchValue(t)
    }
}


/**
 * 支持Lifecycle的带数据的浏览计时器
 */
class LifecycleBoundValueBrowseTimer<T> internal constructor(
    private val base: IValueBrowseTimer<T>,
    private val onStateChanged: (IValueBrowseTimer<T>, Event) -> Unit
) : IValueBrowseTimer<T>, LifecycleEventObserver {
    override fun withDelayInMills(delayInMills: Long): IValueBrowseTimer<T> {
        return base.withDelayInMills(delayInMills)
    }

    override fun withResult(onResult: (T?, Long) -> Unit): IValueBrowseTimer<T> {
        return base.withResult(onResult)
    }

    override fun withStart(onStart: (T?) -> Unit): IValueBrowseTimer<T> {
        return base.withStart(onStart)
    }

    override fun start() {
        base.start()
    }

    override fun stop() {
        base.stop()
    }

    override fun dispatchValue(value: T?) {
        base.dispatchValue(value)
    }

    override fun onStateChanged(source: LifecycleOwner, event: Event) {
        onStateChanged.invoke(this, event)
    }

}

fun <T> IValueBrowseTimer<T>.asObserver(): ObserverBoundValueBrowseTimer<T> = ObserverBoundValueBrowseTimer(this)

fun <T> IValueBrowseTimer<T>.withLifecycle(
    owner: LifecycleOwner,
    onStateChanged: (IValueBrowseTimer<T>, Event) -> Unit = { timer, event ->
        when(event) {
            Event.ON_START -> timer.start()
            Event.ON_STOP -> timer.stop()
            else -> {}
        }
    }
): LifecycleBoundValueBrowseTimer<T> = LifecycleBoundValueBrowseTimer(this, onStateChanged).apply {
    owner.lifecycle.addObserver(this)
}

