package com.develop.food.base.manager.wifi;

import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkRequest;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.text.TextUtils;

import com.develop.food.base.utils.ThreadUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @author Eurigo
 * Created on 2021/7/28 17:48
 * desc   : WIFI及热点状态
 */
public class WifiReceiver extends BroadcastReceiver {

    private static final int WIFI_AP_STATE_DISABLING = 10;
    private static final int WIFI_AP_STATE_DISABLED = 11;
    private static final int WIFI_AP_STATE_ENABLING = 12;
    private static final int WIFI_AP_STATE_ENABLED = 13;
    private static final int WIFI_AP_STATE_FAILED = 14;

    private WifiStateListener wifiStateListener;
    private final WifiManager wifiManager;
    private ConnectivityManager connectivityManager;
    private NetworkInfo lastNetworkInfo;
    private WifiInfo lastWifiInfo;
    private WifiConfiguration lastWifiConfiguration;
    private List<AccessPoint> lastAccessPoints = new CopyOnWriteArrayList<>();
    private Network currentNetwork;

    public WifiStateListener getWifiStateListener() {
        return wifiStateListener;
    }

    public Context context;

    @SuppressLint("MissingPermission")
    public WifiReceiver(Context context, WifiManager wifiManager, ConnectivityManager connectivityManager) {
        this.context = context;
        this.wifiManager = wifiManager;
        this.connectivityManager = connectivityManager;
        lastNetworkInfo = getActiveNetworkInfo();
        lastWifiInfo = wifiManager.getConnectionInfo();
        NetworkRequest.Builder request = new NetworkRequest.Builder()
                .addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
        connectivityManager.registerNetworkCallback(request.build(), callback);
    }

    public void setWifiStateListener(WifiStateListener wifiStateListener) {
        this.wifiStateListener = wifiStateListener;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (action != null &&
                action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
            switch (intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN)) {
                case WifiManager.WIFI_STATE_DISABLED:
                    setWifiState(false);
                    break;
                case WifiManager.WIFI_STATE_ENABLED:
                    setWifiState(true);
                    break;
                case WifiManager.WIFI_STATE_DISABLING:
                case WifiManager.WIFI_STATE_ENABLING:
                case WifiManager.WIFI_STATE_UNKNOWN:
                default:
                    break;

            }
        }
        if (action != null) {
            switch (action) {
                case ConnectivityManager.CONNECTIVITY_ACTION:
                case WifiManager.SCAN_RESULTS_AVAILABLE_ACTION:
                case "android.net.wifi.CONFIGURED_NETWORKS_CHANGE":
                case "android.net.wifi.LINK_CONFIGURATION_CHANGED":
                    updateAccessPoints();
                    break;
                case WifiManager.NETWORK_STATE_CHANGED_ACTION:
                    updateAccessPoints();
                    NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
                    updateNetworkInfo(info);
                    break;
                case WifiManager.SUPPLICANT_STATE_CHANGED_ACTION:
                    int error = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -1);
                    if (error == WifiManager.ERROR_AUTHENTICATING) {
                        handlePasswordError();
                    }
                    break;
            }
        }

        if (intent.getAction() != null &&
                "android.net.wifi.WIFI_AP_STATE_CHANGED".equals(intent.getAction())) {
            //热点的状态为：10---正在关闭；11---已关闭；12---正在开启；13---已开启
            int state = intent.getIntExtra("wifi_state", 0);
            switch (state) {
                // 热点状态：已关闭
                case WIFI_AP_STATE_DISABLED:
                    setHotpotState(false);
                    break;
                // 热点状态：已开启
                case WIFI_AP_STATE_ENABLED:
                    setHotpotState(true);
                    break;
                // 打开热点异常
                case WIFI_AP_STATE_FAILED:
                    if (wifiStateListener != null) {
                        wifiStateListener.onHotpotOpenError();
                    }
                    break;
                default:
                    break;
            }
        }
    }

    public interface WifiStateListener {
        /**
         * WiFi打开
         */
        void onWifiOpen();

        /**
         * WiFi关闭
         */
        void onWifiClose();

        /**
         * 热点打开
         */
        void onHotpotOpen();

        /**
         * 热点打开异常
         */
        void onHotpotOpenError();

        /**
         * 热点关闭
         */
        void onHotpotClose();

        void updateAccessPoints(List<AccessPoint> accessPoints);
    }

    private ConnectivityManager.NetworkCallback callback = new ConnectivityManager.NetworkCallback() {

        @Override
        public void onAvailable(Network network) {
            super.onAvailable(network);
            currentNetwork = network;
        }

        @Override
        public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
            super.onCapabilitiesChanged(network, networkCapabilities);
            if (network.equals(currentNetwork)) {
                updateNetworkInfo(null);
            }
        }
    };

    @SuppressLint("MissingPermission")
    private void updateAccessPoints() {
        List<AccessPoint> accessPoints = new ArrayList<>();
        List<ScanResult> scanResults = wifiManager.getScanResults();
        if (lastWifiInfo != null && lastWifiInfo.getNetworkId() != AccessPoint.INVALID_NETWORK_ID) {
            lastWifiConfiguration = getWifiConfigurationForNetworkId(lastWifiInfo.getNetworkId());
        }
        if (scanResults != null) {
            for (ScanResult scanResult : scanResults) {
                if (TextUtils.isEmpty(scanResult.SSID)) {
                    continue;
                }
                AccessPoint accessPoint = new AccessPoint(context, scanResult);
                if (accessPoints.contains(accessPoint)) {
                    continue;
                }
                List<WifiConfiguration> wifiConfigurations = wifiManager.getConfiguredNetworks();
                if (wifiConfigurations != null) {
                    for (WifiConfiguration config : wifiConfigurations) {
                        if (accessPoint.getQuotedSSID().equals(config.SSID)) {
                            accessPoint.setWifiConfiguration(config);
                        }
                    }
                }
                if (lastWifiInfo != null && lastNetworkInfo != null) {
                    accessPoint.update(lastWifiConfiguration, lastWifiInfo, lastNetworkInfo);
                }
                accessPoints.add(accessPoint);
            }
        }
        Collections.sort(accessPoints);
        lastAccessPoints = accessPoints;
        if (wifiStateListener != null) {
            ThreadUtils.INSTANCE.runOnMainThread(() -> wifiStateListener.updateAccessPoints(accessPoints));
        }
    }

    private void updateNetworkInfo(NetworkInfo networkInfo) {
        if (networkInfo != null) {
            lastNetworkInfo = networkInfo;
        }
        lastWifiInfo = wifiManager.getConnectionInfo();
        if (lastWifiInfo != null && lastWifiInfo.getNetworkId() != AccessPoint.INVALID_NETWORK_ID) {
            lastWifiConfiguration = getWifiConfigurationForNetworkId(lastWifiInfo.getNetworkId());
        }
        boolean reorder = false;
        for (AccessPoint accessPoint : lastAccessPoints) {
            if (accessPoint.update(lastWifiConfiguration, lastWifiInfo, lastNetworkInfo)) {
                reorder = true;
            }
        }
        if (reorder) {
            Collections.sort(lastAccessPoints);
        }
        if (wifiStateListener != null) {
            ThreadUtils.INSTANCE.runOnMainThread(() -> wifiStateListener.updateAccessPoints(lastAccessPoints));

        }
    }

    /**
     * 根据 NetworkId 获取 WifiConfiguration 信息
     *
     * @param networkId 需要获取 WifiConfiguration 信息的 networkId
     * @return 指定 networkId 的 WifiConfiguration 信息
     */
    @SuppressLint("MissingPermission")
    private WifiConfiguration getWifiConfigurationForNetworkId(int networkId) {
        final List<WifiConfiguration> configs = wifiManager.getConfiguredNetworks();
        if (configs != null) {
            for (WifiConfiguration config : configs) {
                if (lastWifiInfo != null && networkId == config.networkId) {
                    return config;
                }
            }
        }
        return null;
    }

    /**
     * 获取当前网络信息
     */
    @SuppressLint("MissingPermission")
    public NetworkInfo getActiveNetworkInfo() {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cm != null) {
            return cm.getActiveNetworkInfo();
        }
        return null;
    }

    private void handlePasswordError() {
        if (lastWifiConfiguration != null) {
            AccessPoint accessPoint = new AccessPoint(lastWifiConfiguration);
            accessPoint.setPasswordError(true);
        }
    }

    private void setWifiState(boolean state) {
        if (wifiStateListener != null) {
            if (state) {
                wifiStateListener.onWifiOpen();
            } else {
                wifiStateListener.onWifiClose();
            }
        }
    }

    private void setHotpotState(boolean state) {
        if (wifiStateListener != null) {
            if (state) {
                wifiStateListener.onHotpotOpen();
            } else {
                wifiStateListener.onHotpotClose();
            }
        }
    }

    public void unregisterNetworkCallback() {
        if (connectivityManager != null) {
            connectivityManager.unregisterNetworkCallback(callback);
        }
    }
}
