/*
 * 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.settings.applications;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;

import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.os.Build;
import android.os.UserHandle;
import android.os.UserManager;

import com.android.settings.testutils.ApplicationTestUtils;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowDefaultDialerManager;
import com.android.settings.testutils.shadow.ShadowSmsApplication;
import com.android.settingslib.wrapper.PackageManagerWrapper;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.ReflectionHelpers;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

/**
 * Tests for {@link ApplicationFeatureProviderImpl}.
 */
@RunWith(SettingsRobolectricTestRunner.class)
public final class ApplicationFeatureProviderImplTest {

    private final int MAIN_USER_ID = 0;
    private final int MANAGED_PROFILE_ID = 10;

    private final int PER_USER_UID_RANGE = 100000;
    private final int APP_1_UID = MAIN_USER_ID * PER_USER_UID_RANGE + 1;
    private final int APP_2_UID = MANAGED_PROFILE_ID * PER_USER_UID_RANGE + 1;

    private final String APP_1 = "app1";
    private final String APP_2 = "app2";

    private final String PERMISSION = "some.permission";

    @Mock
    private UserManager mUserManager;
    @Mock
    private Context mContext;
    @Mock
    private PackageManagerWrapper mPackageManager;
    @Mock
    private IPackageManager mPackageManagerService;
    @Mock
    private DevicePolicyManager mDevicePolicyManager;

    private ApplicationFeatureProvider mProvider;

    private int mAppCount = -1;
    private List<UserAppInfo> mAppList = null;

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

        when(mContext.getApplicationContext()).thenReturn(mContext);
        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);

        mProvider = new ApplicationFeatureProviderImpl(mContext, mPackageManager,
                mPackageManagerService, mDevicePolicyManager);
    }

    private void verifyCalculateNumberOfPolicyInstalledApps(boolean async) {
        setUpUsersAndInstalledApps();

        when(mPackageManager.getInstallReason(APP_1, new UserHandle(MAIN_USER_ID)))
                .thenReturn(PackageManager.INSTALL_REASON_UNKNOWN);
        when(mPackageManager.getInstallReason(APP_2, new UserHandle(MANAGED_PROFILE_ID)))
                .thenReturn(PackageManager.INSTALL_REASON_POLICY);

        mAppCount = -1;
        mProvider.calculateNumberOfPolicyInstalledApps(async,
                (num) -> mAppCount = num);
        if (async) {
            ShadowApplication.runBackgroundTasks();
        }
        assertThat(mAppCount).isEqualTo(1);
    }

    @Test
    public void testListPolicyInstalledApps() {
        setUpUsersAndInstalledApps();

        when(mPackageManager.getInstallReason(APP_1, new UserHandle(MAIN_USER_ID)))
                .thenReturn(PackageManager.INSTALL_REASON_UNKNOWN);
        when(mPackageManager.getInstallReason(APP_2, new UserHandle(MANAGED_PROFILE_ID)))
                .thenReturn(PackageManager.INSTALL_REASON_POLICY);

        mAppList = null;
        mProvider.listPolicyInstalledApps((list) -> mAppList = list);
        assertThat(mAppList).isNotNull();
        assertThat(mAppList.size()).isEqualTo(1);
        assertThat(mAppList.get(0).appInfo.packageName).isEqualTo(APP_2);
    }

    @Test
    public void testCalculateNumberOfInstalledAppsSync() {
        verifyCalculateNumberOfPolicyInstalledApps(false /* async */);
    }

    @Test
    public void testCalculateNumberOfInstalledAppsAsync() {
        verifyCalculateNumberOfPolicyInstalledApps(true /* async */);
    }

    private void verifyCalculateNumberOfAppsWithAdminGrantedPermissions(boolean async)
            throws Exception {
        setUpUsersAndInstalledApps();

        when(mDevicePolicyManager.getPermissionGrantState(null, APP_1, PERMISSION))
                .thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
        when(mDevicePolicyManager.getPermissionGrantState(null, APP_2, PERMISSION))
                .thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
        when(mPackageManagerService.checkUidPermission(PERMISSION, APP_1_UID))
                .thenReturn(PackageManager.PERMISSION_DENIED);
        when(mPackageManagerService.checkUidPermission(PERMISSION, APP_2_UID))
                .thenReturn(PackageManager.PERMISSION_GRANTED);
        when(mPackageManager.getInstallReason(APP_1, new UserHandle(MAIN_USER_ID)))
                .thenReturn(PackageManager.INSTALL_REASON_UNKNOWN);
        when(mPackageManager.getInstallReason(APP_2, new UserHandle(MANAGED_PROFILE_ID)))
                .thenReturn(PackageManager.INSTALL_REASON_POLICY);

        mAppCount = -1;
        mProvider.calculateNumberOfAppsWithAdminGrantedPermissions(new String[] {PERMISSION}, async,
                (num) -> mAppCount = num);
        if (async) {
            ShadowApplication.runBackgroundTasks();
        }
        assertThat(mAppCount).isEqualTo(2);
    }

    @Test
    public void testCalculateNumberOfAppsWithAdminGrantedPermissionsSync() throws Exception {
        verifyCalculateNumberOfAppsWithAdminGrantedPermissions(false /* async */);
    }

    @Test
    public void testCalculateNumberOfAppsWithAdminGrantedPermissionsAsync() throws Exception {
        verifyCalculateNumberOfAppsWithAdminGrantedPermissions(true /* async */);
    }

    @Test
    public void testListAppsWithAdminGrantedPermissions()
            throws Exception {
        setUpUsersAndInstalledApps();

        when(mDevicePolicyManager.getPermissionGrantState(null, APP_1, PERMISSION))
                .thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
        when(mDevicePolicyManager.getPermissionGrantState(null, APP_2, PERMISSION))
                .thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
        when(mPackageManagerService.checkUidPermission(PERMISSION, APP_1_UID))
                .thenReturn(PackageManager.PERMISSION_DENIED);
        when(mPackageManagerService.checkUidPermission(PERMISSION, APP_2_UID))
                .thenReturn(PackageManager.PERMISSION_GRANTED);
        when(mPackageManager.getInstallReason(APP_1, new UserHandle(MAIN_USER_ID)))
                .thenReturn(PackageManager.INSTALL_REASON_UNKNOWN);
        when(mPackageManager.getInstallReason(APP_2, new UserHandle(MANAGED_PROFILE_ID)))
                .thenReturn(PackageManager.INSTALL_REASON_POLICY);

        mAppList = null;
        mProvider.listAppsWithAdminGrantedPermissions(new String[] {PERMISSION},
                (list) -> mAppList = list);
        assertThat(mAppList).isNotNull();
        assertThat(mAppList.size()).isEqualTo(2);
        assertThat(Arrays.asList(mAppList.get(0).appInfo.packageName,
                mAppList.get(1).appInfo.packageName).containsAll(Arrays.asList(APP_1, APP_2)))
                .isTrue();
    }

    @Test
    public void testFindPersistentPreferredActivities() throws Exception {
        final UserInfo mainUser = new UserInfo(MAIN_USER_ID, "main", UserInfo.FLAG_ADMIN);
        final UserInfo managedUser = new UserInfo(MANAGED_PROFILE_ID, "managed",
                UserInfo.FLAG_MANAGED_PROFILE);

        when(mUserManager.getUserProfiles()).thenReturn(Arrays.asList(new UserHandle(MAIN_USER_ID),
                new UserHandle(MANAGED_PROFILE_ID)));
        when(mUserManager.getUserInfo(MAIN_USER_ID)).thenReturn(mainUser);
        when(mUserManager.getUserInfo(MANAGED_PROFILE_ID)).thenReturn(managedUser);

        final Intent viewIntent = new Intent(Intent.ACTION_VIEW);
        final Intent editIntent = new Intent(Intent.ACTION_EDIT);
        final Intent sendIntent = new Intent(Intent.ACTION_SEND);

        final ResolveInfo app1 = createResolveInfo(APP_1);
        final ResolveInfo app2 = createResolveInfo(APP_2);
        when(mPackageManagerService.findPersistentPreferredActivity(viewIntent, MAIN_USER_ID))
                .thenReturn(app1);
        when(mPackageManagerService.findPersistentPreferredActivity(viewIntent, MANAGED_PROFILE_ID))
                .thenReturn(app1);
        when(mPackageManagerService.findPersistentPreferredActivity(editIntent, MAIN_USER_ID))
                .thenReturn(null);
        when(mPackageManagerService.findPersistentPreferredActivity(editIntent, MANAGED_PROFILE_ID))
                .thenReturn(app2);
        when(mPackageManagerService.findPersistentPreferredActivity(sendIntent, MAIN_USER_ID))
                .thenReturn(app1);
        when(mPackageManagerService.findPersistentPreferredActivity(sendIntent, MANAGED_PROFILE_ID))
                .thenReturn(null);

        final List<UserAppInfo> expectedMainUserActivities = new ArrayList<>();
        expectedMainUserActivities.add(new UserAppInfo(mainUser,
                new ApplicationInfo(app1.activityInfo.applicationInfo)));
        final List<UserAppInfo> expectedManagedUserActivities = new ArrayList<>();
        expectedManagedUserActivities.add(new UserAppInfo(managedUser,
                new ApplicationInfo(app1.activityInfo.applicationInfo)));
        expectedManagedUserActivities.add(new UserAppInfo(managedUser,
                new ApplicationInfo(app2.activityInfo.applicationInfo)));

        assertThat(mProvider.findPersistentPreferredActivities(MAIN_USER_ID,
                new Intent[] {viewIntent, editIntent, sendIntent}))
                .isEqualTo(expectedMainUserActivities);
        assertThat(mProvider.findPersistentPreferredActivities(MANAGED_PROFILE_ID,
                new Intent[] {viewIntent, editIntent, sendIntent}))
                .isEqualTo(expectedManagedUserActivities);
    }

    @Test
    @Config(shadows = {ShadowSmsApplication.class, ShadowDefaultDialerManager.class})
    public void getKeepEnabledPackages_shouldContainDefaultPhoneAndSms() {
        final String testDialer = "com.android.test.defaultdialer";
        final String testSms = "com.android.test.defaultsms";
        ShadowSmsApplication.setDefaultSmsApplication(new ComponentName(testSms, "receiver"));
        ShadowDefaultDialerManager.setDefaultDialerApplication(testDialer);
        ReflectionHelpers.setField(mProvider, "mContext", RuntimeEnvironment.application);

        final Set<String> keepEnabledPackages = mProvider.getKeepEnabledPackages();

        final List<String> expectedPackages = Arrays.asList(testDialer, testSms);
        assertThat(keepEnabledPackages).containsExactlyElementsIn(expectedPackages);
    }

    private void setUpUsersAndInstalledApps() {
        when(mUserManager.getProfiles(UserHandle.myUserId())).thenReturn(Arrays.asList(
                new UserInfo(MAIN_USER_ID, "main", UserInfo.FLAG_ADMIN),
                new UserInfo(MANAGED_PROFILE_ID, "managed profile", 0)));

        when(mPackageManager.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS
                        | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS
                        | PackageManager.MATCH_ANY_USER,
                MAIN_USER_ID)).thenReturn(Arrays.asList(
                ApplicationTestUtils.buildInfo(APP_1_UID, APP_1, 0 /* flags */,
                        Build.VERSION_CODES.M)));
        when(mPackageManager.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS
                        | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
                MANAGED_PROFILE_ID)).thenReturn(Arrays.asList(
                ApplicationTestUtils.buildInfo(APP_2_UID, APP_2, 0 /* flags */,
                        Build.VERSION_CODES.LOLLIPOP)));
    }

    private ResolveInfo createResolveInfo(String packageName) {
        final ApplicationInfo applicationInfo = new ApplicationInfo();
        applicationInfo.packageName = packageName;
        final ActivityInfo activityInfo = new ActivityInfo();
        activityInfo.packageName = packageName;
        activityInfo.applicationInfo = applicationInfo;
        final ResolveInfo resolveInfo = new ResolveInfo();
        resolveInfo.activityInfo = activityInfo;
        return resolveInfo;
    }
}
