package com.adealink.weparty.webview.loader

import android.webkit.WebResourceResponse
import com.adealink.weparty.webview.stat.WebViewStatEvent
import java.util.*

interface IResourceLoader {

    companion object {
        private val REPORT_HEADERS = setOf(
            "pragme",//HTTP 1.0，只有 no-cache 这一个值
            "cache-control",
            "expires",//HTTP 1.0，缓存过期的时间点（服务端时间）
            "last-modified",//资源最后更新的时间
            "if-modified-since",//请求回传的缓存资源最后更新时间
            "date",//请求时间
            "etag",//资源计算得出一个唯一标志符
            "if-none-match",//请求头回传的缓存ETag
            "x-swift-cachetime",//CDN节点上的允许缓存时间，即该文件可以在CDN节点上缓存多久，是指文件在CDN节点缓存的总时间。计算还有多久需要回源刷新= ’X-Swift-CacheTime’ – ‘Age’
            "x-swift-savetime",//CDN节点上的缓存RS（swift）的时间，即该文件是在什么时间缓存到CDN节点上
            "x-cache", //HIT：表示已缓存, MISS：节点上无该文件的缓存，回源请求
            "via",//请求经过的cdn节点
            "age"//为CDN返回的头部字段，表示该文件在CDN节点上缓存的时间，单位为秒。只有文件存在于节点上Age字段才会出现，当文件被刷新后或者文件被清除的首次访问，在此前文件并未缓存，无Age头部字段，需要注意当Age为0时，表示节点已有文件的缓存，但由于缓存已过期，本次无法直接使用该缓存，需回源校验。
        )
    }

    fun load(request: ResourceRequest): WebResourceResponse?

    fun report(
        loaderType: LoaderType,
        url: String,
        method: String,
        cacheType: WebCacheType,
        redirect: Boolean,
        code: Int,
        protocol: String,
        reqHeaders: Map<String, String>,
        resHeaders: Map<String, String>,
        duration: Long //ms
    ) {
        WebViewStatEvent(WebViewStatEvent.Action.LOAD)
            .apply {
                uri to url
                type to loaderType.type
                this.method to method
                this.code to code
                this.cache to when (cacheType) {
                    WebCacheType.NO_LOCAL_CACHE -> WebViewStatEvent.Cache.NO_CACHE
                    WebCacheType.DIRECT_LOCAL_CACHE -> WebViewStatEvent.Cache.DIRECT_CACHE
                    WebCacheType.REDIRECT_LOCAL_CACHE -> WebViewStatEvent.Cache.REDIRECT_CACHE
                }
                this.redirect to if (redirect) WebViewStatEvent.Redirect.TRUE else WebViewStatEvent.Redirect.FALSE
                this.duration to duration
                this.protocol to protocol
                addEventMap(filterHeaders(reqHeaders))
                addEventMap(filterHeaders(resHeaders))
            }
            .send()
    }

    fun filterHeaders(map: Map<String, String>): Map<String, String> {
        val filterHeaders = hashMapOf<String, String>()
        map.entries.forEach {
            val lowerKey = it.key.lowercase(Locale.ROOT)
            if (REPORT_HEADERS.contains(lowerKey)) {
                filterHeaders[lowerKey.replace("-", "_")] = it.value
            }
        }
        return filterHeaders
    }

}