package com.oo.seex.netlibrary.net.Api;

import android.text.TextUtils;

import com.app.baselibrary.base.app.BaseApplication;
import com.app.baselibrary.commonUtil.NetWorkUtils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.oo.seex.netlibrary.net.BaseApiConfig;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * desc: retrofit apiService 工厂类；
 * author: pl
 * date: 2017-03-09 21:02
 */

public class ServiceFactory {

    private static ServiceFactory sServiceFactory;

    static final int DEBUG_TYPE = 1;

    static final int RELEASE_TYPE = 2;

    /**
     * 设缓存有效期为两天
     */
    static final long CACHE_STALE_SEC = 60 * 60 * 24 * 2;

    /**
     *保存实例化的ApiService；
     */
//    private SparseArray<T> mApiManager = new SparseArray<T>();

    private Map<String ,Object> mApiMap = new HashMap<>();

    //读超时长，单位：毫秒
    private static final int READ_TIME_OUT = 30000;
    //连接时长，单位：毫秒
    private static final int CONNECT_TIME_OUT = 30000;

    public static ServiceFactory getInstance() {
        if (null == sServiceFactory) {
            synchronized (ServiceFactory.class) {
                if (null == sServiceFactory)
                    sServiceFactory = new ServiceFactory();
            }
        }
        return sServiceFactory;
    }


    /**
     * @param serviceClazz
     * @return
     */
    public <T> T createReleaseService(Class<T> serviceClazz) {
        return getApiService(RELEASE_TYPE, serviceClazz);
    }


    public <T> T createDebugService(Class<T> serviceClazz) {
        return getApiService(DEBUG_TYPE, serviceClazz);
    }

    private <T> T getApiService(int apiType, Class<T> serviceClazz) {
        T apiService = null;
        if (mApiMap.containsKey(serviceClazz.getName()) && mApiMap.get(serviceClazz.getName())!=null){
            apiService = (T)mApiMap.get(serviceClazz.getName());
        }
        if (null != apiService) {
            return apiService;
        } else {
            switch (apiType) {
                case DEBUG_TYPE:
                    apiService = createService(BaseApiConfig.getDebugHost(), serviceClazz);
                    break;
                case RELEASE_TYPE:
                    apiService = createService(BaseApiConfig.getReleaseHost(), serviceClazz);
                    break;
            }
            mApiMap.put(serviceClazz.getName(),apiService);
            return apiService;
        }

    }

    private <T> T createService(String baseUrl, Class<T> serviceClazz) {
        //开启Log
        HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor();
        logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        //缓存
        File cacheFile = new File(BaseApplication.getAppContext().getCacheDir(), "cache");
        Cache cache = new Cache(cacheFile, 1024 * 1024 * 100); //100Mb
        //增加头部信息application/x-www-form-urlencoded
        Interceptor headerInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request build = chain.request().newBuilder()
                        .addHeader("Content-Type", "application/json")
//                        .addHeader("User-Agent", OOAgent.getUserAgent(BaseApplication.getAppContext()))
                        .build();
                return chain.proceed(build);
            }
        };

        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .readTimeout(READ_TIME_OUT, TimeUnit.MILLISECONDS)
                .connectTimeout(CONNECT_TIME_OUT, TimeUnit.MILLISECONDS)
                .addInterceptor(mRewriteCacheControlInterceptor)
                .addNetworkInterceptor(mRewriteCacheControlInterceptor)
                .addInterceptor(headerInterceptor)
                .addInterceptor(logInterceptor)
                .cache(cache)
                .build();

        Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").serializeNulls().create();
        Retrofit retrofit = new Retrofit.Builder()
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .baseUrl(baseUrl)
                .build();
        return retrofit.create(serviceClazz);
    }


    /**
     * 云端响应头拦截器，用来配置缓存策略
     * Dangerous interceptor that rewrites the server's cache-control header.
     */
    private final static Interceptor mRewriteCacheControlInterceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            String cacheControl = request.cacheControl().toString();
            if (!NetWorkUtils.isNetConnected(BaseApplication.getAppContext())) {
                request = request.newBuilder()
                        .cacheControl(TextUtils.isEmpty(cacheControl) ? CacheControl.FORCE_NETWORK : CacheControl.FORCE_CACHE)
                        .build();
            }
            Response originalResponse = chain.proceed(request);
            if (NetWorkUtils.isNetConnected(BaseApplication.getAppContext())) {
                //有网的时候读接口上的@Headers里的配置，你可以在这里进行统一的设置

                return originalResponse.newBuilder()
                        .header("Cache-Control", cacheControl)
                        .removeHeader("Pragma")
                        .build();
            } else {
                return originalResponse.newBuilder()
                        .header("Cache-Control", "public, only-if-cached, max-stale=" + CACHE_STALE_SEC)
                        .removeHeader("Pragma")
                        .build();
            }
        }
    };

}
