/*
 * Copyright (C) 2017 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 static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.storage.StorageManager;
import androidx.preference.PreferenceScreen;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;

@RunWith(RobolectricTestRunner.class)
public class DeletionHelperSettingsTest {
    private static final String PACKAGE_NAME = "com.package";
    private Context mContext;
    private PackageManager mPackageManager;

    @Before
    public void setUp() {
        mContext = spy(RuntimeEnvironment.application);
        mPackageManager = spy(mContext.getPackageManager());
    }

    @Test
    public void nullAppHasNoGaugeTitle() {
        Intent intent = new Intent(StorageManager.ACTION_MANAGE_STORAGE);
        intent.putExtra(StorageManager.EXTRA_REQUESTED_BYTES, 100L);
        assertThat(DeletionHelperSettings.getGaugeString(mContext, intent, PACKAGE_NAME)).isNull();
    }

    @Test
    public void realAppHasGaugeTitle() throws Exception {
        mPackageManager = spy(mContext.getPackageManager());
        when(mContext.getPackageManager()).thenReturn(mPackageManager);
        ApplicationInfo info = mock(ApplicationInfo.class);
        when(info.loadLabel(any(PackageManager.class))).thenReturn("My Package");
        doReturn(info).when(mPackageManager).getApplicationInfo(anyString(), anyInt());
        Intent intent = new Intent(StorageManager.ACTION_MANAGE_STORAGE);
        intent.putExtra(StorageManager.EXTRA_REQUESTED_BYTES, 100L);
        assertThat(DeletionHelperSettings.getGaugeString(mContext, intent, PACKAGE_NAME))
                .isNotNull();
    }

    @Test
    public void downloadsNotDeletedInNoThresholdMode() {
        DeletionHelperSettings settings =
                spy(DeletionHelperSettings.newInstance(AppsAsyncLoader.NO_THRESHOLD));
        PreferenceScreen preferenceScreen = mock(PreferenceScreen.class);
        doReturn(preferenceScreen).when(settings).getPreferenceScreen();
        DownloadsDeletionType downloadsDeletionType = mock(DownloadsDeletionType.class);
        settings.setDownloadsDeletionType(downloadsDeletionType);

        settings.setupEmptyState();
        settings.clearData();

        verify(downloadsDeletionType, never()).clearFreeableData(any());
    }

    @Test
    public void onFreeableChangeChecksForNull() {
        DeletionHelperSettings settings =
                DeletionHelperSettings.newInstance(AppsAsyncLoader.NO_THRESHOLD);
        AppDeletionType appBackend = mock(AppDeletionType.class);
        when(appBackend.isEmpty()).thenReturn(true);
        settings.mAppBackend = appBackend;

        settings.onFreeableChanged(0, 0L);
    }

    @Test
    public void requestingSpecificBytesToClearSetsOkResultCodeOnSufficientClear() {
        DeletionHelperSettings settings =
                spy(DeletionHelperSettings.newInstance(AppsAsyncLoader.NORMAL_THRESHOLD));
        settings.mBytesToFree = 1000L;
        PreferenceScreen preferenceScreen = mock(PreferenceScreen.class);
        doReturn(preferenceScreen).when(settings).getPreferenceScreen();
        // The deletion helper will not delete items which aren't viewable on the UI -- this
        // will trick it into thinking there's an UI.
        settings.mDownloadsPreference = mock(DownloadsDeletionPreferenceGroup.class);
        DownloadsDeletionType downloadsDeletionType = mock(DownloadsDeletionType.class);
        settings.setDownloadsDeletionType(downloadsDeletionType);
        when(downloadsDeletionType.getFreeableBytes(any(Boolean.class))).thenReturn(1001L);

        settings.clearData();

        assertThat(settings.getResultCode()).isEqualTo(Activity.RESULT_OK);
    }

    @Test
    public void requestingSpecificBytesToClearSetsNegativeResultCodeOnSufficientClear() {
        DeletionHelperSettings settings =
                spy(DeletionHelperSettings.newInstance(AppsAsyncLoader.NORMAL_THRESHOLD));
        settings.mBytesToFree = 1000L;
        PreferenceScreen preferenceScreen = mock(PreferenceScreen.class);
        doReturn(preferenceScreen).when(settings).getPreferenceScreen();
        // The deletion helper will not delete items which aren't viewable on the UI -- this
        // will trick it into thinking there's an UI
        settings.mDownloadsPreference = mock(DownloadsDeletionPreferenceGroup.class);
        DownloadsDeletionType downloadsDeletionType = mock(DownloadsDeletionType.class);
        settings.setDownloadsDeletionType(downloadsDeletionType);
        when(downloadsDeletionType.getFreeableBytes(any(Boolean.class))).thenReturn(999L);

        settings.clearData();

        assertThat(settings.getResultCode()).isEqualTo(Activity.RESULT_CANCELED);
    }

    @Test
    public void requestingSpecificBytesToClearSetsNegativeResultCodeOnNoClear() {
        DeletionHelperSettings settings =
                spy(DeletionHelperSettings.newInstance(AppsAsyncLoader.NORMAL_THRESHOLD));
        settings.mBytesToFree = 1000L;
        PreferenceScreen preferenceScreen = mock(PreferenceScreen.class);
        doReturn(preferenceScreen).when(settings).getPreferenceScreen();
        // The deletion helper will not delete items which aren't viewable on the UI -- this
        // will trick it into thinking there's an UI.
        settings.mDownloadsPreference = mock(DownloadsDeletionPreferenceGroup.class);
        DownloadsDeletionType downloadsDeletionType = mock(DownloadsDeletionType.class);
        settings.setDownloadsDeletionType(downloadsDeletionType);
        when(downloadsDeletionType.getFreeableBytes(any(Boolean.class))).thenReturn(999L);

        assertThat(settings.getResultCode()).isEqualTo(Activity.RESULT_CANCELED);
    }
}
