/*
 * Copyright (C) 2019 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.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.drawable.Icon;
import android.net.wifi.WifiConfiguration;
import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.telephony.SubscriptionManager;
import android.text.TextUtils;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;

/**
 * This class may be used to launch notifications when EAP failure occurs.
 */
public class EapFailureNotifier {
    private static final String TAG = "EapFailureNotifier";
    private static final String ERROR_MESSAGE_OVERLAY_PREFIX = "wifi_eap_error_message_code_";

    private static final long CANCEL_TIMEOUT_MILLISECONDS = 5 * 60 * 1000;
    private final WifiContext mContext;
    private final WifiNotificationManager mNotificationManager;
    private final FrameworkFacade mFrameworkFacade;
    private final WifiCarrierInfoManager mWifiCarrierInfoManager;

    // Unique ID associated with the notification.
    public static final int NOTIFICATION_ID = SystemMessage.NOTE_WIFI_EAP_FAILURE;
    private String mCurrentShownSsid;

    public EapFailureNotifier(WifiContext context, FrameworkFacade frameworkFacade,
            WifiCarrierInfoManager wifiCarrierInfoManager,
            WifiNotificationManager wifiNotificationManager) {
        mContext = context;
        mFrameworkFacade = frameworkFacade;
        mWifiCarrierInfoManager = wifiCarrierInfoManager;
        mNotificationManager = wifiNotificationManager;
    }

    /**
     * Invoked when EAP failure occurs.
     *
     * @param errorCode error code which delivers from supplicant
     * @param showNotification whether to display the notification
     * @return true if the receiving error code is found in wifi resource
     */
    public boolean onEapFailure(int errorCode, WifiConfiguration config, boolean showNotification) {
        Resources res = getResourcesForSubId(mContext,
                mWifiCarrierInfoManager.getBestMatchSubscriptionId(config));
        if (res == null) return false;
        int resourceId = res.getIdentifier(ERROR_MESSAGE_OVERLAY_PREFIX + errorCode,
                "string", mContext.getWifiOverlayApkPkgName());

        if (resourceId == 0) return false;
        String errorMessage = res.getString(resourceId, config.SSID);
        if (TextUtils.isEmpty(errorMessage)) return false;
        StatusBarNotification[] activeNotifications = mNotificationManager.getActiveNotifications();
        for (StatusBarNotification activeNotification : activeNotifications) {
            if ((activeNotification.getId() == NOTIFICATION_ID)
                    && TextUtils.equals(config.SSID, mCurrentShownSsid)) {
                return true;
            }
        }

        if (showNotification) {
            showNotification(errorMessage, config.SSID);
        }
        return true;
    }

    /**
     * Display eap error notification which defined by carrier.
     *
     * @param ssid Error Message which defined by carrier
     */
    private void showNotification(String errorMessage, String ssid) {
        String settingsPackage = mFrameworkFacade.getSettingsPackageName(mContext);
        if (settingsPackage == null) return;
        Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS)
                .setPackage(settingsPackage);
        Notification.Builder builder = mFrameworkFacade.makeNotificationBuilder(mContext,
                WifiService.NOTIFICATION_NETWORK_ALERTS)
                .setAutoCancel(true)
                .setTimeoutAfter(CANCEL_TIMEOUT_MILLISECONDS)
                .setSmallIcon(Icon.createWithResource(mContext.getWifiOverlayApkPkgName(),
                        com.android.wifi.resources.R.drawable.stat_notify_wifi_in_range))
                .setContentTitle(mContext.getString(
                        com.android.wifi.resources.R.string.wifi_available_title_failed_to_connect))
                .setContentText(errorMessage)
                .setStyle(new Notification.BigTextStyle().bigText(errorMessage))
                .setContentIntent(mFrameworkFacade.getActivity(
                        mContext, 0, intent,
                        PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE))
                .setColor(mContext.getResources().getColor(
                        android.R.color.system_notification_accent_color));
        mNotificationManager.notify(NOTIFICATION_ID,
                builder.build());
        mCurrentShownSsid = ssid;
    }

    /**
     *  Returns the resources from the given context for the MCC/MNC
     *  associated with the subscription.
     */
    private Resources getResourcesForSubId(WifiContext context, int subId) {
        Context resourceContext = null;
        try {
            resourceContext = context.createPackageContext(
                    context.getWifiOverlayApkPkgName(), 0);
        } catch (PackageManager.NameNotFoundException ex) {
            return null;
        }

        return SubscriptionManager.getResourcesForSubId(resourceContext, subId);
    }

    /**
     * Allow tests to modify mCurrentShownSsid
     */
    @VisibleForTesting
    void setCurrentShownSsid(String currentShownSsid) {
        mCurrentShownSsid = currentShownSsid;
    }
}
