package com.gh.gamecenter.common.tracker

import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import java.util.*
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicLong
import kotlin.concurrent.fixedRateTimer

/**
 * 应用生命周期观察者
 */
class AppLifecycleWatcher(private val mTrack: ITrack) : DefaultLifecycleObserver {

    private var mWatchVisibleCount = 0 // 检查是否满足上传可见的次数

    private val mLastVisibleTime by lazy { AtomicLong(0L) } // 最后可见时间
    private val mIsVisible by lazy { AtomicBoolean(false) } // 当前是否可见
    private val mWatchInterval by lazy { AtomicLong(MIN_WATCH_VISIBLE_INTERVAL) } // 与上次上报可见的间隔时间

    init {
        fixedRateTimer(
            FIXED_RATE_TIMER_NAME,
            initialDelay = MIN_WATCH_VISIBLE_INTERVAL,
            period = MIN_WATCH_VISIBLE_INTERVAL
        ) {
            if (mIsVisible.get()) {
                // 单位间隔发送
                val meetLogVisibleInterval = (mWatchVisibleCount++) * MIN_WATCH_VISIBLE_INTERVAL == mWatchInterval.get()

                val equalToMinVisibleInterval = mWatchInterval.get() == MIN_WATCH_VISIBLE_INTERVAL
                val equalToMaxVisibleInterval = mWatchInterval.get() == MAX_WATCH_VISIBLE_INTERVAL

                if (meetLogVisibleInterval || equalToMinVisibleInterval) {
                    // 上报完重置计数
                    mWatchVisibleCount = 0
                    mTrack.onAppVisible(mWatchInterval.get() / 1000)
                    if (!equalToMaxVisibleInterval) {
                        mWatchInterval.set(mWatchInterval.get() * 2) // 间隔递增两倍
                    }
                }
            }
        }
    }

    override fun onStart(owner: LifecycleOwner) {
        super.onStart(owner)

        if (mLastVisibleTime.get() == 0L
            || (mLastVisibleTime.get() + SESSION_ALIVE_INTERVAL) < System.currentTimeMillis() / 1000
        ) {
            mTrack.onSessionChanged(UUID.randomUUID().toString())
        }
        mIsVisible.set(true)

        mTrack.onAppStarted()
    }

    override fun onStop(owner: LifecycleOwner) {
        super.onStop(owner)

        mIsVisible.set(false)
        mLastVisibleTime.set(System.currentTimeMillis() / 1000)
        mWatchInterval.set(MIN_WATCH_VISIBLE_INTERVAL)

        mTrack.onAppStopped()
    }

    companion object {
        private const val FIXED_RATE_TIMER_NAME = "APP_TRACKER_TIMER"

        private const val SESSION_ALIVE_INTERVAL = 30L // 30s
        private const val MIN_WATCH_VISIBLE_INTERVAL = 5000L // 5s
        private const val MAX_WATCH_VISIBLE_INTERVAL = 320000L // 320s
    }

}