/*
 * Copyright (C) 2020 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 org.robolectric.shadows;

import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
import static android.os.Build.VERSION_CODES.P;
import static android.os.Build.VERSION_CODES.Q;
import static android.os.Build.VERSION_CODES.R;
import static com.google.common.base.Preconditions.checkNotNull;

import android.Manifest;
import android.Manifest.permission;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.app.AppOpsManager;
import android.app.AppOpsManager.Mode;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.CrossProfileApps;
import android.content.pm.ICrossProfileApps;
import android.content.pm.PackageManager;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Process;
import android.os.UserHandle;
import android.text.TextUtils;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import javax.annotation.Nullable;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Resetter;

/** Robolectric implementation of {@link CrossProfileApps}. */
@Implements(value = CrossProfileApps.class, minSdk = P)
public class ShadowCrossProfileApps {

  // BEGIN-INTERNAL
  private final static String INTERACT_ACROSS_PROFILES_APPOP = AppOpsManager.permissionToOp(
          Manifest.permission.INTERACT_ACROSS_PROFILES);
  private static final Set<String> configurableInteractAcrossProfilePackages = new HashSet<>();
  // END-INTERNAL

  private final Set<UserHandle> targetUserProfiles = new LinkedHashSet<>();
  private final List<StartedMainActivity> startedMainActivities = new ArrayList<>();
  private final List<StartedActivity> startedActivities =
          Collections.synchronizedList(new ArrayList<>());
  private final Map<String, Integer> packageNameAppOpModes = new HashMap<>();

  private Context context;
  private PackageManager packageManager;

  @Implementation
  protected void __constructor__(Context context, ICrossProfileApps service) {
    this.context = context;
    this.packageManager = context.getPackageManager();
  }

  /**
   * Returns a list of {@link UserHandle}s currently accessible. This list is populated from calls
   * to {@link #addTargetUserProfile(UserHandle)}.
   */
  @Implementation
  protected List<UserHandle> getTargetUserProfiles() {
    return ImmutableList.copyOf(targetUserProfiles);
  }

  /**
   * Returns a {@link Drawable} that can be shown for profile switching, which is guaranteed to
   * always be the same for a particular user and to be distinct between users.
   */
  @Implementation
  protected Drawable getProfileSwitchingIconDrawable(UserHandle userHandle) {
    verifyCanAccessUser(userHandle);
    return new ColorDrawable(userHandle.getIdentifier());
  }

  /**
   * Returns a {@link CharSequence} that can be shown as a label for profile switching, which is
   * guaranteed to always be the same for a particular user and to be distinct between users.
   */
  @Implementation
  protected CharSequence getProfileSwitchingLabel(UserHandle userHandle) {
    verifyCanAccessUser(userHandle);
    return "Switch to " + userHandle;
  }

  /**
   * Simulates starting the main activity specified in the specified profile, performing the same
   * security checks done by the real {@link CrossProfileApps}.
   *
   * <p>The most recent main activity started can be queried by {@link #peekNextStartedActivity()}
   * ()}.
   */
  @Implementation
  protected void startMainActivity(ComponentName componentName, UserHandle targetUser) {
    verifyCanAccessUser(targetUser);
    verifyActivityInManifest(componentName, /* requireMainActivity= */ true);
    startedMainActivities.add(new StartedMainActivity(componentName, targetUser));
    startedActivities.add(new StartedActivity(componentName, targetUser));
  }

  /**
   * Simulates starting the activity specified in the specified profile, performing the same
   * security checks done by the real {@link CrossProfileApps}.
   *
   * <p>The most recent main activity started can be queried by {@link #peekNextStartedActivity()}
   * ()}.
   */
  @Implementation(minSdk = Q)
  @SystemApi
  @RequiresPermission(permission.INTERACT_ACROSS_PROFILES)
  protected void startActivity(ComponentName componentName, UserHandle targetUser) {
    verifyCanAccessUser(targetUser);
    verifyActivityInManifest(componentName, /* requireMainActivity= */ false);
    verifyHasInteractAcrossProfilesPermission();
    startedActivities.add(new StartedActivity(componentName, targetUser));
  }

  /** Adds {@code userHandle} to the list of accessible handles. */
  public void addTargetUserProfile(UserHandle userHandle) {
    if (userHandle.equals(Process.myUserHandle())) {
      throw new IllegalArgumentException("Cannot target current user");
    }
    targetUserProfiles.add(userHandle);
  }

  /** Removes {@code userHandle} from the list of accessible handles, if present. */
  public void removeTargetUserProfile(UserHandle userHandle) {
    if (userHandle.equals(Process.myUserHandle())) {
      throw new IllegalArgumentException("Cannot target current user");
    }
    targetUserProfiles.remove(userHandle);
  }

  /** Clears the list of accessible handles. */
  public void clearTargetUserProfiles() {
    targetUserProfiles.clear();
  }

  /**
   * Returns the most recent {@link ComponentName}, {@link UserHandle} pair started by {@link
   * CrossProfileApps#startMainActivity(ComponentName, UserHandle)}, wrapped in {@link
   * StartedMainActivity}.
   *
   * @deprecated Use {@link #peekNextStartedActivity()} instead.
   */
  @Nullable
  @Deprecated
  public StartedMainActivity peekNextStartedMainActivity() {
    if (startedMainActivities.isEmpty()) {
      return null;
    } else {
      return Iterables.getLast(startedMainActivities);
    }
  }

  /**
   * Returns the most recent {@link ComponentName}, {@link UserHandle} pair started by {@link
   * CrossProfileApps#startMainActivity(ComponentName, UserHandle)} or {@link
   * CrossProfileApps#startActivity(ComponentName, UserHandle)}, wrapped in {@link StartedActivity}.
   */
  @Nullable
  public StartedActivity peekNextStartedActivity() {
    if (startedActivities.isEmpty()) {
      return null;
    } else {
      return Iterables.getLast(startedActivities);
    }
  }

  /**
   * Consumes the most recent {@link ComponentName}, {@link UserHandle} pair started by {@link
   * CrossProfileApps#startMainActivity(ComponentName, UserHandle)} or {@link
   * CrossProfileApps#startActivity(ComponentName, UserHandle)}, and returns it wrapped in {@link
   * StartedActivity}.
   */
  @Nullable
  public StartedActivity getNextStartedActivity() {
    if (startedActivities.isEmpty()) {
      return null;
    } else {
      return startedActivities.remove(startedActivities.size() - 1);
    }
  }

  /**
   * Clears all records of {@link StartedActivity}s from calls to {@link
   * CrossProfileApps#startActivity(ComponentName, UserHandle)} or {@link
   * CrossProfileApps#startMainActivity(ComponentName, UserHandle)}.
   */
  public void clearNextStartedActivities() {
    startedActivities.clear();
  }

  private void verifyCanAccessUser(UserHandle userHandle) {
    if (!targetUserProfiles.contains(userHandle)) {
      throw new SecurityException(
              "Not allowed to access "
                      + userHandle
                      + " (did you forget to call addTargetUserProfile?)");
    }
  }

  private void verifyHasInteractAcrossProfilesPermission() {
    if (context.checkSelfPermission(permission.INTERACT_ACROSS_PROFILES)
            != PackageManager.PERMISSION_GRANTED) {
      throw new SecurityException(
              "Attempt to launch activity without required "
                      + permission.INTERACT_ACROSS_PROFILES
                      + " permission");
    }
  }

  /**
   * Ensures that {@code component} is present in the manifest as an exported and enabled activity.
   * This check and the error thrown are the same as the check done by the real {@link
   * CrossProfileApps}.
   *
   * <p>If {@code requireMainActivity} is true, then this also asserts that the activity is a
   * launcher activity.
   */
  private void verifyActivityInManifest(ComponentName component, boolean requireMainActivity) {
    Intent launchIntent = new Intent();
    if (requireMainActivity) {
      launchIntent
              .setAction(Intent.ACTION_MAIN)
              .addCategory(Intent.CATEGORY_LAUNCHER)
              .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
              .setPackage(component.getPackageName());
    } else {
      launchIntent.setComponent(component);
    }

    boolean existsMatchingActivity =
            Iterables.any(
                    packageManager.queryIntentActivities(
                            launchIntent, MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE),
                    resolveInfo -> {
                      ActivityInfo activityInfo = resolveInfo.activityInfo;
                      return TextUtils.equals(activityInfo.packageName, component.getPackageName())
                              && TextUtils.equals(activityInfo.name, component.getClassName())
                              && activityInfo.exported;
                    });
    if (!existsMatchingActivity) {
      throw new SecurityException(
              "Attempt to launch activity without "
                      + " category Intent.CATEGORY_LAUNCHER or activity is not exported"
                      + component);
    }
  }

  // BEGIN-INTERNAL
  @Implementation(minSdk = R)
  @RequiresPermission(
          allOf={android.Manifest.permission.MANAGE_APP_OPS_MODES,
                  android.Manifest.permission.INTERACT_ACROSS_USERS})
  protected void setInteractAcrossProfilesAppOp(String packageName, @Mode int newMode) {
    packageNameAppOpModes.put(packageName, newMode);
  }

  /**
   * Returns the app-op mode associated with the given package name. If not set, returns {@code
   * null}.
   */
  @Nullable
  public @Mode Integer getInteractAcrossProfilesAppOp(String packageName) {
    return packageNameAppOpModes.get(packageName);
  }

  public void addCrossProfilePackage(String packageName){
    configurableInteractAcrossProfilePackages.add(packageName);
  }

  @Implementation(minSdk = R)
  protected void resetInteractAcrossProfilesAppOps(
          @NonNull Collection<String> previousCrossProfilePackages,
          @NonNull Set<String> newCrossProfilePackages) {

    final List<String> unsetCrossProfilePackages =
            previousCrossProfilePackages.stream()
                    .filter(packageName -> !newCrossProfilePackages.contains(packageName))
                    .collect(Collectors.toList());

    for (String packageName : unsetCrossProfilePackages) {
      if (!canConfigureInteractAcrossProfiles(packageName)) {
        setInteractAcrossProfilesAppOp(packageName,
                AppOpsManager.opToDefaultMode(INTERACT_ACROSS_PROFILES_APPOP));
      }
    }
  }

  // BEGIN-INTERNAL
  @Implementation(minSdk = R)
  protected void clearInteractAcrossProfilesAppOps() {
    findAllPackageNames().forEach(
        packageName -> setInteractAcrossProfilesAppOp(
            packageName, AppOpsManager.opToDefaultMode(INTERACT_ACROSS_PROFILES_APPOP)));
  }

  private List<String> findAllPackageNames() {
    return context.getPackageManager()
        .getInstalledApplications(/* flags= */ 0)
        .stream()
        .map(applicationInfo -> applicationInfo.packageName)
        .collect(Collectors.toList());
  }
  // END-INTERNAL

  @Implementation
  protected boolean canConfigureInteractAcrossProfiles(@NonNull String packageName) {
    return configurableInteractAcrossProfilePackages.contains(packageName);
  }

  @Resetter
  public static void reset() {
    configurableInteractAcrossProfilePackages.clear();
  }
  // END-INTERNAL

  /**
   * Container object to hold parameters passed to {@link #startMainActivity(ComponentName,
   * UserHandle)}.
   *
   * @deprecated Use {@link #peekNextStartedActivity()} and {@link StartedActivity} instead.
   */
  @Deprecated
  public static class StartedMainActivity {

    private final ComponentName componentName;
    private final UserHandle userHandle;

    public StartedMainActivity(ComponentName componentName, UserHandle userHandle) {
      this.componentName = checkNotNull(componentName);
      this.userHandle = checkNotNull(userHandle);
    }

    public ComponentName getComponentName() {
      return componentName;
    }

    public UserHandle getUserHandle() {
      return userHandle;
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) {
        return true;
      }
      if (o == null || getClass() != o.getClass()) {
        return false;
      }
      StartedMainActivity that = (StartedMainActivity) o;
      return Objects.equals(componentName, that.componentName)
              && Objects.equals(userHandle, that.userHandle);
    }

    @Override
    public int hashCode() {
      return Objects.hash(componentName, userHandle);
    }
  }

  /**
   * Container object to hold parameters passed to {@link #startMainActivity(ComponentName,
   * UserHandle)} or {@link #startActivity(ComponentName, UserHandle)}.
   */
  public static final class StartedActivity {

    private final ComponentName componentName;
    private final UserHandle userHandle;

    public StartedActivity(ComponentName componentName, UserHandle userHandle) {
      this.componentName = checkNotNull(componentName);
      this.userHandle = checkNotNull(userHandle);
    }

    public ComponentName getComponentName() {
      return componentName;
    }

    public UserHandle getUserHandle() {
      return userHandle;
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) {
        return true;
      }
      if (o == null || getClass() != o.getClass()) {
        return false;
      }
      StartedActivity that = (StartedActivity) o;
      return Objects.equals(componentName, that.componentName)
              && Objects.equals(userHandle, that.userHandle);
    }

    @Override
    public int hashCode() {
      return Objects.hash(componentName, userHandle);
    }
  }
}