package com.example.vastlib.utils

import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.net.ConnectivityManager
import android.net.Network
import android.os.Build
import android.provider.Settings
import android.telephony.TelephonyManager

object NetworkManager {
    enum class Type {
        NET_NONE, NET_GPRS, NET_WIFI
    }

    val networkAvailable: (context: Context) -> Boolean = {
        val activeNetworkInfo =
            it.getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager
        activeNetworkInfo?.let { net -> net.activeNetworkInfo?.isConnected == true } ?: false
    }

    val sdkNetworkType: (context: Context) -> Int = { context ->
        val type =
            (context.getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager)?.run {
                if (activeNetworkInfo == null) Type.NET_NONE else {
                    if (isMetered.invoke(context)) Type.NET_GPRS else Type.NET_WIFI
                }
            } ?: Type.NET_NONE
        type.ordinal
    }

    val isMetered: (context: Context) -> Boolean = { context ->
        connectivityManager.invoke(context)?.isActiveNetworkMetered ?: true
    }

    private val connectivityManager: (context: Context) -> ConnectivityManager? = { context ->
        (context.getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager)
    }

    val airModeOn: (context: Context) -> Boolean = { context ->
        Settings.Global.getInt(
            context.contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0
        ) == 1
    }

    val hasSimCard: (context: Context) -> Boolean = { context ->
        (context.getSystemService(Context.TELEPHONY_SERVICE) as? TelephonyManager)?.run {
            when (simState) {
                TelephonyManager.SIM_STATE_ABSENT, TelephonyManager.SIM_STATE_UNKNOWN -> false
                else -> true
            }
        } ?: true
    }

    val repairNetwork: (context: Context) -> Unit = { context ->
        connectivityManager(context)?.runCatching {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                boundNetworkForProcess?.let { this.bindProcessToNetwork(null) }
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                ConnectivityManager.getProcessDefaultNetwork()?.run {
                    ConnectivityManager.setProcessDefaultNetwork(null)
                }
            } else {

            }
        }
    }

    val bindProcessToNetwork: (conManager: ConnectivityManager, network: Network) -> Boolean =
        { conManager, network ->
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                conManager.bindProcessToNetwork(network)
            } else {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    ConnectivityManager.setProcessDefaultNetwork(network)
                } else {
                    false
                }
            }
        }

    val haveChangeNetworkPermission: (context: Context) -> Boolean = { context ->
        context.packageManager.checkPermission(
            Manifest.permission.CHANGE_NETWORK_STATE,
            context.packageName
        ) != PackageManager.PERMISSION_DENIED
    }
}