// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package io.flutter.plugins.quickactionsexample;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import android.content.Context;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.util.Log;
import androidx.lifecycle.Lifecycle;
import androidx.test.core.app.ActivityScenario;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.Until;
import io.flutter.plugins.quickactions.QuickActionsPlugin;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(AndroidJUnit4.class)
public class QuickActionsTest {
  private Context context;
  private UiDevice device;
  private ActivityScenario<QuickActionsTestActivity> scenario;

  @Before
  public void setUp() {
    context = ApplicationProvider.getApplicationContext();
    device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
    scenario = ensureAppRunToView();
    ensureAllAppShortcutsAreCreated();
  }

  @After
  public void tearDown() {
    scenario.close();
    Log.i(QuickActionsTest.class.getSimpleName(), "Run to completion");
  }

  @Test
  public void quickActionPluginIsAdded() {
    final ActivityScenario<QuickActionsTestActivity> scenario =
        ActivityScenario.launch(QuickActionsTestActivity.class);
    scenario.onActivity(
        activity -> {
          assertTrue(activity.engine.getPlugins().has(QuickActionsPlugin.class));
        });
  }

  @Test
  public void appShortcutsAreCreated() {
    List<ShortcutInfo> expectedShortcuts = createMockShortcuts();

    ShortcutManager shortcutManager =
        (ShortcutManager) context.getSystemService(Context.SHORTCUT_SERVICE);
    List<ShortcutInfo> dynamicShortcuts = shortcutManager.getDynamicShortcuts();

    // Assert the app shortcuts defined in ../lib/main.dart.
    assertFalse(dynamicShortcuts.isEmpty());
    assertEquals(expectedShortcuts.size(), dynamicShortcuts.size());
    for (ShortcutInfo expectedShortcut : expectedShortcuts) {
      ShortcutInfo dynamicShortcut =
          dynamicShortcuts
              .stream()
              .filter(s -> s.getId().equals(expectedShortcut.getId()))
              .findFirst()
              .get();

      assertEquals(expectedShortcut.getShortLabel(), dynamicShortcut.getShortLabel());
      assertEquals(expectedShortcut.getLongLabel(), dynamicShortcut.getLongLabel());
    }
  }

  // TODO(bparrishMines): The test is ignored because it fails when ran on Firebase Test Lab. See
  // https://github.com/flutter/flutter/issues/114246.
  @Ignore
  @Test
  public void appShortcutLaunchActivityAfterStarting() {
    // Arrange
    List<ShortcutInfo> shortcuts = createMockShortcuts();
    ShortcutInfo firstShortcut = shortcuts.get(0);
    ShortcutManager shortcutManager =
        (ShortcutManager) context.getSystemService(Context.SHORTCUT_SERVICE);
    List<ShortcutInfo> dynamicShortcuts = shortcutManager.getDynamicShortcuts();
    ShortcutInfo dynamicShortcut =
        dynamicShortcuts
            .stream()
            .filter(s -> s.getId().equals(firstShortcut.getId()))
            .findFirst()
            .get();
    Intent dynamicShortcutIntent = dynamicShortcut.getIntent();
    AtomicReference<QuickActionsTestActivity> initialActivity = new AtomicReference<>();
    scenario.onActivity(initialActivity::set);
    String appReadySentinel = " has launched";

    // Act
    context.startActivity(dynamicShortcutIntent);
    device.wait(Until.hasObject(By.descContains(appReadySentinel)), 2000);
    AtomicReference<QuickActionsTestActivity> currentActivity = new AtomicReference<>();
    scenario.onActivity(currentActivity::set);

    // Assert
    Assert.assertTrue(
        "AppShortcut:" + firstShortcut.getId() + " does not launch the correct activity",
        // We can only find the shortcut type in content description while inspecting it in Ui
        // Automator Viewer.
        device.hasObject(By.desc(firstShortcut.getId() + appReadySentinel)));
    // This is Android SingleTop behavior in which Android does not destroy the initial activity and
    // launch a new activity.
    Assert.assertEquals(initialActivity.get(), currentActivity.get());
  }

  private void ensureAllAppShortcutsAreCreated() {
    device.wait(Until.hasObject(By.text("actions ready")), 1000);
  }

  private List<ShortcutInfo> createMockShortcuts() {
    List<ShortcutInfo> expectedShortcuts = new ArrayList<>();

    String actionOneLocalizedTitle = "Action one";
    expectedShortcuts.add(
        new ShortcutInfo.Builder(context, "action_one")
            .setShortLabel(actionOneLocalizedTitle)
            .setLongLabel(actionOneLocalizedTitle)
            .build());

    String actionTwoLocalizedTitle = "Action two";
    expectedShortcuts.add(
        new ShortcutInfo.Builder(context, "action_two")
            .setShortLabel(actionTwoLocalizedTitle)
            .setLongLabel(actionTwoLocalizedTitle)
            .build());

    return expectedShortcuts;
  }

  private ActivityScenario<QuickActionsTestActivity> ensureAppRunToView() {
    final ActivityScenario<QuickActionsTestActivity> scenario =
        ActivityScenario.launch(QuickActionsTestActivity.class);
    scenario.moveToState(Lifecycle.State.STARTED);
    return scenario;
  }
}
