/*
 * Copyright (C) 2021 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.bedstead.nene.packages;

import static android.os.Build.VERSION_CODES.S;

import static com.google.common.truth.Truth.assertThat;

import static org.junit.Assume.assumeTrue;
import static org.testng.Assert.assertThrows;

import com.android.bedstead.harrier.BedsteadJUnit4;
import com.android.bedstead.harrier.DeviceState;
import com.android.bedstead.harrier.annotations.EnsureHasSecondaryUser;
import com.android.bedstead.harrier.annotations.EnsureHasWorkProfile;
import com.android.bedstead.harrier.annotations.RequireRunOnPrimaryUser;
import com.android.bedstead.harrier.annotations.RequireSdkVersion;
import com.android.bedstead.nene.TestApis;
import com.android.bedstead.nene.exceptions.NeneException;
import com.android.bedstead.nene.users.UserReference;
import com.android.bedstead.nene.utils.Versions;
import com.android.bedstead.testapp.TestApp;
import com.android.bedstead.testapp.TestAppInstance;
import com.android.bedstead.testapp.TestAppProvider;
import com.android.compatibility.common.util.FileUtils;

import org.junit.ClassRule;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

@RunWith(BedsteadJUnit4.class)
public class PackagesTest {
    @ClassRule
    @Rule
    public static final DeviceState sDeviceState = new DeviceState();
    private static final String INPUT_METHODS_FEATURE = "android.software.input_methods";
    private static final String NON_EXISTING_PACKAGE = "com.package.does.not.exist";
    // Controlled by AndroidTest.xml
    private static final String TEST_APP_PACKAGE_NAME =
            "com.android.bedstead.nene.testapps.TestApp1";
    private static final File TEST_APP_APK_FILE = new File("/data/local/tmp/NeneTestApp1.apk");
    private static final File NON_EXISTING_APK_FILE =
            new File("/data/local/tmp/ThisApkDoesNotExist.apk");
    private static final byte[] TEST_APP_BYTES = loadBytes(TEST_APP_APK_FILE);
    private static final TestAppProvider sTestAppProvider = new TestAppProvider();
    private static final TestApp sTestApp = sTestAppProvider.any();
    private final UserReference mUser = TestApis.users().instrumented();
    private final Package mExistingPackage =
            TestApis.packages().find("com.android.providers.telephony");
    private final Package mTestAppReference =
            TestApis.packages().find(TEST_APP_PACKAGE_NAME);
    private final Package mDifferentTestAppReference =
            TestApis.packages().find(NON_EXISTING_PACKAGE);
    private final UserReference mNonExistingUser = TestApis.users().find(99999);
    private final File mApkFile = new File("");

    private static byte[] loadBytes(File file) {
        try (FileInputStream fis = new FileInputStream(file)) {
            return FileUtils.readInputStreamFully(fis);
        } catch (IOException e) {
            throw new AssertionError("Could not read file bytes");
        }
    }

    @Test
    public void construct_constructs() {
        new Packages(); // Doesn't throw any exceptions
    }

    @Test
    public void features_noUserSpecified_containsKnownFeature() {
        assertThat(TestApis.packages().features()).contains(INPUT_METHODS_FEATURE);
    }

    @Test
    public void find_nullPackageName_throwsException() {
        assertThrows(NullPointerException.class, () -> TestApis.packages().find(null));
    }

    @Test
    public void find_existingPackage_returnsPackageReference() {
        assertThat(TestApis.packages().find(mExistingPackage.packageName())).isNotNull();
    }

    @Test
    public void find_nonExistingPackage_returnsPackageReference() {
        assertThat(TestApis.packages().find(NON_EXISTING_PACKAGE)).isNotNull();
    }

    @Test
    public void installedForUser_nullUserReference_throwsException() {
        assertThrows(NullPointerException.class,
                () -> TestApis.packages().installedForUser(/* user= */ null));
    }

    @Test
    public void installedForUser_containsPackageInstalledForUser() {
        Package pkg = TestApis.packages().install(mUser, TEST_APP_APK_FILE);

        try {
            assertThat(TestApis.packages().installedForUser(mUser)).contains(pkg);
        } finally {
            pkg.uninstall(mUser);
        }
    }

    @Test
    public void installedForUser_doesNotContainPackageNotInstalledForUser() {
        Package pkg = TestApis.packages().install(mUser, TEST_APP_APK_FILE);

        try (UserReference otherUser = TestApis.users().createUser().create()) {
            assertThat(TestApis.packages().installedForUser(otherUser))
                    .doesNotContain(pkg);
        } finally {
            pkg.uninstall(mUser);
        }
    }

    @Test
    public void install_nonExistingPackage_throwsException() {
        assertThrows(NeneException.class,
                () -> TestApis.packages().install(mUser, NON_EXISTING_APK_FILE));
    }

    @Test
    public void install_nullUser_throwsException() {
        assertThrows(NullPointerException.class,
                () -> TestApis.packages().install(/* user= */ null, mApkFile));
    }

    @Test
    public void install_byteArray_nullUser_throwsException() {
        assertThrows(NullPointerException.class,
                () -> TestApis.packages().install(/* user= */ null, TEST_APP_BYTES));
    }

    @Test
    public void install_nullApkFile_throwsException() {
        assertThrows(NullPointerException.class,
                () -> TestApis.packages().install(mUser, (File) /* apkFile= */ null));
    }

    @Test
    public void install_nullByteArray_throwsException() {
        assertThrows(NullPointerException.class,
                () -> TestApis.packages().install(mUser, (byte[]) /* apkFile= */ null));
    }

    @Test
    public void install_instrumentedUser_isInstalled() {
        Package pkg =
                TestApis.packages().install(TestApis.users().instrumented(), TEST_APP_APK_FILE);

        try {
            assertThat(pkg.installedOnUser()).isTrue();
        } finally {
            pkg.uninstall(TestApis.users().instrumented());
        }
    }

    @Test
    public void install_byteArray_instrumentedUser_isInstalled() {
        Package pkg =
                TestApis.packages().install(TestApis.users().instrumented(), TEST_APP_BYTES);

        try {
            assertThat(pkg.installedOnUser()).isTrue();
        } finally {
            pkg.uninstall(TestApis.users().instrumented());
        }
    }

    @Test
    @RequireRunOnPrimaryUser
    @EnsureHasWorkProfile
    public void install_inWorkProfile_isInstalled() {
        TestApis.packages().install(sDeviceState.workProfile(), TEST_APP_APK_FILE);
        Package pkg = TestApis.packages().find(TEST_APP_PACKAGE_NAME);

        try {
            assertThat(pkg.installedOnUser(sDeviceState.workProfile())).isTrue();
        } finally {
            pkg.uninstall(sDeviceState.workProfile());
        }
    }

    @Test
    @RequireRunOnPrimaryUser
    @EnsureHasSecondaryUser
    public void install_differentUser_isInstalled() {
        TestApis.packages().install(sDeviceState.secondaryUser(), TEST_APP_APK_FILE);
        Package pkg = TestApis.packages().find(TEST_APP_PACKAGE_NAME);

        try {
            assertThat(pkg.installedOnUser(sDeviceState.secondaryUser())).isTrue();
        } finally {
            pkg.uninstall(sDeviceState.secondaryUser());
        }
    }

    @Test
    public void install_byteArray_differentUser_isInstalled() {
        UserReference user = TestApis.users().createUser().createAndStart();
        TestApis.packages().install(user, TEST_APP_BYTES);
        Package pkg = TestApis.packages().find(TEST_APP_PACKAGE_NAME);

        try {
            assertThat(pkg.installedOnUser(user)).isTrue();
        } finally {
            user.remove();
        }
    }

    @Test
    @RequireRunOnPrimaryUser
    public void install_userNotStarted_throwsException() {
        try (UserReference user = TestApis.users().createUser().create().stop()) {
            assertThrows(NeneException.class, () -> TestApis.packages().install(user,
                    TEST_APP_APK_FILE));
        }
    }

    @Test
    public void install_byteArray_userNotStarted_throwsException() {
        UserReference user = TestApis.users().createUser().create().stop();

        try {
            assertThrows(NeneException.class, () -> TestApis.packages().install(user,
                    TEST_APP_BYTES));
        } finally {
            user.remove();
        }
    }

    @Test
    public void install_userDoesNotExist_throwsException() {
        assertThrows(NeneException.class, () -> TestApis.packages().install(mNonExistingUser,
                TEST_APP_APK_FILE));
    }

    @Test
    public void install_byteArray_userDoesNotExist_throwsException() {
        assertThrows(NeneException.class, () -> TestApis.packages().install(mNonExistingUser,
                TEST_APP_BYTES));
    }

    @Test
    public void install_alreadyInstalledForUser_installs() {
        Package pkg = TestApis.packages().install(mUser, TEST_APP_APK_FILE);

        try {
            pkg = TestApis.packages().install(mUser, TEST_APP_APK_FILE);
            assertThat(pkg.installedOnUser(mUser)).isTrue();
        } finally {
            pkg.uninstall(mUser);
        }
    }

    @Test
    public void install_byteArray_alreadyInstalledForUser_installs() {
        Package pkg = TestApis.packages().install(mUser, TEST_APP_BYTES);

        try {
            pkg = TestApis.packages().install(mUser, TEST_APP_BYTES);
            assertThat(pkg.installedOnUser(mUser)).isTrue();
        } finally {
            pkg.uninstall(mUser);
        }
    }

    @Test
    public void install_alreadyInstalledOnOtherUser_installs() {
        Package pkg = null;

        try (UserReference otherUser = TestApis.users().createUser().createAndStart()) {
            TestApis.packages().install(otherUser, TEST_APP_APK_FILE);

            pkg =
                    TestApis.packages().install(mUser, TEST_APP_APK_FILE);

            assertThat(pkg.installedOnUser(mUser)).isTrue();
        } finally {
            if (pkg != null) {
                pkg.uninstall(mUser);
            }
        }
    }

    @Test
    public void install_byteArray_alreadyInstalledOnOtherUser_installs() {
        Package pkg = null;

        try (UserReference otherUser = TestApis.users().createUser().createAndStart()) {
            TestApis.packages().install(otherUser, TEST_APP_BYTES);

            pkg = TestApis.packages().install(mUser, TEST_APP_BYTES);

            assertThat(pkg.installedOnUser(mUser)).isTrue();
        } finally {
            if (pkg != null) {
                pkg.uninstall(mUser);
            }
        }
    }

    @Test
    @RequireSdkVersion(min = S, reason = "keepUninstalledPackages is only supported on S+")
    @Ignore
    // TODO: .exists() doesn't return true when the package is kept - restore this functionality
    public void keepUninstalledPackages_packageIsUninstalled_packageStillExists() {
        try (TestAppInstance testAppInstance = sTestApp.install()) {
            TestApis.packages().keepUninstalledPackages()
                    .add(sTestApp.pkg())
                    .commit();

            testAppInstance.uninstall();

            assertThat(sTestApp.pkg().exists()).isTrue();
        } finally {
            TestApis.packages().keepUninstalledPackages().clear();
        }
    }

    @Test
    @Ignore("While using adb calls this is not reliable, enable once we use framework calls for "
            + "uninstall")
    public void keepUninstalledPackages_packageRemovedFromList_packageIsUninstalled_packageDoesNotExist() {
        assumeTrue("keepUninstalledPackages is only supported on S+",
                Versions.meetsMinimumSdkVersionRequirement(S));

        TestApis.packages().install(mUser, TEST_APP_APK_FILE);
        TestApis.packages().keepUninstalledPackages()
                .add(mTestAppReference)
                .commit();
        TestApis.packages().keepUninstalledPackages()
                .add(mDifferentTestAppReference)
                .commit();

        try {
            mTestAppReference.uninstall(mUser);

            assertThat(mTestAppReference.exists()).isFalse();
        } finally {
            TestApis.packages().keepUninstalledPackages().clear();
        }
    }

    @Test
    @Ignore("While using adb calls this is not reliable, enable once we use framework calls for "
            + "uninstall")
    public void keepUninstalledPackages_cleared_packageIsUninstalled_packageDoesNotExist() {
        assumeTrue("keepUninstalledPackages is only supported on S+",
                Versions.meetsMinimumSdkVersionRequirement(S));

        TestApis.packages().install(mUser, TEST_APP_APK_FILE);

        TestApis.packages().keepUninstalledPackages()
                .add(mTestAppReference)
                .commit();
        TestApis.packages().keepUninstalledPackages().clear();

        try {
            mTestAppReference.uninstall(mUser);

            assertThat(mTestAppReference.exists()).isFalse();
        } finally {
            TestApis.packages().keepUninstalledPackages().clear();
        }
    }

    @Test
    @Ignore("While using adb calls this is not reliable, enable once we use framework calls for "
            + "uninstall")
    public void keepUninstalledPackages_packageRemovedFromList_packageAlreadyUninstalled_packageDoesNotExist() {
        assumeTrue("keepUninstalledPackages is only supported on S+",
                Versions.meetsMinimumSdkVersionRequirement(S));

        TestApis.packages().install(mUser, TEST_APP_APK_FILE);
        TestApis.packages().keepUninstalledPackages().add(mTestAppReference).commit();
        mTestAppReference.uninstall(mUser);
        TestApis.packages().keepUninstalledPackages().add(mDifferentTestAppReference).commit();

        try {
            assertThat(mTestAppReference.exists()).isFalse();
        } finally {
            TestApis.packages().keepUninstalledPackages().clear();
        }
    }
}
