package com.tenlionsoft.baselib.core.network;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Handler;

import com.tenlionsoft.baselib.core.network.body.ProgressRequestBody;
import com.tenlionsoft.baselib.core.network.body.ResponseProgressBody;
import com.tenlionsoft.baselib.core.network.callback.DownloadCallback;
import com.tenlionsoft.baselib.core.network.callback.RequestCallBack;
import com.tenlionsoft.baselib.core.network.response.DownloadResponseHandler;
import com.tenlionsoft.baselib.core.network.response.ResponseHandler;

import org.json.JSONObject;

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

import okhttp3.Call;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * Created by Xuer on 2017/3/8.
 */
public class HttpUtils {
    private OkHttpClient client;
    private static HttpUtils instance;
    private String TAG = "HttpUtils";

    private HttpUtils() {
//        client = new OkHttpClient();

        client = new OkHttpClient.Builder()
                .connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(40, TimeUnit.SECONDS)
                .build();

//        OkHttpClient.Builder builder= new OkHttpClient.Builder();
//        client=builder.build();

    }

    /*
     * 用来创建
     */
    private static synchronized void syncInit() {
        if (instance == null) {
            instance = new HttpUtils();
        }
    }

    /**
     * 用来得到单例
     *
     * @return
     */
    public static HttpUtils getInstance() {
        if (instance == null) {
            syncInit();
        }
        return instance;
    }

    /**
     * get 请求
     *
     * @param url             url
     * @param params          参数
     * @param responseHandler 回调
     */
    public void get(final String url, final Map<String, String> params, final ResponseHandler responseHandler) {
        get(null, url, params, responseHandler);
    }

    /**
     * get 请求
     *
     * @param context         发起请求的context
     * @param url             url
     * @param params          参数
     * @param responseHandler 回调
     */
    public void get(Context context, final String url, final Map<String, String> params, final ResponseHandler responseHandler) {
        //拼接url
        String get_url = url;
        if (params != null && params.size() > 0) {
            int i = 0;
            for (Map.Entry<String, String> entry : params.entrySet()) {
                if (i++ == 0) {
                    get_url = get_url + "?" + entry.getKey() + "=" + entry.getValue();
                } else {
                    get_url = get_url + "&" + entry.getKey() + "=" + entry.getValue();
                }
            }
        }
        Request request;


        //发起request
        if (context == null) {
            request = new Request.Builder()
                    .url(url)
                    .build();
        } else {
            request = new Request.Builder()
                    .url(url)
                    .tag(context)
                    .build();
        }
        client.newCall(request).enqueue(new RequestCallBack(responseHandler));
    }

    /**
     * post 请求
     *
     * @param url             url
     * @param params          参数
     * @param responseHandler 回调
     */
    public void post(final String url, final Map<String, String> params, final ResponseHandler responseHandler) {

        post(null, url, params, responseHandler);
    }
    //json类型post请求
    public void postJson(Context context, final String url, final Map<String, String> params, final ResponseHandler responseHandler) {
        MediaType JSON = MediaType.parse("application/json; charset=utf-8");
        RequestBody requestBody=RequestBody.create(JSON,new JSONObject(params).toString());
        Request request;
        //发起request
        if (context == null) {
            request = new Request.Builder()
                    .url(url)
                    .post(requestBody)
                    .build();
        } else {
            request = new Request.Builder()
                    .url(url)
                    .post(requestBody)
                    .tag(context)
                    .build();
        }
        client.newCall(request).enqueue(new RequestCallBack(responseHandler));
    }



    /**
     * post 请求
     *
     * @param context         发起请求的context
     * @param url             url
     * @param params          参数
     * @param responseHandler 回调
     */
    public void post(Context context, final String url, final Map<String, String> params, final ResponseHandler responseHandler) {
        getSystemInfo(context,params);
        //post builder 参数
        FormBody.Builder builder = new FormBody.Builder();
        if (params != null && params.size() > 0) {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                builder.add(entry.getKey(), entry.getValue());
            }
        }

        Request request;

        //发起request
        if (context == null) {
            request = new Request.Builder()
                    .url(url)
                    .post(builder.build())
                    .build();
        } else {
            request = new Request.Builder()
                    .url(url)
                    .post(builder.build())
                    .tag(context)
                    .build();
        }

        client.newCall(request).enqueue(new RequestCallBack(responseHandler));

    }
    //获取手机基本信息
    private void getSystemInfo(Context context,Map<String,String> params){
        PackageManager packageManager = null;
        ApplicationInfo applicationInfo = null;
        PackageInfo packageInfo = null;
        try {
            packageManager = context.getApplicationContext().getPackageManager();
            applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0);
            packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
        } catch (PackageManager.NameNotFoundException e) {
            applicationInfo = null;
        }
        String applicationName = (String) packageManager.getApplicationLabel(applicationInfo);
//        params.put("strName", BluetoothAdapter.getDefaultAdapter().getName()==null?"":BluetoothAdapter.getDefaultAdapter().getName());//手机系统版名称
        params.put("strSysName", "Android");//手机系统版名称
//        params.put("strSysVersion", android.os.Build.VERSION.RELEASE==null?"":android.os.Build.VERSION.RELEASE);//手机系统版本号
//        params.put("phoneModel", android.os.Build.MODEL==null?"":android.os.Build.MODEL);//手机型号
        params.put("strAppName", applicationName==null?"":applicationName);//应用名称
        params.put("strAppVersion", packageInfo.versionName==null?"":applicationName);//应用版本名称
        params.put("strAppBuild", packageInfo.versionCode + "");//应用版本号
//        params.put("identifierNumber", );//手机序列号
    }
    /**
     * post 请求
     *
     * @param context 发起请求的context
     * @param url     url
     * @param params  参数
     */
    public Response postExecute(Context context, final String url, final Map<String, String> params) throws IOException {

        getSystemInfo(context,params);
        //post builder 参数
        FormBody.Builder builder = new FormBody.Builder();
        if (params != null && params.size() > 0) {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                builder.add(entry.getKey(), entry.getValue());
            }
        }

        Request request;

        //发起request
        if (context == null) {
            request = new Request.Builder()
                    .url(url)
                    .post(builder.build())
                    .build();
        } else {
            request = new Request.Builder()
                    .url(url)
                    .post(builder.build())
                    .tag(context)
                    .build();
        }
        Response response = client.newCall(request).execute();
        return response;
    }

    /**
     * 上传文件
     *
     * @param url             url
     * @param files           上传的文件files
     * @param responseHandler 回调
     */
//    public void upload(String url, Map<String, File> files, final ResponseHandler responseHandler) {
//        upload(null, url, null, files, responseHandler);
//    }

    /**
     * 上传文件
     *
     * @param url             url
     * @param params          参数
     * @param files           上传的文件files
     * @param responseHandler 回调
     */
    public void upload(String url, Map<String, String> params, Map<String, File> files, final ResponseHandler responseHandler) {
        upload(null, url, params, files, responseHandler);
    }

    /**
     * 上传文件
     *
     * @param context         发起请求的context
     * @param url             url
     * @param files           上传的文件files
     * @param responseHandler 回调
     */
    public void upload(Context context, String url, Map<String, File> files, final ResponseHandler responseHandler) {
        upload(context, url, null, files, responseHandler);
    }

    /**
     * 上传文件
     *
     * @param context         发起请求的context
     * @param url             url
     * @param params          参数
     * @param files           上传的文件files
     * @param responseHandler 回调
     */
    public void upload(Context context, String url, Map<String, String> params, Map<String, File> files, final ResponseHandler responseHandler) {
        if (params == null) {
            params = new HashMap<>();
        }
        getSystemInfo(context,params);


        MultipartBody.Builder multipartBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM);

        //添加参数
        if (params != null && !params.isEmpty()) {
            for (String key : params.keySet()) {
                multipartBuilder.addPart(Headers.of("Content-Disposition", "form-data; name=\"" + key + "\""),
                        RequestBody.create(null, params.get(key)));
            }
        }

        //添加上传文件
        if (files != null && !files.isEmpty()) {
            RequestBody fileBody;
            for (String key : files.keySet()) {
                File file = files.get(key);
                String fileName = file.getName();
                fileBody = RequestBody.create(MediaType.parse(guessMimeType(fileName)), file);
                multipartBuilder.addPart(Headers.of("Content-Disposition",
                        "form-data; name=\"" + key + "\"; filename=\"" + fileName + "\""),
                        fileBody);
            }
        }

        Request request;
        if (context == null) {
            request = new Request.Builder()
                    .url(url)
                    .post(new ProgressRequestBody(multipartBuilder.build(), responseHandler))
                    .build();
        } else {
            request = new Request.Builder()
                    .url(url)
                    .post(new ProgressRequestBody(multipartBuilder.build(), responseHandler))
                    .tag(context)
                    .build();
        }

        client.newCall(request).enqueue(new RequestCallBack(responseHandler));
    }

    /**
     * 下载文件
     *
     * @param url                     下载地址
     * @param filedir                 下载目的目录
     * @param filename                下载目的文件名
     * @param downloadResponseHandler 下载回调
     */
    public void download(String url, String filedir, String filename, final DownloadResponseHandler downloadResponseHandler) {
        download(null, url, filedir, filename, downloadResponseHandler);
    }

    /**
     * 下载文件
     *
     * @param context                 发起请求的context
     * @param url                     下载地址
     * @param filedir                 下载目的目录
     * @param filename                下载目的文件名
     * @param downloadResponseHandler 下载回调
     */
    public void download(Context context, String url, String filedir, String filename, final DownloadResponseHandler downloadResponseHandler) {

        Request request;
        if (context == null) {
            request = new Request.Builder()
                    .url(url)
                    .build();
        } else {
            request = new Request.Builder()
                    .url(url)
                    .tag(context)
                    .build();
        }

        client.newBuilder()
                .addNetworkInterceptor(new Interceptor() {      //设置拦截器
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        Response originalResponse = chain.proceed(chain.request());
                        return originalResponse.newBuilder()
                                .body(new ResponseProgressBody(originalResponse.body(), downloadResponseHandler))
                                .build();
                    }
                })
                .build()
                .newCall(request)
                .enqueue(new DownloadCallback(new Handler(), downloadResponseHandler, filedir, filename));
    }

    /**
     * 取消当前context的所有请求
     *
     * @param context
     */
    public void cancel(Context context) {
        if (client != null) {
            for (Call call : client.dispatcher().queuedCalls()) {
                if (call.request().tag().equals(context))
                    call.cancel();
            }
            for (Call call : client.dispatcher().runningCalls()) {
                if (call.request().tag().equals(context))
                    call.cancel();
            }
        }
    }

    /**
     * 取消当前所有的所有请求
     */
    public void cancel() {

        for (Call call : client.dispatcher().queuedCalls()) {

            call.cancel();
        }
        for (Call call : client.dispatcher().runningCalls()) {

            call.cancel();

        }
    }

    //获取mime type
    private String guessMimeType(String path) {
        FileNameMap fileNameMap = URLConnection.getFileNameMap();
        String contentTypeFor = fileNameMap.getContentTypeFor(path);
        if (contentTypeFor == null) {
            contentTypeFor = "application/octet-stream";
        }
        return contentTypeFor;
    }
}
