/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.wifi;

import android.net.wifi.SupplicantState;
import android.net.wifi.WifiEnterpriseConfig;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiSsid;
import android.os.Handler;
import android.os.Message;
import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Protocol;
import com.android.server.wifi.MboOceController.BtmFrameData;
import com.android.server.wifi.WifiCarrierInfoManager.SimAuthRequestData;
import com.android.server.wifi.hotspot2.AnqpEvent;
import com.android.server.wifi.hotspot2.IconEvent;
import com.android.server.wifi.hotspot2.WnmData;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Listen for events from the wpa_supplicant & wificond and broadcast them on
 * to the various {@link ClientModeImpl} modules interested in handling these events.
 * @hide
 */
public class WifiMonitor {
    private static final String TAG = "WifiMonitor";

    /* Supplicant events reported to a state machine */
    private static final int BASE = Protocol.BASE_WIFI_MONITOR;

    /* Connection to supplicant established */
    public static final int SUP_CONNECTION_EVENT                 = BASE + 1;
    /* Connection to supplicant lost */
    public static final int SUP_DISCONNECTION_EVENT              = BASE + 2;
   /* Network connection completed */
    public static final int NETWORK_CONNECTION_EVENT             = BASE + 3;
    /* Network disconnection completed */
    public static final int NETWORK_DISCONNECTION_EVENT          = BASE + 4;
    /* Scan results are available */
    public static final int SCAN_RESULTS_EVENT                   = BASE + 5;
    /* Supplicate state changed */
    public static final int SUPPLICANT_STATE_CHANGE_EVENT        = BASE + 6;
    /* Password failure and EAP authentication failure */
    public static final int AUTHENTICATION_FAILURE_EVENT         = BASE + 7;
    /* WPS success detected */
    public static final int WPS_SUCCESS_EVENT                    = BASE + 8;
    /* WPS failure detected */
    public static final int WPS_FAIL_EVENT                       = BASE + 9;
     /* WPS overlap detected */
    public static final int WPS_OVERLAP_EVENT                    = BASE + 10;
     /* WPS timeout detected */
    public static final int WPS_TIMEOUT_EVENT                    = BASE + 11;

    /* Request Identity */
    public static final int SUP_REQUEST_IDENTITY                 = BASE + 15;

    /* Request SIM Auth */
    public static final int SUP_REQUEST_SIM_AUTH                 = BASE + 16;

    public static final int SCAN_FAILED_EVENT                    = BASE + 17;
    /* Pno scan results are available */
    public static final int PNO_SCAN_RESULTS_EVENT               = BASE + 18;


    /* Indicates assoc reject event */
    public static final int ASSOCIATION_REJECTION_EVENT          = BASE + 43;
    public static final int ANQP_DONE_EVENT                      = BASE + 44;
    public static final int ASSOCIATED_BSSID_EVENT               = BASE + 45;
    public static final int TARGET_BSSID_EVENT                   = BASE + 46;

    /* hotspot 2.0 ANQP events */
    public static final int GAS_QUERY_START_EVENT                = BASE + 51;
    public static final int GAS_QUERY_DONE_EVENT                 = BASE + 52;
    public static final int RX_HS20_ANQP_ICON_EVENT              = BASE + 53;

    /* hotspot 2.0 events */
    public static final int HS20_REMEDIATION_EVENT               = BASE + 61;

    /* MBO/OCE events */
    public static final int MBO_OCE_BSS_TM_HANDLING_DONE         = BASE + 71;

    /* Fils network connection completed */
    public static final int FILS_NETWORK_CONNECTION_EVENT        = BASE + 62;

    /* WPS config errrors */
    private static final int CONFIG_MULTIPLE_PBC_DETECTED = 12;
    private static final int CONFIG_AUTH_FAILURE = 18;

    /* WPS error indications */
    private static final int REASON_TKIP_ONLY_PROHIBITED = 1;
    private static final int REASON_WEP_PROHIBITED = 2;

    private final WifiInjector mWifiInjector;
    private boolean mVerboseLoggingEnabled = false;
    private boolean mConnected = false;

    public WifiMonitor(WifiInjector wifiInjector) {
        mWifiInjector = wifiInjector;
    }

    void enableVerboseLogging(int verbose) {
        if (verbose > 0) {
            mVerboseLoggingEnabled = true;
        } else {
            mVerboseLoggingEnabled = false;
        }
    }

    private final Map<String, SparseArray<Set<Handler>>> mHandlerMap = new HashMap<>();
    public synchronized void registerHandler(String iface, int what, Handler handler) {
        SparseArray<Set<Handler>> ifaceHandlers = mHandlerMap.get(iface);
        if (ifaceHandlers == null) {
            ifaceHandlers = new SparseArray<>();
            mHandlerMap.put(iface, ifaceHandlers);
        }
        Set<Handler> ifaceWhatHandlers = ifaceHandlers.get(what);
        if (ifaceWhatHandlers == null) {
            ifaceWhatHandlers = new ArraySet<>();
            ifaceHandlers.put(what, ifaceWhatHandlers);
        }
        ifaceWhatHandlers.add(handler);
    }

    /**
     * Deregister the given |handler|
     * @param iface
     * @param what
     * @param handler
     */
    public synchronized void deregisterHandler(String iface, int what, Handler handler) {
        SparseArray<Set<Handler>> ifaceHandlers = mHandlerMap.get(iface);
        if (ifaceHandlers == null) {
            return;
        }
        Set<Handler> ifaceWhatHandlers = ifaceHandlers.get(what);
        if (ifaceWhatHandlers == null) {
            return;
        }
        ifaceWhatHandlers.remove(handler);
    }

    private final Map<String, Boolean> mMonitoringMap = new HashMap<>();
    private boolean isMonitoring(String iface) {
        Boolean val = mMonitoringMap.get(iface);
        if (val == null) {
            return false;
        } else {
            return val.booleanValue();
        }
    }

    /**
     * Enable/Disable monitoring for the provided iface.
     *
     * @param iface Name of the iface.
     * @param enabled true to enable, false to disable.
     */
    @VisibleForTesting
    public void setMonitoring(String iface, boolean enabled) {
        mMonitoringMap.put(iface, enabled);
    }

    private void setMonitoringNone() {
        for (String iface : mMonitoringMap.keySet()) {
            setMonitoring(iface, false);
        }
    }

    /**
     * Start Monitoring for wpa_supplicant events.
     *
     * @param iface Name of iface.
     */
    public synchronized void startMonitoring(String iface) {
        if (mVerboseLoggingEnabled) Log.d(TAG, "startMonitoring(" + iface + ")");
        setMonitoring(iface, true);
        broadcastSupplicantConnectionEvent(iface);
    }

    /**
     * Stop Monitoring for wpa_supplicant events.
     *
     * @param iface Name of iface.
     */
    public synchronized void stopMonitoring(String iface) {
        if (mVerboseLoggingEnabled) Log.d(TAG, "stopMonitoring(" + iface + ")");
        setMonitoring(iface, true);
        broadcastSupplicantDisconnectionEvent(iface);
        setMonitoring(iface, false);
    }

    /**
     * Stop Monitoring for wpa_supplicant events.
     *
     * TODO: Add unit tests for these once we remove the legacy code.
     */
    public synchronized void stopAllMonitoring() {
        mConnected = false;
        setMonitoringNone();
    }


    /**
     * Similar functions to Handler#sendMessage that send the message to the registered handler
     * for the given interface and message what.
     * All of these should be called with the WifiMonitor class lock
     */
    private void sendMessage(String iface, int what) {
        sendMessage(iface, Message.obtain(null, what));
    }

    private void sendMessage(String iface, int what, Object obj) {
        sendMessage(iface, Message.obtain(null, what, obj));
    }

    private void sendMessage(String iface, int what, int arg1) {
        sendMessage(iface, Message.obtain(null, what, arg1, 0));
    }

    private void sendMessage(String iface, int what, int arg1, int arg2) {
        sendMessage(iface, Message.obtain(null, what, arg1, arg2));
    }

    private void sendMessage(String iface, int what, int arg1, int arg2, Object obj) {
        sendMessage(iface, Message.obtain(null, what, arg1, arg2, obj));
    }

    private void sendMessage(String iface, Message message) {
        SparseArray<Set<Handler>> ifaceHandlers = mHandlerMap.get(iface);
        if (iface != null && ifaceHandlers != null) {
            if (isMonitoring(iface)) {
                Set<Handler> ifaceWhatHandlers = ifaceHandlers.get(message.what);
                if (ifaceWhatHandlers != null) {
                    for (Handler handler : ifaceWhatHandlers) {
                        if (handler != null) {
                            sendMessage(handler, Message.obtain(message));
                        }
                    }
                }
            } else {
                if (mVerboseLoggingEnabled) {
                    Log.d(TAG, "Dropping event because (" + iface + ") is stopped");
                }
            }
        } else {
            if (mVerboseLoggingEnabled) {
                Log.d(TAG, "Sending to all monitors because there's no matching iface");
            }
            for (Map.Entry<String, SparseArray<Set<Handler>>> entry : mHandlerMap.entrySet()) {
                if (isMonitoring(entry.getKey())) {
                    Set<Handler> ifaceWhatHandlers = entry.getValue().get(message.what);
                    for (Handler handler : ifaceWhatHandlers) {
                        if (handler != null) {
                            sendMessage(handler, Message.obtain(message));
                        }
                    }
                }
            }
        }

        message.recycle();
    }

    private void sendMessage(Handler handler, Message message) {
        message.setTarget(handler);
        message.sendToTarget();
    }

    /**
     * Broadcast the WPS fail event to all the handlers registered for this event.
     *
     * @param iface Name of iface on which this occurred.
     * @param cfgError Configuration error code.
     * @param vendorErrorCode Vendor specific error indication code.
     */
    public void broadcastWpsFailEvent(String iface, int cfgError, int vendorErrorCode) {
        int reason = 0;
        switch(vendorErrorCode) {
            case REASON_TKIP_ONLY_PROHIBITED:
                sendMessage(iface, WPS_FAIL_EVENT, WifiManager.WPS_TKIP_ONLY_PROHIBITED);
                return;
            case REASON_WEP_PROHIBITED:
                sendMessage(iface, WPS_FAIL_EVENT, WifiManager.WPS_WEP_PROHIBITED);
                return;
            default:
                reason = vendorErrorCode;
                break;
        }
        switch(cfgError) {
            case CONFIG_AUTH_FAILURE:
                sendMessage(iface, WPS_FAIL_EVENT, WifiManager.WPS_AUTH_FAILURE);
                return;
            case CONFIG_MULTIPLE_PBC_DETECTED:
                sendMessage(iface, WPS_FAIL_EVENT, WifiManager.WPS_OVERLAP_ERROR);
                return;
            default:
                if (reason == 0) {
                    reason = cfgError;
                }
                break;
        }
        //For all other errors, return a generic internal error
        sendMessage(iface, WPS_FAIL_EVENT, WifiManager.ERROR, reason);
    }

   /**
    * Broadcast the WPS succes event to all the handlers registered for this event.
    *
    * @param iface Name of iface on which this occurred.
    */
    public void broadcastWpsSuccessEvent(String iface) {
        sendMessage(iface, WPS_SUCCESS_EVENT);
    }

    /**
     * Broadcast the WPS overlap event to all the handlers registered for this event.
     *
     * @param iface Name of iface on which this occurred.
     */
    public void broadcastWpsOverlapEvent(String iface) {
        sendMessage(iface, WPS_OVERLAP_EVENT);
    }

    /**
     * Broadcast the WPS timeout event to all the handlers registered for this event.
     *
     * @param iface Name of iface on which this occurred.
     */
    public void broadcastWpsTimeoutEvent(String iface) {
        sendMessage(iface, WPS_TIMEOUT_EVENT);
    }

    /**
     * Broadcast the ANQP done event to all the handlers registered for this event.
     *
     * @param iface Name of iface on which this occurred.
     * @param anqpEvent ANQP result retrieved.
     */
    public void broadcastAnqpDoneEvent(String iface, AnqpEvent anqpEvent) {
        sendMessage(iface, ANQP_DONE_EVENT, anqpEvent);
    }

    /**
     * Broadcast the Icon done event to all the handlers registered for this event.
     *
     * @param iface Name of iface on which this occurred.
     * @param iconEvent Instance of IconEvent containing the icon data retrieved.
     */
    public void broadcastIconDoneEvent(String iface, IconEvent iconEvent) {
        sendMessage(iface, RX_HS20_ANQP_ICON_EVENT, iconEvent);
    }

    /**
     * Broadcast the WNM event to all the handlers registered for this event.
     *
     * @param iface Name of iface on which this occurred.
     * @param wnmData Instance of WnmData containing the event data.
     */
    public void broadcastWnmEvent(String iface, WnmData wnmData) {
        sendMessage(iface, HS20_REMEDIATION_EVENT, wnmData);
    }

    /**
     * Broadcast the Network identity request event to all the handlers registered for this event.
     *
     * @param iface Name of iface on which this occurred.
     * @param networkId ID of the network in wpa_supplicant.
     * @param ssid SSID of the network.
     */
    public void broadcastNetworkIdentityRequestEvent(String iface, int networkId, String ssid) {
        sendMessage(iface, SUP_REQUEST_IDENTITY, 0, networkId, ssid);
    }

    /**
     * Broadcast the Network Gsm Sim auth request event to all the handlers registered for this
     * event.
     *
     * @param iface Name of iface on which this occurred.
     * @param networkId ID of the network in wpa_supplicant.
     * @param ssid SSID of the network.
     * @param data Accompanying event data.
     */
    public void broadcastNetworkGsmAuthRequestEvent(String iface, int networkId, String ssid,
                                                    String[] data) {
        sendMessage(iface, SUP_REQUEST_SIM_AUTH,
                new SimAuthRequestData(networkId, WifiEnterpriseConfig.Eap.SIM, ssid, data));
    }

    /**
     * Broadcast the Network Umts Sim auth request event to all the handlers registered for this
     * event.
     *
     * @param iface Name of iface on which this occurred.
     * @param networkId ID of the network in wpa_supplicant.
     * @param ssid SSID of the network.
     * @param data Accompanying event data.
     */
    public void broadcastNetworkUmtsAuthRequestEvent(String iface, int networkId, String ssid,
                                                     String[] data) {
        sendMessage(iface, SUP_REQUEST_SIM_AUTH,
                new SimAuthRequestData(networkId, WifiEnterpriseConfig.Eap.AKA, ssid, data));
    }

    /**
     * Broadcast scan result event to all the handlers registered for this event.
     * @param iface Name of iface on which this occurred.
     */
    public void broadcastScanResultEvent(String iface) {
        sendMessage(iface, SCAN_RESULTS_EVENT);
    }

    /**
     * Broadcast pno scan result event to all the handlers registered for this event.
     * @param iface Name of iface on which this occurred.
     */
    public void broadcastPnoScanResultEvent(String iface) {
        sendMessage(iface, PNO_SCAN_RESULTS_EVENT);
    }

    /**
     * Broadcast scan failed event to all the handlers registered for this event.
     * @param iface Name of iface on which this occurred.
     */
    public void broadcastScanFailedEvent(String iface) {
        sendMessage(iface, SCAN_FAILED_EVENT);
    }

    /**
     * Broadcast the authentication failure event to all the handlers registered for this event.
     *
     * @param iface Name of iface on which this occurred.
     * @param reason Reason for authentication failure. This has to be one of the
     *               {@link android.net.wifi.WifiManager#ERROR_AUTH_FAILURE_NONE},
     *               {@link android.net.wifi.WifiManager#ERROR_AUTH_FAILURE_TIMEOUT},
     *               {@link android.net.wifi.WifiManager#ERROR_AUTH_FAILURE_WRONG_PSWD},
     *               {@link android.net.wifi.WifiManager#ERROR_AUTH_FAILURE_EAP_FAILURE}
     * @param errorCode Error code associated with the authentication failure event.
     *               A value of -1 is used when no error code is reported.
     */
    public void broadcastAuthenticationFailureEvent(String iface, int reason, int errorCode) {
        sendMessage(iface, AUTHENTICATION_FAILURE_EVENT, reason, errorCode);
    }

    /**
     * Broadcast the association rejection event to all the handlers registered for this event.
     *
     * @param iface Name of iface on which this occurred.
     * @param status Status code for association rejection.
     * @param timedOut Indicates if the association timed out.
     * @param bssid BSSID of the access point from which we received the reject.
     */
    public void broadcastAssociationRejectionEvent(String iface, int status, boolean timedOut,
                                                   String bssid) {
        sendMessage(iface, ASSOCIATION_REJECTION_EVENT, timedOut ? 1 : 0, status, bssid);
    }

    /**
     * Broadcast the association success event to all the handlers registered for this event.
     *
     * @param iface Name of iface on which this occurred.
     * @param bssid BSSID of the access point.
     */
    public void broadcastAssociatedBssidEvent(String iface, String bssid) {
        sendMessage(iface, ASSOCIATED_BSSID_EVENT, 0, 0, bssid);
    }

    /**
     * Broadcast the start of association event to all the handlers registered for this event.
     *
     * @param iface Name of iface on which this occurred.
     * @param bssid BSSID of the access point.
     */
    public void broadcastTargetBssidEvent(String iface, String bssid) {
        sendMessage(iface, TARGET_BSSID_EVENT, 0, 0, bssid);
    }

    /**
     * Broadcast the network connection event to all the handlers registered for this event.
     *
     * @param iface Name of iface on which this occurred.
     * @param networkId ID of the network in wpa_supplicant.
     * @param bssid BSSID of the access point.
     */
    public void broadcastNetworkConnectionEvent(String iface, int networkId, String bssid) {
        sendMessage(iface, NETWORK_CONNECTION_EVENT, networkId, 0, bssid);
    }

    /**
     * Broadcast the fils network connection event to all the handlers registered for this event.
     *
     * @param iface Name of iface on which this occurred.
     * @param networkId ID of the network in wpa_supplicant.
     * @param bssid BSSID of the access point.
     */
    public void broadcastFilsNetworkConnectionEvent(String iface, int networkId, String bssid) {
        sendMessage(iface, FILS_NETWORK_CONNECTION_EVENT, networkId, 0, bssid);
    }

    /**
     * Broadcast the network disconnection event to all the handlers registered for this event.
     *
     * @param iface Name of iface on which this occurred.
     * @param local Whether the disconnect was locally triggered.
     * @param reason Disconnect reason code.
     * @param bssid BSSID of the access point.
     */
    public void broadcastNetworkDisconnectionEvent(String iface, int local, int reason,
                                                   String bssid) {
        sendMessage(iface, NETWORK_DISCONNECTION_EVENT, local, reason, bssid);
    }

    /**
     * Broadcast the supplicant state change event to all the handlers registered for this event.
     *
     * @param iface Name of iface on which this occurred.
     * @param networkId ID of the network in wpa_supplicant.
     * @param bssid BSSID of the access point.
     * @param newSupplicantState New supplicant state.
     */
    public void broadcastSupplicantStateChangeEvent(String iface, int networkId, WifiSsid wifiSsid,
                                                    String bssid,
                                                    SupplicantState newSupplicantState) {
        sendMessage(iface, SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
                new StateChangeResult(networkId, wifiSsid, bssid, newSupplicantState));
    }

    /**
     * Broadcast the connection to wpa_supplicant event to all the handlers registered for
     * this event.
     *
     * @param iface Name of iface on which this occurred.
     */
    public void broadcastSupplicantConnectionEvent(String iface) {
        sendMessage(iface, SUP_CONNECTION_EVENT);
    }

    /**
     * Broadcast the loss of connection to wpa_supplicant event to all the handlers registered for
     * this event.
     *
     * @param iface Name of iface on which this occurred.
     */
    public void broadcastSupplicantDisconnectionEvent(String iface) {
        sendMessage(iface, SUP_DISCONNECTION_EVENT);
    }

    /**
     * Broadcast the bss transition management frame handling event
     * to all the handlers registered for this event.
     *
     * @param iface Name of iface on which this occurred.
     */
    public void broadcastBssTmHandlingDoneEvent(String iface, BtmFrameData btmFrmData) {
        sendMessage(iface, MBO_OCE_BSS_TM_HANDLING_DONE, btmFrmData);
    }
}
