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

import static com.android.compatibility.common.util.FileUtils.readInputStreamFully;

import android.content.Context;
import android.os.Bundle;
import android.os.UserHandle;

import androidx.annotation.Nullable;

import com.android.bedstead.nene.TestApis;
import com.android.bedstead.nene.exceptions.NeneException;
import com.android.bedstead.nene.packages.Package;
import com.android.bedstead.nene.users.UserReference;
import com.android.bedstead.nene.users.Users;
import com.android.bedstead.testapp.processor.annotations.TestAppSender;
import com.android.queryable.info.ActivityInfo;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;
import java.util.Set;

/** Represents a single test app which can be installed and interacted with. */
@TestAppSender
public final class TestApp {
    // Must be instrumentation context to access resources
    private static final Context sContext = TestApis.context().instrumentationContext();
    final TestAppDetails mDetails;

    TestApp(TestAppDetails details) {
        if (details == null) {
            throw new NullPointerException();
        }
        mDetails = details;
    }

    /**
     * Get a {@link Package} for the {@link TestApp}.
     *
     * <p>This will only be resolvable after the app is installed.
     */
    public Package pkg() {
        return TestApis.packages().find(packageName());
    }

    /**
     * Install the {@link TestApp} on the device for the instrumented user.
     *
     * <p>See {@link Users#instrumented()}
     */
    public TestAppInstance install() {
        return install(TestApis.users().instrumented());
    }

    /**
     * Install the {@link TestApp} on the device for the given {@link UserReference}.
     */
    public TestAppInstance install(UserReference user) {
        try {
            pkg().installBytes(user, this::apkBytes);
        } catch (NeneException e) {
            throw new NeneException("Error while installing TestApp " + this, e);
        }

        return new TestAppInstance(this, user);
    }

    /**
     * Install the {@link TestApp} on the device for the given {@link UserHandle}.
     */
    public TestAppInstance install(UserHandle user) {
        install(TestApis.users().find(user));
        return instance(user);
    }

    /**
     * Uninstall the {@link TestApp} on the device from the instrumented user.
     *
     * <p>See {@link Users#instrumented()}
     */
    public void uninstall() {
        uninstall(TestApis.users().instrumented());
    }

    /**
     * Uninstall the {@link TestApp} from the device from all users.
     */
    public void uninstallFromAllUsers() {
        pkg().uninstallFromAllUsers();
    }

    /**
     * Uninstall the {@link TestApp} on the device from the given {@link UserReference}.
     */
    public void uninstall(UserReference user) {
        pkg().uninstall(user);
    }

    /**
     * Uninstall the {@link TestApp} on the device from the given {@link UserHandle}.
     */
    public void uninstall(UserHandle user) {
        uninstall(TestApis.users().find(user));
    }

    /**
     * Get a reference to the specific instance of this test app on a given user.
     *
     * <p>This does not check if the user exists, or if the test app is installed on the user.
     */
    public TestAppInstance instance(UserHandle user) {
        return instance(TestApis.users().find(user));
    }

    /**
     * Get a reference to the specific instance of this test app on a given user.
     *
     * <p>This does not check if the user exists, or if the test app is installed on the user.
     */
    public TestAppInstance instance(UserReference user) {
        if (user == null) {
            throw new NullPointerException();
        }
        return new TestAppInstance(this, user);
    }

    /**
     * Returns an {@link InputStream} of the apk for this app.
     */
    public InputStream apkStream() {
        return sContext.getResources().openRawResource(mDetails.mResourceIdentifier);
    }

    /**
     * Returns a byte array of the apk for this app.
     */
    public byte[] apkBytes() {
        try (InputStream inputStream = apkStream()) {
            return readInputStreamFully(inputStream);
        } catch (IOException e) {
            throw new NeneException("Error when reading TestApp bytes", e);
        }
    }

    /** Write the APK file to the given {@link File}. */
    public void writeApkFile(File outputFile) throws IOException {
        outputFile.getParentFile().mkdirs();
        try (FileOutputStream output = new FileOutputStream(outputFile)) {
            output.write(apkBytes());
        }
    }

    /** The package name of the test app. */
    public String packageName() {
        return mDetails.mApp.getPackageName();
    }

    /** The testOnly attribute for the test app. */
    public boolean testOnly() {
        return mDetails.mApp.getTestOnly();
    }

    /** The minSdkVersion of the test app. */
    public int minSdkVersion() {
        return mDetails.mApp.getUsesSdk().getMinSdkVersion();
    }

    /** The maxSdkVersion of the test app. */
    public int maxSdkVersion() {
        return mDetails.mApp.getUsesSdk().getMaxSdkVersion();
    }

    /** The targetSdkVersion of the test app. */
    public int targetSdkVersion() {
        return mDetails.mApp.getUsesSdk().getTargetSdkVersion();
    }

    /** The permissions declared by the test app. */
    public Set<String> permissions() {
        return mDetails.mPermissions;
    }

    /** The activities which exist in the test app. */
    public Set<ActivityInfo> activities() {
        return mDetails.mActivities;
    }

    /**
     * The metadata declared by the test app.
     *
     * <p>Note that currently all values are of type String.
     */
    public Bundle metadata() {
        return mDetails.mMetadata;
    }

    @Override
    public String toString() {
        return "TestApp{"
                + "packageName=" + packageName()
                + ", details=" + mDetails
                + "}";
    }

    /** The shared user id of the test app, if any. */
    @Nullable
    public String sharedUserId() {
        return mDetails.sharedUserId();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof TestApp)) return false;
        TestApp testApp = (TestApp) o;
        return mDetails.mApp.getPackageName().equals(testApp.mDetails.mApp.getPackageName());
    }

    @Override
    public int hashCode() {
        return Objects.hash(mDetails.mApp.getPackageName());
    }
}
