package com.convenient.android.common.utils.net

import android.content.Context
import android.location.LocationManager
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Build
import android.telephony.TelephonyManager

/**
 *    @author : hubowen
 *    @date   : 2021/2/20  4:21 PM
 *    @description：网络工具类
 */
class NetUtil {

    enum class NetType {
        WIFI, CM_NET, CM_WAP, NONE_NET
    }

    init {
        /* cannot be instantiated */
        throw UnsupportedOperationException("cannot be instantiated")
    }

    companion object {
        /* 网络状态 */
        const val NETWORK_TYPE_UNKNOWN = 0
        const val NETWORK_TYPE_2G = 1
        const val NETWORK_TYPE_3G = 2
        const val NETWORK_TYPE_4G = 5
        const val NETWORK_TYPE_WIFI = 3
        const val NETWORK_TYPE_NONE = 4

        /**
         * @author lin
         * @param context
         * @return 返回5种网络类型，0-->未知网络，1-->2G网络，2-->3G网络，3-->wifi网络，4-->无网络
         * 注意：只有wifi类型的判断是准确的，其他类型相对都有适配问题
         */
        fun getNetworkState(context: Context?): Int {
            if (context == null) {
                return NETWORK_TYPE_UNKNOWN
            }
            var networkType = NETWORK_TYPE_NONE
            try {
                val cm = context.applicationContext
                    .getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
                val info = cm.activeNetworkInfo
                if (info != null && info.isConnected) {
                    val type = info.type
                    if (type == ConnectivityManager.TYPE_WIFI) {
                        networkType = if (isWiFiActive(context)) {
                            NETWORK_TYPE_WIFI
                        } else {
                            NETWORK_TYPE_NONE
                        }
                    } else {
                        val subType = info.subtype
                        when {
                            isMobile2G(subType) -> NETWORK_TYPE_2G
                            isMobile3G(subType) -> NETWORK_TYPE_3G
                            isMobile4G(subType) -> NETWORK_TYPE_4G
                        }
                    }
                } else {
                    networkType = NETWORK_TYPE_NONE
                }
            } catch (ignored: Exception) {
                networkType = NETWORK_TYPE_UNKNOWN
            }
            return networkType
        }


        /**
         * 判断Wifi是否可用
         *
         * @author yang (10.17修改)
         * @since 10.17
         * @return true:可用 false:不可用
         */
        @Deprecated("""由于有USB连接导致判断不准 最好不用这个方法""")
        fun isWiFiActive(context: Context?): Boolean {
            var bReturn = false
            try {
                if (context == null) {
                    return false
                }
                val cm = context.applicationContext
                    .getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
                val info = cm.activeNetworkInfo
                if (null != info && info.isConnected) {
                    val type = info.type
                    if (type == ConnectivityManager.TYPE_WIFI) {
                        bReturn = true
                    }
                }
            } catch (ignored: Exception) {
            }
            return bReturn
        }

        /**
         * 判断是否2G网络
         *
         * @param type
         * @return
         */
        private fun isMobile2G(type: Int): Boolean {
            var is2G = false
            is2G = when (type) {
                TelephonyManager.NETWORK_TYPE_GPRS,
                TelephonyManager.NETWORK_TYPE_EDGE,
                TelephonyManager.NETWORK_TYPE_CDMA,
                TelephonyManager.NETWORK_TYPE_1xRTT,
                TelephonyManager.NETWORK_TYPE_IDEN -> true
                else -> false
            }
            return is2G
        }

        /**
         * 判断是否是3G网络
         *
         * @param type
         * @return
         */
        private fun isMobile3G(type: Int): Boolean {
            return when (type) {
                TelephonyManager.NETWORK_TYPE_UMTS,
                TelephonyManager.NETWORK_TYPE_EVDO_0,
                TelephonyManager.NETWORK_TYPE_EVDO_A,
                TelephonyManager.NETWORK_TYPE_HSDPA,
                TelephonyManager.NETWORK_TYPE_HSUPA,
                TelephonyManager.NETWORK_TYPE_HSPA,
                TelephonyManager.NETWORK_TYPE_EVDO_B,
                TelephonyManager.NETWORK_TYPE_EHRPD,
                TelephonyManager.NETWORK_TYPE_HSPAP -> true
                else -> false
            }
        }

        /**
         * 判断是否是4G网络
         *
         * @param type
         * @return
         */
        private fun isMobile4G(type: Int): Boolean {
            return when (type) {
                TelephonyManager.NETWORK_TYPE_LTE -> true
                else -> false
            }
        }

        /**
         * @方法说明:判断是否是手机网络
         * @方法名称:is3GNet
         * @param context
         * @return 返回值：boolean
         */
        fun is3GNet(context: Context): Boolean {
            val connectivityManager = context.applicationContext
                .getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            val activeNetInfo = connectivityManager.activeNetworkInfo
            return (activeNetInfo != null
                    && activeNetInfo.type == ConnectivityManager.TYPE_MOBILE)
        }

        /**
         * @方法说明:判断WIFI网络是否可用
         * @方法名称:isWifiConnected
         * @param context
         * @return
         * @返回值:boolean
         */
        fun isWifiConnected(context: Context?): Boolean {
            if (context != null) {
                val mConnectivityManager = context.applicationContext
                    .getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
                val mWiFiNetworkInfo = mConnectivityManager
                    .getNetworkInfo(ConnectivityManager.TYPE_WIFI)
                if (mWiFiNetworkInfo != null) {
                    return mWiFiNetworkInfo.isAvailable
                }
            }
            return false
        }

        /**
         * @方法说明:判断Gps是否可用
         * @方法名称:isGpsEnable
         * @param context
         * @return
         * @返回值:boolean
         */
        fun isGpsEnable(context: Context?): Boolean {
            return if (context != null) {
                val locationManager = context.applicationContext
                    .getSystemService(Context.LOCATION_SERVICE) as LocationManager
                locationManager
                    .isProviderEnabled(LocationManager.GPS_PROVIDER)
            } else {
                false
            }
        }

        /**
         * @param context
         * @return
         * @返回值:boolean
         */
        fun isMobileConnected(context: Context?): Boolean {
            if (context != null) {
                val mConnectivityManager = context.applicationContext
                    .getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
                val mMobileNetworkInfo = mConnectivityManager
                    .getNetworkInfo(ConnectivityManager.TYPE_MOBILE)
                if (mMobileNetworkInfo != null) {
                    return mMobileNetworkInfo.isAvailable
                }
            }
            return false
        }

        /**
         * @方法说明:获取当前网络连接的类型信息
         * @方法名称:getConnectedType
         * @param context
         * @return
         * @返回值:int
         */
        fun getConnectedType(context: Context?): Int {
            if (context != null) {
                val mConnectivityManager = context.applicationContext
                    .getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
                val mNetworkInfo = mConnectivityManager
                    .activeNetworkInfo
                if (mNetworkInfo != null && mNetworkInfo.isAvailable) {
                    return mNetworkInfo.type
                }
            }
            return -1
        }

        /**
         * @方法说明:获取当前的网络状态 -1：没有网络 1：WIFI网络2：wap 网络3：net网络
         * @方法名称:getAPNType
         * @param context
         * @return
         * @返回值:netType
         */
        fun getAPNType(context: Context): NetType {
            val connMgr = context.applicationContext
                .getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            val networkInfo = connMgr.activeNetworkInfo ?: return NetType.NONE_NET
            val nType = networkInfo.type
            if (nType == ConnectivityManager.TYPE_MOBILE) {
                return if ("cmnet" == networkInfo.extraInfo.toLowerCase()) {
                    NetType.CM_NET
                } else {
                    NetType.CM_WAP
                }
            } else if (nType == ConnectivityManager.TYPE_WIFI) {
                return NetType.WIFI
            }
            return NetType.NONE_NET
        }

        /**
         * @方法说明:判断是否有网络连接
         * @方法名称:isNetworkConnected
         * @param context
         * @return 返回值：boolean
         */
        fun isNetworkConnected(context: Context?): Boolean {
            if (context != null) {
                val mConnectivityManager = context.applicationContext
                    .getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
                val mNetworkInfo = mConnectivityManager
                    .activeNetworkInfo
                if (mNetworkInfo != null) {
                    return mNetworkInfo.isConnected
                }
            }
            return false
        }

        /**
         * @方法说明:网络是否可用
         * @方法名称:isNetworkAvailable
         * @param context
         * @return
         * @返回值:boolean
         */
        fun isNetworkAvailable(context: Context?): Boolean {
            if (context == null) return false
            val connectivityManager = context.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                val networkCapabilities = connectivityManager.activeNetwork ?: return false
                val actNw = connectivityManager.getNetworkCapabilities(networkCapabilities) ?: return false
                when {
                    actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
                            actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
                            actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
                    else -> false
                }
            } else {
                connectivityManager.run {
                    activeNetworkInfo?.run {
                        when (type) {
                            ConnectivityManager.TYPE_WIFI,
                            ConnectivityManager.TYPE_MOBILE,
                            ConnectivityManager.TYPE_ETHERNET -> true
                            else -> false
                        }
                    } ?: false
                }
            }
        }


    }
}