/*
 * Copyright (C) 2018 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.settings.fuelgauge.batterytip;

import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.app.StatsManager;
import android.content.Context;
import android.content.Intent;
import android.os.UserHandle;
import android.os.UserManager;

import androidx.annotation.NonNull;

import com.android.internal.util.CollectionUtils;
import com.android.settings.SettingsActivity;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.fuelgauge.batterytip.actions.BatterySaverAction;
import com.android.settings.fuelgauge.batterytip.actions.BatteryTipAction;
import com.android.settings.fuelgauge.batterytip.actions.OpenBatterySaverAction;
import com.android.settings.fuelgauge.batterytip.actions.OpenRestrictAppFragmentAction;
import com.android.settings.fuelgauge.batterytip.actions.RestrictAppAction;
import com.android.settings.fuelgauge.batterytip.actions.SmartBatteryAction;
import com.android.settings.fuelgauge.batterytip.actions.UnrestrictAppAction;
import com.android.settings.fuelgauge.batterytip.tips.AppLabelPredicate;
import com.android.settings.fuelgauge.batterytip.tips.AppRestrictionPredicate;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip;

import java.util.ArrayList;
import java.util.List;

/**
 * Utility class for {@link BatteryTip}
 */
public class BatteryTipUtils {
    private static final int REQUEST_CODE = 0;

    /**
     * Get a list of restricted apps with {@link AppOpsManager#OP_RUN_ANY_IN_BACKGROUND}
     */
    @NonNull
    public static List<AppInfo> getRestrictedAppsList(AppOpsManager appOpsManager,
            UserManager userManager) {
        final List<UserHandle> userHandles = userManager.getUserProfiles();
        final List<AppOpsManager.PackageOps> packageOpsList = appOpsManager.getPackagesForOps(
                new int[]{AppOpsManager.OP_RUN_ANY_IN_BACKGROUND});
        final List<AppInfo> appInfos = new ArrayList<>();

        for (int i = 0, size = CollectionUtils.size(packageOpsList); i < size; i++) {
            final AppOpsManager.PackageOps packageOps = packageOpsList.get(i);
            final List<AppOpsManager.OpEntry> entries = packageOps.getOps();
            for (int j = 0, entriesSize = entries.size(); j < entriesSize; j++) {
                AppOpsManager.OpEntry entry = entries.get(j);
                if (entry.getOp() != AppOpsManager.OP_RUN_ANY_IN_BACKGROUND) {
                    continue;
                }
                if (entry.getMode() != AppOpsManager.MODE_ALLOWED
                        && userHandles.contains(
                        new UserHandle(UserHandle.getUserId(packageOps.getUid())))) {
                    appInfos.add(new AppInfo.Builder()
                            .setPackageName(packageOps.getPackageName())
                            .setUid(packageOps.getUid())
                            .build());
                }
            }
        }

        return appInfos;
    }

    /**
     * Get a corresponding action based on {@code batteryTip}
     * @param batteryTip used to detect which action to choose
     * @param settingsActivity used to populate {@link BatteryTipAction}
     * @param fragment used to populate {@link BatteryTipAction}
     * @return an action for {@code batteryTip}
     */
    public static BatteryTipAction getActionForBatteryTip(BatteryTip batteryTip,
            SettingsActivity settingsActivity, InstrumentedPreferenceFragment fragment) {
        switch (batteryTip.getType()) {
            case BatteryTip.TipType.SMART_BATTERY_MANAGER:
                return new SmartBatteryAction(settingsActivity, fragment);
            case BatteryTip.TipType.BATTERY_SAVER:
            case BatteryTip.TipType.LOW_BATTERY:
                if (batteryTip.getState() == BatteryTip.StateType.HANDLED) {
                    return new OpenBatterySaverAction(settingsActivity);
                } else {
                    return new BatterySaverAction(settingsActivity);
                }
            case BatteryTip.TipType.APP_RESTRICTION:
                if (batteryTip.getState() == BatteryTip.StateType.HANDLED) {
                    return new OpenRestrictAppFragmentAction(fragment, (RestrictAppTip) batteryTip);
                } else {
                    return new RestrictAppAction(settingsActivity, (RestrictAppTip) batteryTip);
                }
            case BatteryTip.TipType.REMOVE_APP_RESTRICTION:
                return new UnrestrictAppAction(settingsActivity, (UnrestrictAppTip) batteryTip);
            default:
                return null;
        }
    }

    /**
     * Upload the {@link PendingIntent} to {@link StatsManager} for anomaly detection
     * @throws StatsManager.StatsUnavailableException if failed to communicate with stats service
     */
    public static void uploadAnomalyPendingIntent(Context context, StatsManager statsManager)
            throws StatsManager.StatsUnavailableException {
        final Intent extraIntent = new Intent(context, AnomalyDetectionReceiver.class);
        final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, REQUEST_CODE,
                extraIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        statsManager.setBroadcastSubscriber(pendingIntent,
                StatsManagerConfig.ANOMALY_CONFIG_KEY, StatsManagerConfig.SUBSCRIBER_ID);
    }

    /**
     * Detect and return anomaly apps after {@code timeAfterMs}
     */
    public static List<AppInfo> detectAnomalies(Context context, long timeAfterMs) {
        final List<AppInfo> highUsageApps = BatteryDatabaseManager.getInstance(context)
                .queryAllAnomalies(timeAfterMs, AnomalyDatabaseHelper.State.NEW);
        // Remove it if it doesn't have label or been restricted
        highUsageApps.removeIf(AppLabelPredicate.getInstance(context)
                .or(AppRestrictionPredicate.getInstance(context)));

        return highUsageApps;
    }
}
