/*
 * Copyright (C) 2016 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.storagemanager.deletionhelper;

import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.storage.VolumeInfo;
import android.text.TextUtils;

import com.android.settingslib.applications.StorageStatsSource;
import com.android.settingslib.applications.StorageStatsSource.AppStorageStats;
import com.android.storagemanager.deletionhelper.AppsAsyncLoader.PackageInfo;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowApplication;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@RunWith(RobolectricTestRunner.class)
public class AppsAsyncLoaderTest {

    private static final String PACKAGE_SYSTEM = "package.system";
    private static final long STARTING_TIME = TimeUnit.DAYS.toMillis(1000);
    private static final String PACKAGE_NAME = "package.mcpackageface";
    private static final String PACKAGE_CLEARABLE = "package.clearable";
    private static final String PACKAGE_TOO_NEW_TO_DELETE = "package.tooNewToDelete";
    private static final String PACKAGE_DEFAULT_LAUNCHER = "package.launcherface";

    @Mock private UsageStatsManager mUsageStatsManager;
    @Mock private StorageStatsSource mStorageStatsSource;
    @Mock private AppsAsyncLoader.Clock mClock;
    @Mock private PackageManager mPackageManager;
    @Mock private AppStorageStats mAppStorageStats;
    private AppsAsyncLoader mLoader;
    private HashMap<String, UsageStats> mUsageStats;
    private ArrayList<ApplicationInfo> mInfo;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);

        // Set up our mock usage app service.
        ShadowApplication app = Shadows.shadowOf(RuntimeEnvironment.application);
        app.setSystemService(Context.USAGE_STATS_SERVICE, mUsageStatsManager);

        // Initialize filters and loader with mock objects
        AppsAsyncLoader.FILTER_NO_THRESHOLD.init();
        AppsAsyncLoader.FILTER_USAGE_STATS.init();

        // Set up the AppsAsyncLoader with a fake clock for us to manipulate the time.
        when(mClock.getCurrentTime()).thenReturn(STARTING_TIME);

        // Set up the loader to return our fake list of apps.
        mInfo = new ArrayList<>();
        when(mPackageManager.getInstalledApplicationsAsUser(anyInt(), anyInt())).thenReturn(mInfo);
        when(mPackageManager.getHomeActivities(any(List.class)))
                .thenReturn(new ComponentName(PACKAGE_DEFAULT_LAUNCHER, ""));

        AppsAsyncLoader.FILTER_USAGE_STATS.init();

        // Set up our fake usage app.
        mUsageStats = new HashMap<>();
        when(mUsageStatsManager.queryAndAggregateUsageStats(anyLong(), anyLong()))
                .thenReturn(mUsageStats);
        when(mStorageStatsSource.getStatsForUid(any(), anyInt())).thenReturn(mAppStorageStats);

        mLoader =
                new AppsAsyncLoader.Builder(RuntimeEnvironment.application)
                        .setUid(0)
                        .setUuid(VolumeInfo.ID_PRIVATE_INTERNAL)
                        .setStorageStatsSource(mStorageStatsSource)
                        .setPackageManager(mPackageManager)
                        .setUsageStatsManager(mUsageStatsManager)
                        .setFilter(AppsAsyncLoader.FILTER_NO_THRESHOLD)
                        .build();
        mLoader.mClock = mClock;
    }

    @Test
    public void test_appInstalledSameDayNeverUsed_isInvalid() {
        AppsAsyncLoader.PackageInfo app =
                createPackage(PACKAGE_NAME, AppsAsyncLoader.NEVER_USED, 0);

        assertThat(AppsAsyncLoader.FILTER_USAGE_STATS.filterApp(app)).isFalse();
    }

    @Test
    public void test_noThresholdFilter_appInstalledSameDayNeverUsed_isValid() {
        AppsAsyncLoader.PackageInfo app =
                createPackage(PACKAGE_NAME, AppsAsyncLoader.NEVER_USED, 0);

        assertThat(AppsAsyncLoader.FILTER_NO_THRESHOLD.filterApp(app)).isTrue();
    }

    @Test
    public void test_unusedApp_isValid() {
        AppsAsyncLoader.PackageInfo app =
                createPackage(PACKAGE_NAME, AppsAsyncLoader.NEVER_USED, 90);

        assertThat(AppsAsyncLoader.FILTER_USAGE_STATS.filterApp(app)).isTrue();
    }

    @Test
    public void test_noThresholdFilter_unusedApp_isValid() {
        AppsAsyncLoader.PackageInfo app =
                createPackage(PACKAGE_NAME, AppsAsyncLoader.NEVER_USED, 90);

        assertThat(AppsAsyncLoader.FILTER_NO_THRESHOLD.filterApp(app)).isTrue();
    }

    @Test
    public void test_unknownLastUse_isFilteredOut() {
        AppsAsyncLoader.PackageInfo app = createPackage(PACKAGE_NAME, -1, 90);

        assertThat(AppsAsyncLoader.FILTER_USAGE_STATS.filterApp(app)).isFalse();
    }

    @Test
    public void test_noThresholdFilter_unknownLastUse_isFilteredOut() {
        AppsAsyncLoader.PackageInfo app = createPackage(PACKAGE_NAME, -1, 90);

        assertThat(AppsAsyncLoader.FILTER_NO_THRESHOLD.filterApp(app)).isFalse();
    }

    @Test
    public void test_oldAppRecentlyUsed_isNotValid() {
        AppsAsyncLoader.PackageInfo app = createPackage(PACKAGE_NAME, 1, 200);

        assertThat(AppsAsyncLoader.FILTER_USAGE_STATS.filterApp(app)).isFalse();
    }

    @Test
    public void test_noThresholdFilter_oldAppRecentlyUsed_isValid() {
        AppsAsyncLoader.PackageInfo app = createPackage(PACKAGE_NAME, 1, 200);

        assertThat(AppsAsyncLoader.FILTER_NO_THRESHOLD.filterApp(app)).isTrue();
    }

    @Test
    public void test_oldUnusedApp_isValid() {
        AppsAsyncLoader.PackageInfo app = createPackage(PACKAGE_NAME, 199, 200);

        assertThat(AppsAsyncLoader.FILTER_USAGE_STATS.filterApp(app)).isTrue();
    }

    @Test
    public void test_noThresholdFilter_oldUnusedApp_isValid() {
        AppsAsyncLoader.PackageInfo app = createPackage(PACKAGE_NAME, 199, 200);

        assertThat(AppsAsyncLoader.FILTER_NO_THRESHOLD.filterApp(app)).isTrue();
    }

    @Test
    public void test_systemApps_areInvalid() {
        AppsAsyncLoader.PackageInfo app = createPackage(PACKAGE_NAME, 200, 200);
        app.flags = ApplicationInfo.FLAG_SYSTEM;

        assertThat(AppsAsyncLoader.FILTER_USAGE_STATS.filterApp(app)).isFalse();
    }

    @Test
    public void test_noThresholdFilter_systemApps_areInvalid() {
        AppsAsyncLoader.PackageInfo app = createPackage(PACKAGE_NAME, 200, 200);
        app.flags = ApplicationInfo.FLAG_SYSTEM;

        assertThat(AppsAsyncLoader.FILTER_NO_THRESHOLD.filterApp(app)).isFalse();
    }

    @Test
    public void test_persistentProcessApps_areInvalid() {
        AppsAsyncLoader.PackageInfo app = createPackage(PACKAGE_NAME, 200, 200);
        app.flags = ApplicationInfo.FLAG_PERSISTENT;

        assertThat(AppsAsyncLoader.FILTER_USAGE_STATS.filterApp(app)).isFalse();
    }

    @Test
    public void test_noThresholdFilter_persistentProcessApps_areInvalid() {
        AppsAsyncLoader.PackageInfo app = createPackage(PACKAGE_NAME, 200, 200);
        app.flags = ApplicationInfo.FLAG_PERSISTENT;

        assertThat(AppsAsyncLoader.FILTER_NO_THRESHOLD.filterApp(app)).isFalse();
    }

    @Test
    public void test_multipleApps_processCorrectly() {
        mLoader.mFilter = AppsAsyncLoader.FILTER_USAGE_STATS;
        mLoader.mFilter.init();
        AppsAsyncLoader.PackageInfo clearable =
                createPackage(
                        PACKAGE_CLEARABLE,
                        TimeUnit.DAYS.toMillis(800),
                        TimeUnit.DAYS.toMillis(800));
        registerLastUse(PACKAGE_CLEARABLE, TimeUnit.DAYS.toMillis(800));
        registerApp(clearable, 0, TimeUnit.DAYS.toMillis(800));
        AppsAsyncLoader.PackageInfo tooNewtoDelete =
                createPackage(
                        PACKAGE_TOO_NEW_TO_DELETE,
                        TimeUnit.DAYS.toMillis(1000),
                        TimeUnit.DAYS.toMillis(1000));
        registerLastUse(PACKAGE_TOO_NEW_TO_DELETE, TimeUnit.DAYS.toMillis(1000));
        registerApp(tooNewtoDelete, 1, TimeUnit.DAYS.toMillis(1000));
        AppsAsyncLoader.PackageInfo systemApp =
                createPackage(
                        PACKAGE_SYSTEM, TimeUnit.DAYS.toMillis(800), TimeUnit.DAYS.toMillis(800));
        registerLastUse(PACKAGE_SYSTEM, TimeUnit.DAYS.toMillis(800));
        systemApp.flags = ApplicationInfo.FLAG_SYSTEM;
        registerApp(systemApp, 2, TimeUnit.DAYS.toMillis(800));
        AppsAsyncLoader.PackageInfo persistentApp =
                createPackage(
                        PACKAGE_NAME, TimeUnit.DAYS.toMillis(800), TimeUnit.DAYS.toMillis(800));
        registerLastUse(PACKAGE_NAME, TimeUnit.DAYS.toMillis(800));
        persistentApp.flags = ApplicationInfo.FLAG_PERSISTENT;
        registerApp(persistentApp, 3, TimeUnit.DAYS.toMillis(800));
        List<AppsAsyncLoader.PackageInfo> infos = mLoader.loadInBackground();

        assertThat(containsPackage(infos, PACKAGE_CLEARABLE)).isTrue();
        assertThat(containsPackage(infos, PACKAGE_TOO_NEW_TO_DELETE)).isFalse();
        assertThat(containsPackage(infos, PACKAGE_NAME)).isFalse();
        assertThat(containsPackage(infos, PACKAGE_SYSTEM)).isFalse();
    }

    @Test
    public void test_noThresholdFilter_ignoresUsageForFiltering() {
        mLoader.mFilter = AppsAsyncLoader.FILTER_NO_THRESHOLD;
        mLoader.mFilter.init();
        AppsAsyncLoader.PackageInfo clearable =
                createPackage(
                        PACKAGE_CLEARABLE,
                        TimeUnit.DAYS.toMillis(800),
                        TimeUnit.DAYS.toMillis(800));
        registerLastUse(PACKAGE_CLEARABLE, TimeUnit.DAYS.toMillis(800));
        registerApp(clearable, 0, TimeUnit.DAYS.toMillis(800));
        AppsAsyncLoader.PackageInfo tooNewtoDelete =
                createPackage(
                        PACKAGE_TOO_NEW_TO_DELETE,
                        TimeUnit.DAYS.toMillis(1000),
                        TimeUnit.DAYS.toMillis(1000));
        registerLastUse(PACKAGE_TOO_NEW_TO_DELETE, TimeUnit.DAYS.toMillis(1000));
        registerApp(tooNewtoDelete, 1, TimeUnit.DAYS.toMillis(1000));
        AppsAsyncLoader.PackageInfo systemApp =
                createPackage(
                        PACKAGE_SYSTEM, TimeUnit.DAYS.toMillis(800), TimeUnit.DAYS.toMillis(800));
        registerLastUse(PACKAGE_SYSTEM, TimeUnit.DAYS.toMillis(800));
        systemApp.flags = ApplicationInfo.FLAG_SYSTEM;
        registerApp(systemApp, 2, TimeUnit.DAYS.toMillis(800));
        AppsAsyncLoader.PackageInfo persistentApp =
                createPackage(
                        PACKAGE_NAME, TimeUnit.DAYS.toMillis(800), TimeUnit.DAYS.toMillis(800));
        registerLastUse(PACKAGE_NAME, TimeUnit.DAYS.toMillis(800));
        persistentApp.flags = ApplicationInfo.FLAG_PERSISTENT;
        registerApp(persistentApp, 3, TimeUnit.DAYS.toMillis(800));
        List<AppsAsyncLoader.PackageInfo> infos = mLoader.loadInBackground();

        assertThat(containsPackage(infos, PACKAGE_CLEARABLE)).isTrue();
        assertThat(containsPackage(infos, PACKAGE_TOO_NEW_TO_DELETE)).isTrue();
        assertThat(containsPackage(infos, PACKAGE_NAME)).isFalse();
        assertThat(containsPackage(infos, PACKAGE_SYSTEM)).isFalse();
    }

    @Test
    public void testAppUsedOverOneYearAgoIsValid() {
        AppsAsyncLoader.PackageInfo app = createPackage(PACKAGE_NAME, 1000 - 366, 400);

        assertThat(AppsAsyncLoader.FILTER_USAGE_STATS.filterApp(app)).isTrue();
    }

    @Test
    public void test_getGreaterUsageStats_primaryIsNull() {
        UsageStats secondary = mock(UsageStats.class);
        when(secondary.getLastTimeUsed()).thenReturn(1000L);
        assertThat(mLoader.getGreaterUsageStats(PACKAGE_NAME, null, secondary))
                .isEqualTo(secondary);
    }

    @Test
    public void test_getGreaterUsageStats_secondaryIsNull() {
        UsageStats primary = mock(UsageStats.class);
        when(primary.getLastTimeUsed()).thenReturn(1000L);
        assertThat(mLoader.getGreaterUsageStats(PACKAGE_NAME, primary, null)).isEqualTo(primary);
    }

    @Test
    public void test_getGreaterUsageStats_primaryIsGreater() {
        UsageStats primary = mock(UsageStats.class);
        when(primary.getLastTimeUsed()).thenReturn(1000L);
        UsageStats secondary = mock(UsageStats.class);
        when(secondary.getLastTimeUsed()).thenReturn(900L);
        assertThat(mLoader.getGreaterUsageStats(PACKAGE_NAME, primary, secondary))
                .isEqualTo(primary);
    }

    @Test
    public void test_getGreaterUsageStats_secondaryIsGreater() {
        UsageStats primary = mock(UsageStats.class);
        when(primary.getLastTimeUsed()).thenReturn(900L);
        UsageStats secondary = mock(UsageStats.class);
        when(secondary.getLastTimeUsed()).thenReturn(1000L);
        assertThat(mLoader.getGreaterUsageStats(PACKAGE_NAME, primary, secondary))
                .isEqualTo(secondary);
    }

    @Test
    public void test_defaultLauncherDisallowedFromDeletion() {
        mLoader.mFilter = AppsAsyncLoader.FILTER_USAGE_STATS;
        mLoader.mFilter.init();
        AppsAsyncLoader.PackageInfo defaultLauncher =
                createPackage(
                        PACKAGE_DEFAULT_LAUNCHER,
                        TimeUnit.DAYS.toMillis(800),
                        TimeUnit.DAYS.toMillis(800));
        registerLastUse(PACKAGE_DEFAULT_LAUNCHER, TimeUnit.DAYS.toMillis(800));
        registerApp(defaultLauncher, 0, TimeUnit.DAYS.toMillis(800));
        List<AppsAsyncLoader.PackageInfo> infos = mLoader.loadInBackground();

        assertThat(containsPackage(infos, PACKAGE_DEFAULT_LAUNCHER)).isFalse();
    }

    private AppsAsyncLoader.PackageInfo createPackage(
            String packageName, long lastUse, long installTime) {
        AppsAsyncLoader.PackageInfo app =
                new AppsAsyncLoader.PackageInfo.Builder()
                        .setDaysSinceLastUse(lastUse)
                        .setDaysSinceFirstInstall(installTime)
                        .setPackageName(packageName)
                        .setLabel("")
                        .build();
        app.packageName = packageName;
        app.label = packageName;
        return app;
    }

    private void registerApp(AppsAsyncLoader.PackageInfo info, int uid, long installed) {
        ApplicationInfo applicationInfo = mock(ApplicationInfo.class);
        applicationInfo.uid = uid;
        applicationInfo.packageName = info.packageName;
        applicationInfo.flags = info.flags;
        mInfo.add(applicationInfo);
        android.content.pm.PackageInfo packageInfo = mock(android.content.pm.PackageInfo.class);
        packageInfo.firstInstallTime = installed;
        try {
            when(mPackageManager.getPackageInfo(eq(info.packageName), anyInt()))
                    .thenReturn(packageInfo);
            when(applicationInfo.loadLabel(eq(mPackageManager)))
                    .thenReturn(applicationInfo.packageName);
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }
    }

    private void registerLastUse(String packageName, long time) {
        UsageStats usageStats = mock(UsageStats.class);
        when(usageStats.getPackageName()).thenReturn(packageName);
        when(usageStats.getLastTimeUsed()).thenReturn(time);
        mUsageStats.put(packageName, usageStats);
    }

    private boolean containsPackage(List<PackageInfo> infos, String expectedPackage) {
        for (PackageInfo info : infos) {
            if (TextUtils.equals(info.packageName, expectedPackage)) {
                return true;
            }
        }
        return false;
    }
}
