package com.secspace.lib.common.utils;

import android.annotation.SuppressLint;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.annotation.IntDef;
import android.support.annotation.StringDef;
import android.telephony.TelephonyManager;
import android.util.Log;

import com.secspace.lib.common.net.TimeOutDns;

import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * TelephonyManager#getSimOperator用于获取SIM卡运营商ID，比如移动是46002
 * TelephonyManager#getSimOperatorName方法获取运营商名字，比如移动是CMCC
 * TelephonyManager#getSimCountryIso获取SIM卡国家，比如中国是cn
 * TelephonyManager#getSimState获取SIM卡状态
 * Created by cyw_m on 2018/4/20.
 */
@SuppressLint("MissingPermission")
public class NetUtil {

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({NetworkStatus.NONE, NetworkStatus.WIFI, NetworkStatus.NET_2G, NetworkStatus.NET_3G, NetworkStatus.NET_4G, NetworkStatus.MOBILE})
    public @interface NetworkStatus {
        int NONE = 0; // 没有网络连接
        int WIFI = 1; // wifi连接
        int NET_2G = 2; // 2G
        int NET_3G = 3; // 3G
        int NET_4G = 4; // 4G
        int MOBILE = 5; // 手机流量
    }

    @Retention(RetentionPolicy.SOURCE)
    @StringDef({ApnName.TELECOM, ApnName.UNICOM, ApnName.MOBILE})
    public @interface ApnName {
        String TELECOM = "ctnet";
        String UNICOM = "3gnet";
        String MOBILE = "cmnet";
    }

    private static final String TAG = "NetUtil";


    /**
     * 获取当前网络连接的类型
     *
     * @param context context
     * @return int
     */
    public static int getNetworkStatus(Context context) {
        ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); // 获取网络服务
        if (null == connManager) {
            return NetworkStatus.NONE;
        }
        NetworkInfo activeNetInfo = connManager.getActiveNetworkInfo();
        if (activeNetInfo == null || !activeNetInfo.isAvailable()) {
            return NetworkStatus.NONE;
        }
        //is wifi?
        NetworkInfo wifiInfo = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
        if (null != wifiInfo) {
            NetworkInfo.State state = wifiInfo.getState();
            if (null != state) {
                if (state == NetworkInfo.State.CONNECTED || state == NetworkInfo.State.CONNECTING) {
                    return NetworkStatus.WIFI;
                }
            }
        }
        // is 2G、3G、4G网?
        TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        int networkType = telephonyManager.getNetworkType();
        switch (networkType) {
            // 2G网络
            case TelephonyManager.NETWORK_TYPE_GPRS:
            case TelephonyManager.NETWORK_TYPE_CDMA:
            case TelephonyManager.NETWORK_TYPE_EDGE:
            case TelephonyManager.NETWORK_TYPE_1xRTT:
            case TelephonyManager.NETWORK_TYPE_IDEN:
                return NetworkStatus.NET_2G;
            // 3G网络
            case TelephonyManager.NETWORK_TYPE_EVDO_A:
            case TelephonyManager.NETWORK_TYPE_UMTS:
            case TelephonyManager.NETWORK_TYPE_EVDO_0:
            case TelephonyManager.NETWORK_TYPE_HSDPA:
            case TelephonyManager.NETWORK_TYPE_HSUPA:
            case TelephonyManager.NETWORK_TYPE_HSPA:
            case TelephonyManager.NETWORK_TYPE_EVDO_B:
            case TelephonyManager.NETWORK_TYPE_EHRPD:
            case TelephonyManager.NETWORK_TYPE_HSPAP:
                return NetworkStatus.NET_3G;
            // 4G网络
            case TelephonyManager.NETWORK_TYPE_LTE:
                return NetworkStatus.NET_4G;
            default:
                return NetworkStatus.MOBILE;
        }
    }

    /**
     * 判断网络是否连接
     *
     * @param context context
     * @return true/false
     */
    public static boolean isNetConnected(Context context) {
        ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivity != null) {
            NetworkInfo info = connectivity.getActiveNetworkInfo();
            if (info != null && info.isConnected()) {
                if (info.getState() == NetworkInfo.State.CONNECTED) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 判断MOBILE网络是否连接
     *
     * @param context * @return
     */
    public static boolean isMobileConnected(Context context) {
        ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = manager.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_MOBILE)
            return networkInfo.isAvailable();
        return false;
    }


    /**
     * 判断是否wifi连接
     *
     * @param context context
     * @return true/false
     */
    public static synchronized boolean isWifiConnected(Context context) {
        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivityManager != null) {
            NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
            if (networkInfo != null) {
                int networkInfoType = networkInfo.getType();
                if (networkInfoType == ConnectivityManager.TYPE_WIFI || networkInfoType == ConnectivityManager.TYPE_ETHERNET) {
                    return networkInfo.isConnected();
                }
            }
        }
        return false;
    }


    /**
     * 当数据流量连接时获取APN
     *
     * @return
     */
    public static String getApnWhenDataConnected(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cm == null) {
            return null;
        }
        NetworkInfo info = cm.getActiveNetworkInfo();
        if (info == null) {
            Log.w(TAG, "getApnWhenDataConnected, NetworkInfo is Null! Maybe data not connected!");
            return null;
        }
        String currentApn = info.getExtraInfo();
        Log.i(TAG, "currentApn = " + currentApn);
        return currentApn;
    }

    /**
     * 检查外网是否可用
     *
     * @return
     */
    public static boolean checkInternetAvailable() {
        try {
            String ip = "www.baidu.com";
            Process p = Runtime.getRuntime().exec("ping -c 1 -w 3 " + ip);
            int status = p.waitFor();
            Log.i(TAG, "checkInternetConnected status " + status);
            return status == 0;
        } catch (Exception e) {
            e.printStackTrace();
            Log.i(TAG, "checkInternetAvailable exception...");
        }
        return false;
    }


    private static final String REQUEST_URL = "http://www.baidu.com";
    private static OkHttpClient sClient;
    private static Request sRequset;

    static {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(3000, TimeUnit.MILLISECONDS);
        builder.readTimeout(3000, TimeUnit.MILLISECONDS);
        builder.writeTimeout(3000, TimeUnit.MILLISECONDS);
        builder.retryOnConnectionFailure(false);
        builder.dns(new TimeOutDns(3000, TimeUnit.MILLISECONDS));
        sClient = builder.build();
        sRequset = new Request.Builder()
                .url(REQUEST_URL)
                .get()
                .build();
    }

    public static boolean checkInternetAvailableByOkHttp() {
        try {
            Call call = sClient.newCall(sRequset);
            Response response = call.execute();
            if (response != null) {
                return true;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    public static boolean isMobileDataOn(Context context) {
        try {
            ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            Method getMobileDataEnabledMethod = ConnectivityManager.class.getDeclaredMethod("getMobileDataEnabled");
            getMobileDataEnabledMethod.setAccessible(true);
            return (Boolean) getMobileDataEnabledMethod.invoke(connectivityManager);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
}
