// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ash/arc/notification/arc_management_transition_notification.h"

#include <memory>
#include <string>

#include "ash/resources/vector_icons/vector_icons.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/ash/app_list/arc/arc_app_list_prefs.h"
#include "chrome/browser/ash/app_list/arc/arc_app_test.h"
#include "chrome/browser/ash/app_list/arc/arc_app_utils.h"
#include "chrome/test/base/testing_profile.h"
#include "chromeos/ash/experiences/arc/arc_prefs.h"
#include "chromeos/ash/experiences/arc/metrics/arc_metrics_constants.h"
#include "chromeos/ash/experiences/arc/session/arc_management_transition.h"
#include "chromeos/ash/experiences/arc/test/fake_app_instance.h"
#include "chromeos/ui/vector_icons/vector_icons.h"
#include "components/prefs/pref_service.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/message_center/message_center.h"
#include "ui/message_center/public/cpp/notification.h"

namespace arc {

namespace {

struct TransitionNotificationParams {
  TransitionNotificationParams(ArcManagementTransition arc_transition,
                               const gfx::VectorIcon* notification_icon)
      : arc_transition(arc_transition), notification_icon(notification_icon) {}

  ArcManagementTransition arc_transition;
  raw_ptr<const gfx::VectorIcon> notification_icon;
};

}  // namespace

class ArcManagementTransitionNotificationTest
    : public testing::Test,
      public testing::WithParamInterface<TransitionNotificationParams> {
 public:
  ArcManagementTransitionNotificationTest() = default;
  ~ArcManagementTransitionNotificationTest() override = default;
  ArcManagementTransitionNotificationTest(
      const ArcManagementTransitionNotificationTest&) = delete;
  ArcManagementTransitionNotificationTest& operator=(
      const ArcManagementTransitionNotificationTest&) = delete;

  void SetUp() override {
    message_center::MessageCenter::Initialize();
    arc_app_test_.PreProfileSetUp();
    profile_ = std::make_unique<TestingProfile>();
    arc_app_test_.PostProfileSetUp(profile());
  }

  void TearDown() override {
    arc_app_test_.PreProfileTearDown();
    profile_.reset();
    arc_app_test_.PostProfileTearDown();
    message_center::MessageCenter::Shutdown();
  }

  Profile* profile() { return profile_.get(); }
  ArcAppTest* arc_app_test() { return &arc_app_test_; }

  const gfx::VectorIcon* expected_notification_icon() {
    return GetParam().notification_icon;
  }

  ArcManagementTransition arc_transition() { return GetParam().arc_transition; }

 private:
  std::unique_ptr<TestingProfile> profile_;
  ArcAppTest arc_app_test_;

  content::BrowserTaskEnvironment task_environment_;
};

INSTANTIATE_TEST_SUITE_P(
    All,
    ArcManagementTransitionNotificationTest,
    ::testing::Values(
        TransitionNotificationParams(ArcManagementTransition::NO_TRANSITION,
                                     nullptr),
        TransitionNotificationParams(ArcManagementTransition::CHILD_TO_REGULAR,
                                     &ash::kNotificationFamilyLinkIcon),
        TransitionNotificationParams(ArcManagementTransition::REGULAR_TO_CHILD,
                                     &ash::kNotificationFamilyLinkIcon),
        TransitionNotificationParams(
            ArcManagementTransition::UNMANAGED_TO_MANAGED,
            &chromeos::kEnterpriseIcon)));

TEST_P(ArcManagementTransitionNotificationTest, BaseFlow) {
  ASSERT_TRUE(arc_app_test()->fake_apps().size());
  arc_app_test()->app_instance()->SendRefreshAppList(
      arc_app_test()->fake_apps());
  const std::string app_id =
      ArcAppTest::GetAppId(*arc_app_test()->fake_apps()[0]);

  profile()->GetPrefs()->SetInteger(prefs::kArcManagementTransition,
                                    static_cast<int>(arc_transition()));

  // Attempt to launch ARC app triggers notification.
  LaunchApp(profile(), app_id, 0 /* event_flags */,
            UserInteractionType::NOT_USER_INITIATED);

  std::unique_ptr<ArcAppListPrefs::AppInfo> app_info =
      arc_app_test()->arc_app_list_prefs()->GetApp(app_id);
  ASSERT_TRUE(app_info);

  // In case no management transition in progress notification is not
  // triggered.
  if (arc_transition() == ArcManagementTransition::NO_TRANSITION) {
    EXPECT_FALSE(
        message_center::MessageCenter::Get()->FindVisibleNotificationById(
            kManagementTransitionNotificationId));
    // Last launch is set, indicating that launch attempt was not blocked.
    EXPECT_FALSE(app_info->last_launch_time.is_null());
    return;
  }

  {
    const message_center::Notification* notification =
        message_center::MessageCenter::Get()->FindVisibleNotificationById(
            kManagementTransitionNotificationId);

    // Notification is shown.
    ASSERT_TRUE(notification);
    // Notification has expected icon.
    EXPECT_EQ(&notification->vector_small_image(),
              expected_notification_icon());
  }

  // Last launch is not set, indicating that launch attempt was blocked.
  EXPECT_TRUE(app_info->last_launch_time.is_null());

  // Finishing transition automatically dismisses notification.
  profile()->GetPrefs()->SetInteger(
      prefs::kArcManagementTransition,
      static_cast<int>(ArcManagementTransition::NO_TRANSITION));
  EXPECT_FALSE(
      message_center::MessageCenter::Get()->FindVisibleNotificationById(
          kManagementTransitionNotificationId));

  // Re-activate notification and check opt out. On opt-out notification is also
  // automatically dismissed.
  profile()->GetPrefs()->SetInteger(prefs::kArcManagementTransition,
                                    static_cast<int>(arc_transition()));
  ShowManagementTransitionNotification(profile());
  EXPECT_TRUE(message_center::MessageCenter::Get()->FindVisibleNotificationById(
      kManagementTransitionNotificationId));
  profile()->GetPrefs()->SetBoolean(prefs::kArcEnabled, false);
  EXPECT_FALSE(
      message_center::MessageCenter::Get()->FindVisibleNotificationById(
          kManagementTransitionNotificationId));
}

}  // namespace arc
