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

import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.os.Build.VERSION_CODES.R;

import android.content.Intent;
import android.os.UserHandle;
import android.util.Log;

import com.android.bedstead.nene.TestApis;
import com.android.bedstead.nene.exceptions.AdbException;
import com.android.bedstead.nene.exceptions.NeneException;
import com.android.bedstead.nene.permissions.PermissionContext;
import com.android.bedstead.nene.users.User.UserState;
import com.android.bedstead.nene.utils.ShellCommand;
import com.android.bedstead.nene.utils.ShellCommandUtils;
import com.android.bedstead.nene.utils.Versions;
import com.android.compatibility.common.util.BlockingBroadcastReceiver;

import javax.annotation.Nullable;

/**
 * A representation of a User on device which may or may not exist.
 *
 * <p>To resolve the user into a {@link User}, see {@link #resolve()}.
 */
public abstract class UserReference implements AutoCloseable {

    private static final String LOG_TAG = "UserReference";

    private final int mId;

    UserReference(int id) {
        mId = id;
    }

    public final int id() {
        return mId;
    }

    /**
     * Get a {@link UserHandle} for the {@link #id()}.
     */
    public final UserHandle userHandle() {
        return UserHandle.of(mId);
    }

    /**
     * Get the current state of the {@link User} from the device, or {@code null} if the user does
     * not exist.
     */
    @Nullable
    public final User resolve() {
        return TestApis.users().fetchUser(mId);
    }

    /**
     * Remove the user from the device.
     *
     * <p>If the user does not exist, or the removal fails for any other reason, a
     * {@link NeneException} will be thrown.
     */
    public final void remove() {
        // TODO(scottjonathan): There's a potential issue here as when the user is marked as
        //  "is removing" the DPC still can't be uninstalled because it's set as the profile owner.
        try {
            // Expected success string is "Success: removed user"
            ShellCommand.builder("pm remove-user")
                    .addOperand(mId)
                    .validate(ShellCommandUtils::startsWithSuccess)
                    .execute();
            TestApis.users().waitForUserToNotExistOrMatch(this, User::isRemoving);
        } catch (AdbException e) {
            throw new NeneException("Could not remove user " + this, e);
        }
    }

    /**
     * Start the user.
     *
     * <p>After calling this command, the user will be in the {@link UserState#RUNNING_UNLOCKED}
     * state.
     *
     * <p>If the user does not exist, or the start fails for any other reason, a
     * {@link NeneException} will be thrown.
     */
    //TODO(scottjonathan): Deal with users who won't unlock
    public UserReference start() {
        try {
            // Expected success string is "Success: user started"
            ShellCommand.builder("am start-user")
                    .addOperand(mId)
                    .addOperand("-w")
                    .validate(ShellCommandUtils::startsWithSuccess)
                    .execute();
            User waitedUser = TestApis.users().waitForUserToNotExistOrMatch(
                    this, (user) -> user.state() == UserState.RUNNING_UNLOCKED);
            if (waitedUser == null) {
                throw new NeneException("User does not exist " + this);
            }
        } catch (AdbException e) {
            throw new NeneException("Could not start user " + this, e);
        }

        return this;
    }

    /**
     * Stop the user.
     *
     * <p>After calling this command, the user will be in the {@link UserState#NOT_RUNNING} state.
     */
    public UserReference stop() {
        try {
            // Expects no output on success or failure - stderr output on failure
            ShellCommand.builder("am stop-user")
                    .addOperand("-f") // Force stop
                    .addOperand(mId)
                    .allowEmptyOutput(true)
                    .validate(String::isEmpty)
                    .execute();
            User waitedUser = TestApis.users().waitForUserToNotExistOrMatch(
                    this, (user) -> user.state() == UserState.NOT_RUNNING);
            if (waitedUser == null) {
                throw new NeneException("User does not exist " + this);
            }
        } catch (AdbException e) {
            throw new NeneException("Could not stop user " + this, e);
        }

        return this;
    }

    /**
     * Make the user the foreground user.
     */
    public UserReference switchTo() {
        // This is created outside of the try because we don't want to wait for the broadcast
        // on versions less than R
        BlockingBroadcastReceiver broadcastReceiver =
                new BlockingBroadcastReceiver(TestApis.context().instrumentedContext(),
                        Intent.ACTION_USER_FOREGROUND,
                        (intent) ->((UserHandle)
                                intent.getParcelableExtra(Intent.EXTRA_USER))
                                .getIdentifier() == mId);

        try {
            if (Versions.meetsMinimumSdkVersionRequirement(R)) {
                try (PermissionContext p =
                             TestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL)) {
                    broadcastReceiver.registerForAllUsers();
                }
            }

            // Expects no output on success or failure
            ShellCommand.builder("am switch-user")
                    .addOperand(mId)
                    .allowEmptyOutput(true)
                    .validate(String::isEmpty)
                    .execute();

            if (Versions.meetsMinimumSdkVersionRequirement(R)) {
                broadcastReceiver.awaitForBroadcast();
            } else {
                Thread.sleep(20000);
            }
        } catch (AdbException e) {
            throw new NeneException("Could not switch to user", e);
        } catch (InterruptedException e) {
            Log.e(LOG_TAG, "Interrupted while switching user", e);
        } finally {
            broadcastReceiver.unregisterQuietly();
        }

        return this;
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof UserReference)) {
            return false;
        }

        UserReference other = (UserReference) obj;

        return other.id() == id();
    }

    @Override
    public int hashCode() {
        return id();
    }

    /** See {@link #remove}. */
    @Override
    public void close() {
        remove();
    }
}
