/*
 * 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.settingslib.users;

import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.nullable;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageDeleteObserver;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.inputmethod.InputMethodInfo;

import com.android.settingslib.BaseTest;

import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

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

@SmallTest
public class AppRestrictionsHelperTest extends BaseTest {
    private @Mock Context mContext;
    private @Mock PackageManager mPm;
    private @Mock IPackageManager mIpm;
    private @Mock UserManager mUm;

    private TestInjector mInjector;
    private UserHandle mTestUser = UserHandle.of(1111);
    private AppRestrictionsHelper mHelper;

    private ArrayList<String> mInstalledApps;
    private ArrayList<ApplicationInfo> mInstalledAppInfos;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        MockitoAnnotations.initMocks(this);

        mInjector = new TestInjector();
        final UserInfo user = new UserInfo(
                mTestUser.getIdentifier(), "test_user", UserInfo.FLAG_RESTRICTED);
        when(mUm.getUserInfo(mTestUser.getIdentifier())).thenReturn(user);
        mHelper = new AppRestrictionsHelper(mInjector);
        mInstalledApps = new ArrayList<>();
        mInstalledAppInfos = new ArrayList<>();
    }

    public void testFetchAndMergeApps() throws Exception {
        addSystemAppsWithRequiredAccounts("sys.app0");
        addsystemImes(new String[] {"sys.app1", "sys.app2"},
                new String[] {"sys.app3", "sys.app4", "sys.app5"});
        addSystemAppsForIntent(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER),
                "sys.app1", "sys.app4", "sys.app6");
        addSystemAppsForIntent(new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE),
                "sys.app2", "sys.app5", "sys.app7");
        addDownloadedApps("app1", "app2");
        when(mPm.getInstalledApplications(anyInt())).thenReturn(mInstalledAppInfos);

        mHelper.fetchAndMergeApps();

        final ArrayList<String> notExpectedInVisibleApps = new ArrayList<>();
        // System apps that require an account and doesn't see restricted account are
        // not part of visibleApps.
        notExpectedInVisibleApps.add("sys.app0");
        // Default system IMEs are not part of visibleApps.
        notExpectedInVisibleApps.add("sys.app1");
        notExpectedInVisibleApps.add("sys.app2");

        final ArrayList<String> expectedInVisibleApps = new ArrayList<>();
        expectedInVisibleApps.add("sys.app4");
        expectedInVisibleApps.add("sys.app5");
        expectedInVisibleApps.add("sys.app6");
        expectedInVisibleApps.add("sys.app7");
        expectedInVisibleApps.add("app1");
        expectedInVisibleApps.add("app2");

        for (AppRestrictionsHelper.SelectableAppInfo info : mHelper.getVisibleApps()) {
            if (expectedInVisibleApps.contains(info.packageName)) {
                expectedInVisibleApps.remove(info.packageName);
            } else if (notExpectedInVisibleApps.contains(info.packageName)) {
                fail("Package: " + info.packageName + " should not be included in visibleApps");
            } else {
                fail("Unknown package: " + info.packageName);
            }
        }
        assertEquals("Some expected apps are not inclued in visibleApps: " + expectedInVisibleApps,
                0, expectedInVisibleApps.size());

        assertFalse("System apps that require an account and doesn't see restricted account "
                + "should be marked for removal", mHelper.isPackageSelected("sys.app0"));
    }

    public void testApplyUserAppsStates() throws Exception {
        final int testUserId = mTestUser.getIdentifier();
        mHelper.setPackageSelected("app1", true);

        mHelper.setPackageSelected("app2", true);
        ApplicationInfo info = new ApplicationInfo();
        info.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
        info.flags |= ApplicationInfo.FLAG_INSTALLED;
        when(mIpm.getApplicationInfo(eq("app2"), anyInt(), eq(testUserId)))
                .thenReturn(info);

        mHelper.setPackageSelected("app3", false);
        info = new ApplicationInfo();
        when(mIpm.getApplicationInfo(eq("app3"), anyInt(), eq(testUserId)))
                .thenReturn(info);

        AppRestrictionsHelper.OnDisableUiForPackageListener mockListener =
                mock(AppRestrictionsHelper.OnDisableUiForPackageListener.class);
        mHelper.applyUserAppsStates(mockListener);

        verify(mIpm, times(1)).installExistingPackageAsUser("app1", testUserId,
                PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS,
                PackageManager.INSTALL_REASON_UNKNOWN, null);
        verify(mIpm, times(1)).setApplicationHiddenSettingAsUser("app2", false, testUserId);
        verify(mockListener).onDisableUiForPackage("app2");
        verify(mPm, times(1)).deletePackageAsUser(eq("app3"),
                nullable(IPackageDeleteObserver.class), anyInt(), eq(mTestUser.getIdentifier()));
    }

    private void addsystemImes(String[] defaultImes, String[] otherImes) throws
            PackageManager.NameNotFoundException, RemoteException {
        final ArrayList<InputMethodInfo> inputMethods = new ArrayList<>();
        for (String pkg : defaultImes) {
            final ResolveInfo ri = createResolveInfoForSystemApp(pkg);
            final InputMethodInfo inputMethodInfo = new InputMethodInfo(
                    ri, false, null, null, 0, true, true, false);
            inputMethods.add(inputMethodInfo);
            addInstalledApp(ri);
        }
        for (String pkg : otherImes) {
            final ResolveInfo ri = createResolveInfoForSystemApp(pkg);
            final InputMethodInfo inputMethodInfo = new InputMethodInfo(
                    ri, false, null, null, 0, false, true, false);
            inputMethods.add(inputMethodInfo);
            addInstalledApp(ri);
        }

        mInjector.setInputMethodList(inputMethods);
    }

    private void addSystemAppsForIntent(Intent intent, String... packages) throws Exception {
        List<ResolveInfo> resolveInfos = new ArrayList<>();
        for (String pkg : packages) {
            final ResolveInfo ri = createResolveInfoForSystemApp(pkg);
            resolveInfos.add(ri);
            addInstalledApp(ri);
        }
        when(mPm.queryIntentActivities(argThat(new IntentMatcher(intent)), anyInt()))
                .thenReturn(resolveInfos);
    }

    private void addSystemAppsWithRequiredAccounts(String... packages) throws Exception {
        for (String pkg : packages) {
            final ResolveInfo ri = createResolveInfoForSystemApp(pkg);
            final PackageInfo packageInfo = new PackageInfo();
            packageInfo.applicationInfo = ri.activityInfo.applicationInfo;
            packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED;
            packageInfo.requiredAccountType = "account";
            packageInfo.restrictedAccountType = null;
            mInstalledAppInfos.add(packageInfo.applicationInfo);
            when(mPm.getPackageInfo(eq(pkg), anyInt())).thenReturn(packageInfo);
        }
    }

    private void addDownloadedApps(String... packages) throws Exception {
        for (String pkg : packages) {
            final ResolveInfo ri = createResolveInfo(pkg);
            addInstalledApp(ri);
        }
    }

    private void addInstalledApp(ResolveInfo ri) throws PackageManager.NameNotFoundException {
        final String pkgName = ri.activityInfo.packageName;
        if (mInstalledApps.contains(pkgName)) {
            return;
        }
        final PackageInfo packageInfo = new PackageInfo();
        packageInfo.applicationInfo = ri.activityInfo.applicationInfo;
        packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED;
        mInstalledAppInfos.add(packageInfo.applicationInfo);
        when(mPm.getPackageInfo(eq(pkgName), anyInt())).thenReturn(packageInfo);
    }

    private ResolveInfo createResolveInfoForSystemApp(String packageName) {
        final ResolveInfo ri = createResolveInfo(packageName);
        ri.activityInfo.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
        ri.serviceInfo.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
        return ri;
    }

    private ResolveInfo createResolveInfo(String packageName) {
        final ResolveInfo ri = new ResolveInfo();
        final ApplicationInfo applicationInfo = new ApplicationInfo();
        applicationInfo.packageName = packageName;
        final ActivityInfo activityInfo = new ActivityInfo();
        activityInfo.applicationInfo = applicationInfo;
        activityInfo.packageName = packageName;
        activityInfo.name = "";
        ri.activityInfo = activityInfo;
        final ServiceInfo serviceInfo = new ServiceInfo();
        serviceInfo.applicationInfo = applicationInfo;
        serviceInfo.packageName = packageName;
        serviceInfo.name = "";
        ri.serviceInfo = serviceInfo;
        return ri;
    }

    private class IntentMatcher implements ArgumentMatcher<Intent> {
        private final Intent mIntent;

        IntentMatcher(Intent intent) {
            mIntent = intent;
        }

        @Override
        public boolean matches(Intent argument) {
            return argument != null && argument.filterEquals(mIntent);
        }

        @Override
        public String toString() {
            return "Expected: " + mIntent;
        }
    }

    private class TestInjector extends AppRestrictionsHelper.Injector {
        List<InputMethodInfo> mImis;

        TestInjector() {
            super(mContext, mTestUser);
        }

        @Override
        Context getContext() {
            return mContext;
        }

        @Override
        UserHandle getUser() {
            return mTestUser;
        }

        @Override
        PackageManager getPackageManager() {
            return mPm;
        }

        @Override
        IPackageManager getIPackageManager() {
            return mIpm;
        }

        @Override
        UserManager getUserManager() {
            return mUm;
        }

        @Override
        List<InputMethodInfo> getInputMethodList() {
            return mImis;
        }

        void setInputMethodList(List<InputMethodInfo> imis) {
            mImis = imis;
        }
    }
}
