package com.mogo.cloud.network

import java.util.concurrent.locks.ReentrantReadWriteLock

object WeakNetworkManager {

    private var weakHttpListener: OnWeakHttpListener? = null

    @Volatile
    var WEAK_HTTP_RTT_THRESHOLD = 500

    @Volatile
    var FAILURE_THRESHOLD = 10

    @Volatile
    var isDebug = true

    private val lock by lazy {
        ReentrantReadWriteLock()
    }
    private val writeLock by lazy {
        lock.writeLock()
    }
    private val readLock by lazy {
        lock.readLock()
    }

    private var failCount = 0L

    fun setListener(weakHttpListener: OnWeakHttpListener?) {
        this.weakHttpListener = weakHttpListener
    }

    internal val listener = object : WeakNetworkEventFactory.OnHttpRttListener {
        override fun onHttpRttReceived(hashCode: Int, url: String, timeStamp: Long) {
            weakHttpListener?.onHttpRttReceived(hashCode, url, timeStamp)
            if (timeStamp > WEAK_HTTP_RTT_THRESHOLD) {
                weakHttpListener?.onWeakNetworkEvent()
            }
        }

        override fun onFailEvent(hashCode: Int, url: String, timeStamp: Long) {
            val failCount = increment()
            weakHttpListener?.onFailEvent(hashCode, url, timeStamp, failCount)
            if (failCount >= FAILURE_THRESHOLD) {
                clearFailCount()
                weakHttpListener?.onWeakNetworkEvent()
            }
        }
    }

    private fun increment(): Long {
        writeLock.lock()
        try {
            return ++failCount
        } finally {
            writeLock.unlock()
        }
    }

    private fun clearFailCount() {
        writeLock.lock()
        try {
            failCount = 0
        } finally {
            writeLock.unlock()
        }
    }

    private fun getFailCount(): Long {
        readLock.lock()
        try {
            return failCount
        } finally {
            readLock.unlock()
        }
    }

    interface OnWeakHttpListener {
        fun onHttpRttReceived(hashCode: Int, url: String, timeStamp: Long)
        fun onFailEvent(hashCode: Int, url: String, timeStamp: Long, currentFailCount: Long)
        fun onWeakNetworkEvent()
    }
}