/*
 * 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.BatteryDefenderAction;
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);
            case BatteryTip.TipType.BATTERY_DEFENDER:
                return new BatteryDefenderAction(settingsActivity);
            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;
    }
}
