package com.kiisoo.ic.utils;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.kiisoo.aegis.common.faces.util.ErrorMesage;
import com.kiisoo.aegis.common.faces.util.MessageException;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @author dexiang
 * @date 2017/10/30
 * @company kiisoo
 * @details okhttp工具类
 */
public class OkhttpUtil {

    /**
     * 日志打印
     */
    private static final Logger logger = LoggerFactory.getLogger(OkhttpUtil.class);

    /**
     * 实例
     */
    private static OkhttpUtil instance;

    /**
     * 请求管理实例
     */
    private OkHttpClient okHttpClient;

    /**
     * 认证token
     */
    private static String authorization;

    /**
     * 客流认证token
     */
    private static String token;

    public static String getToken() {
        return token;
    }

    public static void setToken(String token) {
        OkhttpUtil.token = token;
    }


    /**
     * 错误的key
     */
    private static final String ERROS = "erros";

    /**
     * 此处配置OkHttpClient的基本信息 okhttp3在new对象并需要配置参数一般通过build这个方法来实现 类似的还有Request
     * 构建形式如:new XXX.Builder().xxx().xxx().build();
     *
     * @author dexiang.jiang
     */
    private OkhttpUtil() {
        okHttpClient = new OkHttpClient.Builder().connectTimeout(60, TimeUnit.SECONDS).readTimeout(30, TimeUnit.SECONDS)
                .build();
    }

    /**
     * 单例模式
     *
     * @return 返回OkhttpUtil实例
     * @author dexiang.jiang
     */
    public static OkhttpUtil getInstance() {
        if (instance == null) {
            synchronized (OkhttpUtil.class) {
                if (instance == null) {
                    instance = new OkhttpUtil();
                }
            }
        }
        return instance;
    }

    /**
     * 传入JSON字符串结果 判断错误信息并抛出异常
     *
     * @param result 结果
     * @return 返回JSON字符串
     */
    public String isResult(String result) throws MessageException {
        if (result.contains(ERROS)) {
            JsonObject json = new JsonParser().parse(result).getAsJsonObject();
            JsonArray erros = json.getAsJsonArray(ERROS);
            ErrorMesage errorMesage = new Gson().fromJson(erros.get(0), ErrorMesage.class);
            throw new MessageException(errorMesage);
        }
        return result;
    }

    public String params(Map<String, Object> params) {
        StringBuilder sb = new StringBuilder();
        if (params != null && params.size() > 0) {
            Set<Map.Entry<String, Object>> entrySet = params.entrySet();
            sb.append("?");
            try {
                for (Map.Entry<String, Object> entry : entrySet) {
                    Object val = entry.getValue();
                    if (null != val) {
                        sb.append(entry.getKey());
                        sb.append("=");
                        sb.append(URLEncoder.encode(val.toString(), "UTF-8"));
                        sb.append("&");
                    }
                }
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            sb.deleteCharAt(sb.length() - 1);
        }
        System.out.println(sb.toString());
        return sb.toString();
    }

    /**
     * 一般的get请求 对于一般的请求，我们希望给个url，然后取的返回的String。
     *
     * @param url 请求路径
     * @return 返回JSON字符串
     * @throws IOException 异常
     */
    public String get(String url) throws IOException, MessageException {
        return get(url, null);
    }

    /**
     * get请求
     *
     * @param url    请求路径
     * @param params 请求参数
     * @return 返回
     * @throws IOException 异常
     */
    public String get(String url, Map<String, Object> params) throws IOException, MessageException {
        String paramstr = params(params);
        Request request = new Request.Builder().url(url + paramstr).get()
                .addHeader("content-type", "application/json").addHeader("Authorization", "Basic " + getAuthorization())
                .build();
        Call call = okHttpClient.newCall(request);
        return isResult(call.execute().body().string());
    }

    /**
     * 一般的post请求 对于一般的请求，我们希望给个url和封装参数的Map，然后取的返回的String。
     *
     * @param url    请求路径
     * @param params 请求参数
     * @return 返回结果
     * @throws IOException 异常
     * @author dexiang.jiang
     */
    public String post(String url, Map<String, Object> params) throws IOException, MessageException {
        MediaType mediaType = MediaType.parse("application/json");
        String json = new Gson().toJson(params);
        RequestBody body = RequestBody.create(mediaType, json);
        Request request = new Request.Builder().url(url).post(body)
                .addHeader("content-type", "application/json").addHeader("Authorization", "Basic " + authorization)
                .build();
        Call call = okHttpClient.newCall(request);
        return isResult(call.execute().body().string());
    }

    public String getAuthorization() {
        return authorization;
    }

    public void setAuthorization(String auth) {
        authorization = auth;
    }


}
