/*
 * Copyright 2020 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.google.android.iwlan;

import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
import android.net.Uri;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.telephony.CarrierConfigManager;
import android.telephony.CellInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsManager;
import android.telephony.ims.ImsMmTelManager;
import android.util.Log;
import android.util.SparseArray;

import com.android.internal.annotations.VisibleForTesting;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class IwlanEventListener {

    public static final int UNKNOWN_EVENT = -1;

    /** On receiving {@link CarrierConfigManager#ACTION_CARRIER_CONFIG_CHANGED} intent. */
    public static final int CARRIER_CONFIG_CHANGED_EVENT = 1;

    /** Wifi turned off or disabled. */
    public static final int WIFI_DISABLE_EVENT = 2;

    /** Airplane mode turned off or disabled. */
    public static final int APM_DISABLE_EVENT = 3;
    /** Airplame mode turned on or enabled */
    public static final int APM_ENABLE_EVENT = 4;

    /** Wifi AccessPoint changed. */
    public static final int WIFI_AP_CHANGED_EVENT = 5;

    /** Wifi calling turned on or enabled */
    public static final int WIFI_CALLING_ENABLE_EVENT = 6;

    /** Wifi calling turned off or disabled */
    public static final int WIFI_CALLING_DISABLE_EVENT = 7;

    /** Cross sim calling enabled */
    public static final int CROSS_SIM_CALLING_ENABLE_EVENT = 8;

    /** Cross sim calling disabled */
    public static final int CROSS_SIM_CALLING_DISABLE_EVENT = 9;

    /**
     * On receiving {@link CarrierConfigManager#ACTION_CARRIER_CONFIG_CHANGED} intent with
     * UNKNOWN_CARRIER_ID.
     */
    public static final int CARRIER_CONFIG_UNKNOWN_CARRIER_EVENT = 10;

    /** On Cellinfo changed */
    public static final int CELLINFO_CHANGED_EVENT = 11;

    /* Events used and handled by IwlanDataService internally */
    public static final int DATA_SERVICE_INTERNAL_EVENT_BASE = 100;

    public static final int DATA_SERVICE_INTERNAL_EVENT_END = 200;

    /* Events used and handled by IwlanNetworkService internally */
    public static final int NETWORK_SERVICE_INTERNAL_EVENT_BASE = 200;

    public static final int NETWORK_SERVICE_INTERNAL_EVENT_END = 300;

    @IntDef({
        CARRIER_CONFIG_CHANGED_EVENT,
        WIFI_DISABLE_EVENT,
        APM_DISABLE_EVENT,
        APM_ENABLE_EVENT,
        WIFI_AP_CHANGED_EVENT,
        WIFI_CALLING_ENABLE_EVENT,
        WIFI_CALLING_DISABLE_EVENT,
        CROSS_SIM_CALLING_ENABLE_EVENT,
        CROSS_SIM_CALLING_DISABLE_EVENT,
        CARRIER_CONFIG_UNKNOWN_CARRIER_EVENT,
        CELLINFO_CHANGED_EVENT
    })
    @interface IwlanEventType {};

    private static String LOG_TAG = IwlanEventListener.class.getSimpleName();

    private final String SUB_TAG;

    private static Boolean sIsAirplaneModeOn;

    private static String sWifiSSID = new String();

    private static Map<Integer, IwlanEventListener> mInstances = new ConcurrentHashMap<>();

    private Context mContext;
    private int mSlotId;
    private int mSubId;
    private Uri mCrossSimCallingUri;
    private Uri mWfcEnabledUri;
    private UserSettingContentObserver mUserSettingContentObserver;
    private HandlerThread mUserSettingHandlerThread;
    private RadioInfoTelephonyCallback mTelephonyCallback;

    SparseArray<Set<Handler>> eventHandlers = new SparseArray<>();

    private class UserSettingContentObserver extends ContentObserver {
        UserSettingContentObserver(Handler h) {
            super(h);
        }

        @Override
        public void onChange(boolean selfChange, Uri uri) {
            if (mCrossSimCallingUri.equals(uri)) {
                notifyCurrentSetting(uri);
            } else if (mWfcEnabledUri.equals(uri)) {
                notifyCurrentSetting(uri);
            }
        }
    }

    private class RadioInfoTelephonyCallback extends TelephonyCallback
            implements TelephonyCallback.CellInfoListener {
        @Override
        public void onCellInfoChanged(List<CellInfo> arrayCi) {
            Log.d(LOG_TAG, "Cellinfo changed");

            int event = CELLINFO_CHANGED_EVENT;
            for (Map.Entry<Integer, IwlanEventListener> entry : mInstances.entrySet()) {
                IwlanEventListener instance = entry.getValue();
                if (instance != null) {
                    instance.updateHandlers(event, arrayCi);
                }
            }
        }
    }

    /**
     * Returns IwlanEventListener instance
     */
    public static IwlanEventListener getInstance(@NonNull Context context, int slotId) {
        return mInstances.computeIfAbsent(slotId, k -> new IwlanEventListener(context, slotId));
    }

    @VisibleForTesting
    public static void resetAllInstances() {
        mInstances.clear();
    }

    /**
     * Adds handler for the list of events.
     *
     * @param events lists of events for which the handler needs to be notified.
     * @param handler handler to be called when the events happen
     */
    public synchronized void addEventListener(List<Integer> events, Handler handler) {
        for (@IwlanEventType int event : events) {
            if (eventHandlers.contains(event)) {
                eventHandlers.get(event).add(handler);
            } else {
                Set<Handler> handlers = new HashSet<>();
                handlers.add(handler);
                eventHandlers.append(event, handlers);
            }
        }
    }

    /**
     * Removes handler for the list of events.
     *
     * @param events lists of events for which the handler needs to be removed.
     * @param handler handler to be removed
     */
    public synchronized void removeEventListener(List<Integer> events, Handler handler) {
        for (int event : events) {
            if (eventHandlers.contains(event)) {
                Set<Handler> handlers = eventHandlers.get(event);
                handlers.remove(handler);
                if (handlers.isEmpty()) {
                    eventHandlers.delete(event);
                }
            }
        }
        if (eventHandlers.size() == 0) {
            mInstances.remove(mSlotId, this);
        }
    }

    /**
     * Removes handler for all events it is registered
     *
     * @param handler handler to be removed
     */
    public synchronized void removeEventListener(Handler handler) {
        for (int i = 0; i < eventHandlers.size(); i++) {
            Set<Handler> handlers = eventHandlers.valueAt(i);
            handlers.remove(handler);
            if (handlers.isEmpty()) {
                eventHandlers.delete(eventHandlers.keyAt(i));
                i--;
            }
        }
        if (eventHandlers.size() == 0) {
            mInstances.remove(mSlotId, this);
        }
    }

    /**
     * Report a Broadcast received. Mainly used by IwlanBroadcastReceiver to report the following
     * broadcasts CARRIER_CONFIG_CHANGED
     *
     * @param Intent intent
     */
    public static synchronized void onBroadcastReceived(Intent intent) {
        int event = UNKNOWN_EVENT;
        switch (intent.getAction()) {
            case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED:
                int slotId =
                        intent.getIntExtra(
                                CarrierConfigManager.EXTRA_SLOT_INDEX,
                                SubscriptionManager.INVALID_SIM_SLOT_INDEX);
                int carrierId =
                        intent.getIntExtra(
                                TelephonyManager.EXTRA_CARRIER_ID,
                                TelephonyManager.UNKNOWN_CARRIER_ID);
                Context context = IwlanDataService.getContext();
                if (slotId != SubscriptionManager.INVALID_SIM_SLOT_INDEX && context != null) {
                    getInstance(context, slotId).onCarrierConfigChanged(slotId, carrierId);
                }
                break;
            case Intent.ACTION_AIRPLANE_MODE_CHANGED:
                Boolean isAirplaneModeOn = new Boolean(intent.getBooleanExtra("state", false));
                if (sIsAirplaneModeOn != null && sIsAirplaneModeOn.equals(isAirplaneModeOn)) {
                    // no change in apm state
                    break;
                }
                sIsAirplaneModeOn = isAirplaneModeOn;
                event = sIsAirplaneModeOn ? APM_ENABLE_EVENT : APM_DISABLE_EVENT;
                for (Map.Entry<Integer, IwlanEventListener> entry : mInstances.entrySet()) {
                    IwlanEventListener instance = entry.getValue();
                    instance.updateHandlers(event);
                }
                break;
            case WifiManager.WIFI_STATE_CHANGED_ACTION:
                int wifiState =
                        intent.getIntExtra(
                                WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN);
                if (wifiState == WifiManager.WIFI_STATE_DISABLED) {
                    event = WIFI_DISABLE_EVENT;
                    for (Map.Entry<Integer, IwlanEventListener> entry : mInstances.entrySet()) {
                        IwlanEventListener instance = entry.getValue();
                        instance.updateHandlers(event);
                    }
                }
                break;
        }
    }

    /**
     * Broadcast WIFI_AP_CHANGED_EVENT if Wifi SSID changed after Wifi connected.
     *
     * @param Context context
     */
    public static void onWifiConnected(Context context) {
        WifiManager wifiManager = context.getSystemService(WifiManager.class);
        if (wifiManager == null) {
            Log.e(LOG_TAG, "Could not find wifiManager");
            return;
        }
        WifiInfo wifiInfo = wifiManager.getConnectionInfo();
        if (wifiInfo == null) {
            Log.e(LOG_TAG, "wifiInfo is null");
            return;
        }
        String wifiSSID = wifiInfo.getSSID();
        if (wifiSSID.equals(WifiManager.UNKNOWN_SSID)) {
            Log.e(LOG_TAG, "Could not get Wifi SSID");
            return;
        }

        // Check sWifiSSID is greater than 0 to avoid trigger event after device first camps on
        // Wifi.
        if (sWifiSSID.length() > 0 && !sWifiSSID.equals(wifiSSID)) {
            Log.d(LOG_TAG, "Wifi SSID changed");
            int event = WIFI_AP_CHANGED_EVENT;
            for (Map.Entry<Integer, IwlanEventListener> entry : mInstances.entrySet()) {
                IwlanEventListener instance = entry.getValue();
                if (instance != null) {
                    instance.updateHandlers(event);
                }
            }
        }
        sWifiSSID = wifiSSID;
    }

    /**
     * Returns the Event id of the String. String that matches the name of the event
     *
     * @param event String form of the event.
     * @param int form of the event.
     */
    public static int getUnthrottlingEvent(String event) {
        int ret = UNKNOWN_EVENT;
        switch (event) {
            case "CARRIER_CONFIG_CHANGED_EVENT":
                ret = CARRIER_CONFIG_CHANGED_EVENT;
                break;
            case "WIFI_DISABLE_EVENT":
                ret = WIFI_DISABLE_EVENT;
                break;
            case "APM_DISABLE_EVENT":
                ret = APM_DISABLE_EVENT;
                break;
            case "APM_ENABLE_EVENT":
                ret = APM_ENABLE_EVENT;
                break;
            case "WIFI_AP_CHANGED_EVENT":
                ret = WIFI_AP_CHANGED_EVENT;
                break;
            case "WIFI_CALLING_ENABLE_EVENT":
                ret = WIFI_CALLING_ENABLE_EVENT;
                break;
            case "WIFI_CALLING_DISABLE_EVENT":
                ret = WIFI_CALLING_DISABLE_EVENT;
                break;
            case "CROSS_SIM_CALLING_ENABLE_EVENT":
                ret = CROSS_SIM_CALLING_ENABLE_EVENT;
                break;
            case "CROSS_SIM_CALLING_DISABLE_EVENT":
                ret = CROSS_SIM_CALLING_DISABLE_EVENT;
                break;
            case "CARRIER_CONFIG_UNKNOWN_CARRIER_EVENT":
                ret = CARRIER_CONFIG_UNKNOWN_CARRIER_EVENT;
                break;
            case "CELLINFO_CHANGED_EVENT":
                ret = CELLINFO_CHANGED_EVENT;
                break;
        }
        return ret;
    }

    private IwlanEventListener(Context context, int slotId) {
        mContext = context;
        mSlotId = slotId;
        mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
        SUB_TAG = IwlanEventListener.class.getSimpleName() + "[" + slotId + "]";
        sIsAirplaneModeOn = null;
    }

    private void onCarrierConfigChanged(int slotId, int carrierId) {
        Log.d(SUB_TAG, "onCarrierConfigChanged");
        int subId = IwlanHelper.getSubId(mContext, mSlotId);
        if (subId != mSubId) {
            unregisterContentObserver();
            mSubId = subId;
            registerContentObserver();
        }
        notifyCurrentSetting(mCrossSimCallingUri);
        notifyCurrentSetting(mWfcEnabledUri);

        int event;
        if (carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) {
            event = CARRIER_CONFIG_CHANGED_EVENT;
            registerTelephonyCallback();
        } else {
            event = CARRIER_CONFIG_UNKNOWN_CARRIER_EVENT;
        }
        updateHandlers(event);
    }

    /** Unregister ContentObserver. */
    private void unregisterContentObserver() {
        if (mUserSettingContentObserver != null) {
            mContext.getContentResolver().unregisterContentObserver(mUserSettingContentObserver);
        }
        mCrossSimCallingUri = null;
        mWfcEnabledUri = null;
    }

    /** Initiate ContentObserver if it is not created. And, register it with the current sub id. */
    private void registerContentObserver() {
        if (mUserSettingContentObserver == null) {
            mUserSettingHandlerThread =
                    new HandlerThread(IwlanNetworkService.class.getSimpleName());
            mUserSettingHandlerThread.start();
            Looper looper = mUserSettingHandlerThread.getLooper();
            Handler handler = new Handler(looper);
            mUserSettingContentObserver = new UserSettingContentObserver(handler);
        }

        if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
            return;
        }

        ContentResolver resolver = mContext.getContentResolver();
        // Register for CrossSimCalling setting uri
        mCrossSimCallingUri =
                Uri.withAppendedPath(
                        SubscriptionManager.CROSS_SIM_ENABLED_CONTENT_URI, String.valueOf(mSubId));
        resolver.registerContentObserver(mCrossSimCallingUri, true, mUserSettingContentObserver);

        // Register for WifiCalling setting uri
        mWfcEnabledUri =
                Uri.withAppendedPath(
                        SubscriptionManager.WFC_ENABLED_CONTENT_URI, String.valueOf(mSubId));
        resolver.registerContentObserver(mWfcEnabledUri, true, mUserSettingContentObserver);
    }

    @VisibleForTesting
    void notifyCurrentSetting(Uri uri) {
        if (uri == null) {
            return;
        }
        String uriString = uri.getPath();
        int subIndex = Integer.parseInt(uriString.substring(uriString.lastIndexOf('/') + 1));
        int slotIndex = SubscriptionManager.getSlotIndex(subIndex);

        if (slotIndex == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
            Log.e(SUB_TAG, "Invalid slot index: " + slotIndex);
            return;
        }

        if (uri.equals(mCrossSimCallingUri)) {
            boolean isCstEnabled = IwlanHelper.isCrossSimCallingEnabled(mContext, slotIndex);
            int event =
                    (isCstEnabled)
                            ? CROSS_SIM_CALLING_ENABLE_EVENT
                            : CROSS_SIM_CALLING_DISABLE_EVENT;
            getInstance(mContext, slotIndex).updateHandlers(event);
        } else if (uri.equals(mWfcEnabledUri)) {
            ImsManager imsManager = mContext.getSystemService(ImsManager.class);
            if (imsManager == null) {
                Log.e(SUB_TAG, "Could not find  ImsManager");
                return;
            }
            ImsMmTelManager imsMmTelManager = imsManager.getImsMmTelManager(subIndex);
            if (imsMmTelManager == null) {
                Log.e(SUB_TAG, "Could not find  ImsMmTelManager");
                return;
            }
            boolean wfcEnabled = imsMmTelManager.isVoWiFiSettingEnabled();
            int event = (wfcEnabled) ? WIFI_CALLING_ENABLE_EVENT : WIFI_CALLING_DISABLE_EVENT;
            getInstance(mContext, slotIndex).updateHandlers(event);
        } else {
            Log.e(SUB_TAG, "Unknown Uri : " + uri);
        }
    }

    @VisibleForTesting
    void registerTelephonyCallback() {
        Log.d(SUB_TAG, "registerTelephonyCallback");
        TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
        telephonyManager =
                telephonyManager.createForSubscriptionId(IwlanHelper.getSubId(mContext, mSlotId));
        mTelephonyCallback = new RadioInfoTelephonyCallback();
        telephonyManager.registerTelephonyCallback(r -> r.run(), mTelephonyCallback);
    }

    @VisibleForTesting
    void setCrossSimCallingUri(Uri uri) {
        mCrossSimCallingUri = uri;
    }

    @VisibleForTesting
    void setWfcEnabledUri(Uri uri) {
        mWfcEnabledUri = uri;
    }

    @VisibleForTesting
    RadioInfoTelephonyCallback getTelephonyCallback() {
        return mTelephonyCallback;
    }

    private synchronized void updateHandlers(int event) {
        if (eventHandlers.contains(event)) {
            Log.d(SUB_TAG, "Updating handlers for the event: " + event);
            for (Handler handler : eventHandlers.get(event)) {
                handler.obtainMessage(event, mSlotId, 0 /* unused */).sendToTarget();
            }
        }
    }

    private synchronized void updateHandlers(int event, List<CellInfo> arrayCi) {
        if (eventHandlers.contains(event)) {
            Log.d(SUB_TAG, "Updating handlers for the event: " + event);
            for (Handler handler : eventHandlers.get(event)) {
                handler.obtainMessage(event, mSlotId, 0 /* unused */, arrayCi).sendToTarget();
            }
        }
    }
}
