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

#include <memory>
#include <set>
#include <string>
#include <vector>

#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "chrome/browser/notifications/notification_blocker.h"
#include "chrome/browser/notifications/notification_display_queue.h"
#include "chrome/browser/notifications/notification_display_service.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/message_center/message_center.h"
#include "ui/message_center/public/cpp/notification.h"
#include "ui/message_center/public/cpp/notification_delegate.h"
#include "ui/message_center/public/cpp/notification_types.h"
#include "url/gurl.h"
#include "url/origin.h"

namespace {

class FakeNotificationBlocker : public NotificationBlocker {
 public:
  FakeNotificationBlocker() = default;
  ~FakeNotificationBlocker() override = default;

  // NotificationDisplayQueue::NotificationBlocker:
  bool ShouldBlockNotification(
      const message_center::Notification& notification) override {
    if (!should_block_ || !blocked_origin_)
      return should_block_;

    return url::IsSameOriginWith(notification.origin_url(), *blocked_origin_);
  }
  MOCK_METHOD(void,
              OnBlockedNotification,
              (const message_center::Notification&, bool),
              (override));
  MOCK_METHOD(void,
              OnClosedNotification,
              (const message_center::Notification&),
              (override));

  void SetShouldBlockNotifications(bool should_block) {
    should_block_ = should_block;
    NotifyBlockingStateChanged();
  }

  void SetBlockedOrigin(const absl::optional<GURL>& blocked_origin) {
    blocked_origin_ = blocked_origin;
    NotifyBlockingStateChanged();
  }

 private:
  bool should_block_ = false;
  absl::optional<GURL> blocked_origin_;
};

class NotificationDisplayServiceMock : public NotificationDisplayService {
 public:
  NotificationDisplayServiceMock() = default;
  ~NotificationDisplayServiceMock() override = default;

  using NotificationDisplayService::DisplayedNotificationsCallback;

  MOCK_METHOD3(DisplayMockImpl,
               void(NotificationHandler::Type,
                    const message_center::Notification&,
                    NotificationCommon::Metadata*));
  void Display(
      NotificationHandler::Type notification_type,
      const message_center::Notification& notification,
      std::unique_ptr<NotificationCommon::Metadata> metadata) override {
    DisplayMockImpl(notification_type, notification, metadata.get());
  }

  MOCK_METHOD2(Close, void(NotificationHandler::Type, const std::string&));
  MOCK_METHOD1(GetDisplayed, void(DisplayedNotificationsCallback));
  MOCK_METHOD1(AddObserver, void(Observer* observer));
  MOCK_METHOD1(RemoveObserver, void(Observer* observer));
};

// Matcher to compare Notifications
MATCHER_P(EqualNotification, notification, "") {
  return arg.type() == notification.type() && arg.id() == notification.id();
}

message_center::Notification CreateNotification(const std::string& id,
                                                const GURL& origin) {
  return message_center::Notification(
      message_center::NOTIFICATION_TYPE_SIMPLE, id, /*title=*/std::u16string(),
      /*message=*/std::u16string(), /*icon=*/ui::ImageModel(),
      /*display_source=*/std::u16string(), origin, message_center::NotifierId(),
      message_center::RichNotificationData(),
      base::MakeRefCounted<message_center::NotificationDelegate>());
}

message_center::Notification CreateNotification(const std::string& id) {
  return CreateNotification(id, GURL());
}

}  // namespace

class NotificationDisplayQueueTest : public testing::Test {
 protected:
  NotificationDisplayQueueTest() = default;
  ~NotificationDisplayQueueTest() override = default;

  // testing::Test:
  void SetUp() override {
    auto blocker = std::make_unique<FakeNotificationBlocker>();
    notification_blocker_ = blocker.get();

    NotificationDisplayQueue::NotificationBlockers blockers;
    blockers.push_back(std::move(blocker));
    queue_.SetNotificationBlockers(std::move(blockers));
  }

  NotificationDisplayServiceMock& service() { return service_; }

  NotificationDisplayQueue& queue() { return queue_; }

  FakeNotificationBlocker& notification_blocker() {
    return *notification_blocker_;
  }

 private:
  NotificationDisplayServiceMock service_;
  NotificationDisplayQueue queue_{&service_};
  raw_ptr<FakeNotificationBlocker> notification_blocker_ = nullptr;
};

TEST_F(NotificationDisplayQueueTest, ShouldEnqueueWithoutBlockers) {
  queue().SetNotificationBlockers({});
  EXPECT_FALSE(queue().ShouldEnqueueNotification(
      NotificationHandler::Type::WEB_PERSISTENT, CreateNotification("id")));
}

TEST_F(NotificationDisplayQueueTest, ShouldEnqueueWithAllowingBlocker) {
  EXPECT_FALSE(queue().ShouldEnqueueNotification(
      NotificationHandler::Type::WEB_PERSISTENT, CreateNotification("id")));
}

TEST_F(NotificationDisplayQueueTest, ShouldEnqueueWithBlockingBlocker) {
  notification_blocker().SetShouldBlockNotifications(true);
  EXPECT_TRUE(queue().ShouldEnqueueNotification(
      NotificationHandler::Type::WEB_PERSISTENT, CreateNotification("id")));
}

TEST_F(NotificationDisplayQueueTest, ShouldEnqueueForNonWebNotification) {
  notification_blocker().SetShouldBlockNotifications(true);
  EXPECT_FALSE(queue().ShouldEnqueueNotification(
      NotificationHandler::Type::TRANSIENT, CreateNotification("id")));
}

TEST_F(NotificationDisplayQueueTest, EnqueueNotification) {
  std::string notification_id = "id";
  queue().EnqueueNotification(NotificationHandler::Type::TRANSIENT,
                              CreateNotification(notification_id),
                              /*metadata=*/nullptr);
  std::set<std::string> queued = queue().GetQueuedNotificationIds();
  EXPECT_EQ(1u, queued.size());
  EXPECT_EQ(1u, queued.count(notification_id));
}

TEST_F(NotificationDisplayQueueTest, RemoveQueuedNotification) {
  std::string notification_id_1 = "id1";
  std::string notification_id_2 = "id2";
  std::string notification_id_3 = "id3";

  queue().EnqueueNotification(NotificationHandler::Type::TRANSIENT,
                              CreateNotification(notification_id_1),
                              /*metadata=*/nullptr);
  queue().EnqueueNotification(NotificationHandler::Type::TRANSIENT,
                              CreateNotification(notification_id_2),
                              /*metadata=*/nullptr);
  queue().EnqueueNotification(NotificationHandler::Type::TRANSIENT,
                              CreateNotification(notification_id_3),
                              /*metadata=*/nullptr);
  EXPECT_EQ(3u, queue().GetQueuedNotificationIds().size());

  queue().RemoveQueuedNotification(notification_id_2);
  std::set<std::string> queued = queue().GetQueuedNotificationIds();
  EXPECT_EQ(2u, queued.size());
  EXPECT_EQ(1u, queued.count(notification_id_1));
  EXPECT_EQ(1u, queued.count(notification_id_3));
}

TEST_F(NotificationDisplayQueueTest, BlockUnblockBlocker) {
  EXPECT_CALL(service(), DisplayMockImpl).Times(0);
  notification_blocker().SetShouldBlockNotifications(true);
  notification_blocker().SetShouldBlockNotifications(false);
}

TEST_F(NotificationDisplayQueueTest, BlockUnblockMultipleBlockers) {
  auto blocker_1 = std::make_unique<FakeNotificationBlocker>();
  FakeNotificationBlocker* notification_blocker_1 = blocker_1.get();
  auto blocker_2 = std::make_unique<FakeNotificationBlocker>();
  FakeNotificationBlocker* notification_blocker_2 = blocker_2.get();

  NotificationDisplayQueue::NotificationBlockers blockers;
  blockers.push_back(std::move(blocker_1));
  blockers.push_back(std::move(blocker_2));
  queue().SetNotificationBlockers(std::move(blockers));

  EXPECT_CALL(service(), DisplayMockImpl).Times(0);
  notification_blocker_1->SetShouldBlockNotifications(true);
  notification_blocker_2->SetShouldBlockNotifications(true);

  EXPECT_CALL(*notification_blocker_1, OnBlockedNotification);
  EXPECT_CALL(*notification_blocker_2, OnBlockedNotification);

  message_center::Notification notification = CreateNotification("id");
  queue().EnqueueNotification(NotificationHandler::Type::TRANSIENT,
                              notification, /*metadata=*/nullptr);

  notification_blocker_2->SetShouldBlockNotifications(false);
  EXPECT_CALL(service(), DisplayMockImpl(NotificationHandler::Type::TRANSIENT,
                                         EqualNotification(notification),
                                         /*metadata=*/nullptr))
      .Times(1);
  notification_blocker_1->SetShouldBlockNotifications(false);
}

TEST_F(NotificationDisplayQueueTest, UnblockNotificationOrdering) {
  notification_blocker().SetShouldBlockNotifications(true);

  message_center::Notification notification_1 = CreateNotification("id1");
  message_center::Notification notification_2 = CreateNotification("id2");
  message_center::Notification notification_3 = CreateNotification("id3");

  EXPECT_CALL(notification_blocker(), OnBlockedNotification).Times(3);

  queue().EnqueueNotification(NotificationHandler::Type::TRANSIENT,
                              notification_1, /*metadata=*/nullptr);
  queue().EnqueueNotification(NotificationHandler::Type::TRANSIENT,
                              notification_2, /*metadata=*/nullptr);
  queue().EnqueueNotification(NotificationHandler::Type::TRANSIENT,
                              notification_3, /*metadata=*/nullptr);
  EXPECT_EQ(3u, queue().GetQueuedNotificationIds().size());

  testing::InSequence s;
  EXPECT_CALL(service(), DisplayMockImpl(NotificationHandler::Type::TRANSIENT,
                                         EqualNotification(notification_1),
                                         /*metadata=*/nullptr));
  EXPECT_CALL(service(), DisplayMockImpl(NotificationHandler::Type::TRANSIENT,
                                         EqualNotification(notification_2),
                                         /*metadata=*/nullptr));
  EXPECT_CALL(service(), DisplayMockImpl(NotificationHandler::Type::TRANSIENT,
                                         EqualNotification(notification_3),
                                         /*metadata=*/nullptr));
  notification_blocker().SetShouldBlockNotifications(false);
}

TEST_F(NotificationDisplayQueueTest, UnblockNotificationSubset) {
  GURL origin_1("https://example1.com");
  GURL origin_2("https://example2.com");

  auto blocker_1 = std::make_unique<FakeNotificationBlocker>();
  FakeNotificationBlocker* notification_blocker_1 = blocker_1.get();
  notification_blocker_1->SetShouldBlockNotifications(true);
  notification_blocker_1->SetBlockedOrigin(origin_1);

  auto blocker_2 = std::make_unique<FakeNotificationBlocker>();
  FakeNotificationBlocker* notification_blocker_2 = blocker_2.get();
  notification_blocker_2->SetShouldBlockNotifications(true);
  notification_blocker_2->SetBlockedOrigin(origin_2);

  NotificationDisplayQueue::NotificationBlockers blockers;
  blockers.push_back(std::move(blocker_1));
  blockers.push_back(std::move(blocker_2));
  queue().SetNotificationBlockers(std::move(blockers));

  message_center::Notification notification_1 =
      CreateNotification("id1", origin_1);
  message_center::Notification notification_2 =
      CreateNotification("id2", origin_2);

  queue().EnqueueNotification(NotificationHandler::Type::TRANSIENT,
                              notification_1, /*metadata=*/nullptr);
  queue().EnqueueNotification(NotificationHandler::Type::TRANSIENT,
                              notification_2, /*metadata=*/nullptr);
  EXPECT_EQ(2u, queue().GetQueuedNotificationIds().size());

  // Unblocking first blocker should only show first notification.
  EXPECT_CALL(service(), DisplayMockImpl(NotificationHandler::Type::TRANSIENT,
                                         EqualNotification(notification_1),
                                         /*metadata=*/nullptr));
  notification_blocker_1->SetShouldBlockNotifications(false);
  testing::Mock::VerifyAndClearExpectations(&service());
  EXPECT_EQ(1u, queue().GetQueuedNotificationIds().size());

  // Unblocking second blocker should show second notification.
  EXPECT_CALL(service(), DisplayMockImpl(NotificationHandler::Type::TRANSIENT,
                                         EqualNotification(notification_2),
                                         /*metadata=*/nullptr));
  notification_blocker_2->SetShouldBlockNotifications(false);
  testing::Mock::VerifyAndClearExpectations(&service());
  EXPECT_EQ(0u, queue().GetQueuedNotificationIds().size());
}

TEST_F(NotificationDisplayQueueTest, MultipleBlockersNotifyBlocked) {
  auto blocker_1 = std::make_unique<FakeNotificationBlocker>();
  FakeNotificationBlocker* notification_blocker_1 = blocker_1.get();
  auto blocker_2 = std::make_unique<FakeNotificationBlocker>();
  FakeNotificationBlocker* notification_blocker_2 = blocker_2.get();

  NotificationDisplayQueue::NotificationBlockers blockers;
  blockers.push_back(std::move(blocker_1));
  blockers.push_back(std::move(blocker_2));
  queue().SetNotificationBlockers(std::move(blockers));

  notification_blocker_1->SetShouldBlockNotifications(true);
  notification_blocker_2->SetShouldBlockNotifications(false);

  EXPECT_CALL(*notification_blocker_1, OnBlockedNotification).Times(1);
  EXPECT_CALL(*notification_blocker_2, OnBlockedNotification).Times(0);

  queue().EnqueueNotification(NotificationHandler::Type::TRANSIENT,
                              CreateNotification("id1"), /*metadata=*/nullptr);

  notification_blocker_2->SetShouldBlockNotifications(true);
  notification_blocker_1->SetShouldBlockNotifications(false);

  EXPECT_CALL(*notification_blocker_1, OnBlockedNotification).Times(0);
  EXPECT_CALL(*notification_blocker_2, OnBlockedNotification).Times(1);

  queue().EnqueueNotification(NotificationHandler::Type::TRANSIENT,
                              CreateNotification("id2"), /*metadata=*/nullptr);
}

TEST_F(NotificationDisplayQueueTest, NotifiesReplacedNotification) {
  message_center::Notification notification = CreateNotification("id");
  notification_blocker().SetShouldBlockNotifications(true);

  EXPECT_CALL(notification_blocker(),
              OnBlockedNotification(testing::_, /*replaced=*/false));
  queue().EnqueueNotification(NotificationHandler::Type::TRANSIENT,
                              notification, /*metadata=*/nullptr);

  EXPECT_CALL(notification_blocker(),
              OnBlockedNotification(testing::_, /*replaced=*/true));
  EXPECT_CALL(notification_blocker(), OnClosedNotification).Times(0);
  queue().EnqueueNotification(NotificationHandler::Type::TRANSIENT,
                              notification, /*metadata=*/nullptr);
}

TEST_F(NotificationDisplayQueueTest, NotifiesClosedNotification) {
  message_center::Notification notification = CreateNotification("id");
  notification_blocker().SetShouldBlockNotifications(true);

  EXPECT_CALL(notification_blocker(), OnBlockedNotification);
  queue().EnqueueNotification(NotificationHandler::Type::TRANSIENT,
                              notification, /*metadata=*/nullptr);

  EXPECT_CALL(notification_blocker(), OnClosedNotification);
  queue().RemoveQueuedNotification(notification.id());
}
