package com.ydl.ydlnet.builder.manage

import com.ydl.ydlnet.YDLHttpUtils
import com.ydl.ydlnet.builder.factory.ApiFactory
import okhttp3.HttpUrl
import okhttp3.Interceptor
import okhttp3.Request
import java.util.*

/**
 * Created by haorui on 2019-09-02 .
 * Des: 多域名管理类
 */
class HttpUrlManager private constructor() {
    open val mRedirectInterceptor: Interceptor
    val DOMAIN = "Domain-Name"
    
    open var mDomainNameHub: MutableMap<String, String>? = null

    /**
     * 获取全局唯一的baseUrl
     *
     * @return url
     */
    val url: String?
        get() = getUrlByKey(DEFAULT_URL_KEY)

    init {
        mDomainNameHub = HashMap()
        this.mRedirectInterceptor = Interceptor { chain -> chain.proceed(processRequest(chain.request())) }
    }

    /**
     * 一次性传入urlMap
     *
     * @param urlMap map
     * @return HttpUrlManager
     */
    fun setMultipleUrl(urlMap: MutableMap<String, String>): HttpUrlManager {
        if (urlMap.isNotEmpty()){
            this.mDomainNameHub?.putAll(urlMap)
        }
        return this
    }

    /**
     * 向map中添加url
     *
     * @param urlKey   key
     * @param urlValue value
     * @return HttpUrlManager
     */
    fun addUrl(urlKey: String, urlValue: String): HttpUrlManager {
        mDomainNameHub!![urlKey] = urlValue
        return this
    }

    /**
     * 从map中删除某个url
     *
     * @param urlKey 需要删除的urlKey
     * @return HttpUrlManager
     */
    fun removeUrlByKey(urlKey: String): HttpUrlManager {
        mDomainNameHub!!.remove(urlKey)
        return this
    }

    /**
     * 针对单个baseUrl切换的时候清空老baseUrl的所有信息
     *
     * @param urlValue url
     * @return HttpUrlManager
     */
    fun setUrl(urlValue: String): HttpUrlManager {
        mDomainNameHub!![DEFAULT_URL_KEY] = urlValue
        return this
    }

    /**
     * 根据key
     *
     * @param urlKey 获取对应的url
     * @return url
     */
    fun getUrlByKey(urlKey: String): String? {
        return mDomainNameHub!![urlKey]
    }

    /**
     * 清空设置的url相关的所以信息
     * 相当于重置url
     * 动态切换生产测试环境时候调用
     *
     * @return HttpUrlManager
     */
    fun clear(): HttpUrlManager {
        mDomainNameHub!!.clear()
        ApiFactory.getInstance().clearAllApi()
        YDLHttpUtils.removeAllCookie()
        return this
    }

    companion object {

        @Volatile
        private var instance: HttpUrlManager? = null

        var DEFAULT_URL_KEY = "http_default_url_key"

        fun getInstance(): HttpUrlManager? {
            if (instance == null) {
                synchronized(HttpUrlManager::class.java) {
                    if (instance == null) {
                        instance = HttpUrlManager()
                    }
                }
            }
            return instance
        }
    }


    //========================================

    /**
     *解析Request的Header
     */
    private fun processRequest(request: Request): Request {
        var newBuilder = request.newBuilder()
        var domainName = obtainDomainNameFromHeaders(request)
        var httpUrl: HttpUrl? = null
        if (domainName.isNotEmpty()) {
            httpUrl = fetchDomain(domainName)?.let { checkUrl(it) }
            newBuilder.removeHeader(DOMAIN)
        }
        if (null != httpUrl) {
            val newUrl = parseUrl(httpUrl, request.url())
            return newBuilder.url(newUrl).build()
        }
        return newBuilder.build()
    }

    /**
     * 解析请求的Header
     */
    private fun obtainDomainNameFromHeaders(request: Request): String {
        val headers = request.headers(DOMAIN)
        if (headers == null || headers.size == 0)
            return ""
        if (headers.size > 1)
            throw IllegalArgumentException("Only one Domain-Name in the headers")
        return request.header(DOMAIN)!!
    }


    /**
     *获得Header对应的HttpUrl
     */
    fun fetchDomain(domainName: String): String? {
        return mDomainNameHub?.get(domainName)
    }

    fun parseUrl(domainUrl: HttpUrl, url: HttpUrl): HttpUrl {
        return checkUrl(url.toString().replace(this.url?:url.host(),domainUrl.toString()))
//        return url.newBuilder()
//            .scheme(domainUrl.scheme())
//            .host(domainUrl.host())
//            .port(domainUrl.port())
//            .build()
    }

    /**
     * 包装url类型String->HttpUrl
     */
    fun checkUrl(url: String): HttpUrl {
        val parseUrl = HttpUrl.parse(url)
        return parseUrl!!
    }

    

}