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

#include "remoting/host/host_change_notification_listener.h"

#include <set>

#include "base/bind.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
#include "remoting/base/constants.h"
#include "remoting/signaling/mock_signal_strategy.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
#include "third_party/webrtc/libjingle/xmpp/constants.h"

using buzz::QName;
using buzz::XmlElement;

using testing::NotNull;
using testing::Return;

namespace remoting {

namespace {
const char kHostId[] = "0";
const char kTestJid[] = "user@gmail.com/chromoting123";
const char kTestBotJid[] = "remotingunittest@bot.talk.google.com";
}  // namespace

ACTION_P(AddListener, list) {
  list->insert(arg0);
}

ACTION_P(RemoveListener, list) {
  EXPECT_TRUE(list->find(arg0) != list->end());
  list->erase(arg0);
}


class HostChangeNotificationListenerTest : public testing::Test {
 protected:
  class MockListener : public HostChangeNotificationListener::Listener {
   public:
    MOCK_METHOD0(OnHostDeleted, void());
  };

  void SetUp() override {
    EXPECT_CALL(signal_strategy_, AddListener(NotNull()))
        .WillRepeatedly(AddListener(&signal_strategy_listeners_));
    EXPECT_CALL(signal_strategy_, RemoveListener(NotNull()))
        .WillRepeatedly(RemoveListener(&signal_strategy_listeners_));
    EXPECT_CALL(signal_strategy_, GetLocalJid())
        .WillRepeatedly(Return(kTestJid));

    host_change_notification_listener_.reset(new HostChangeNotificationListener(
        &mock_listener_, kHostId, &signal_strategy_, kTestBotJid));
  }

  void TearDown() override {
    host_change_notification_listener_.reset();
    EXPECT_TRUE(signal_strategy_listeners_.empty());
  }

  scoped_ptr<XmlElement> GetNotificationStanza(std::string operation,
                                               std::string hostId,
                                               std::string botJid) {
    scoped_ptr<XmlElement> stanza(new XmlElement(buzz::QN_IQ));
    stanza->AddAttr(QName(std::string(), "type"), "set");
    XmlElement* host_changed =
        new XmlElement(QName(kChromotingXmlNamespace, "host-changed"));
    host_changed->AddAttr(QName(kChromotingXmlNamespace, "operation"),
                          operation);
    host_changed->AddAttr(QName(kChromotingXmlNamespace, "hostid"), hostId);
    stanza->AddElement(host_changed);
    stanza->AddAttr(buzz::QN_FROM, botJid);
    stanza->AddAttr(buzz::QN_TO, kTestJid);
    return stanza;
  }

  MockListener mock_listener_;
  MockSignalStrategy signal_strategy_;
  std::set<SignalStrategy::Listener*> signal_strategy_listeners_;
  scoped_ptr<HostChangeNotificationListener> host_change_notification_listener_;
  base::MessageLoop message_loop_;
};

TEST_F(HostChangeNotificationListenerTest, ReceiveValidNotification) {
  EXPECT_CALL(mock_listener_, OnHostDeleted())
      .WillOnce(Return());
  scoped_ptr<XmlElement> stanza = GetNotificationStanza(
      "delete", kHostId, kTestBotJid);
  host_change_notification_listener_->OnSignalStrategyIncomingStanza(
      stanza.get());
  message_loop_.PostTask(FROM_HERE,
                         base::Bind(base::MessageLoop::QuitWhenIdleClosure()));
  message_loop_.Run();
}

TEST_F(HostChangeNotificationListenerTest, ReceiveNotificationBeforeDelete) {
  EXPECT_CALL(mock_listener_, OnHostDeleted())
      .Times(0);
  scoped_ptr<XmlElement> stanza = GetNotificationStanza(
      "delete", kHostId, kTestBotJid);
  host_change_notification_listener_->OnSignalStrategyIncomingStanza(
      stanza.get());
  host_change_notification_listener_.reset();
  message_loop_.PostTask(FROM_HERE,
                         base::Bind(base::MessageLoop::QuitWhenIdleClosure()));
  message_loop_.Run();
}


TEST_F(HostChangeNotificationListenerTest, ReceiveInvalidHostIdNotification) {
  EXPECT_CALL(mock_listener_, OnHostDeleted())
      .Times(0);
  scoped_ptr<XmlElement> stanza = GetNotificationStanza(
      "delete", "1", kTestBotJid);
  host_change_notification_listener_->OnSignalStrategyIncomingStanza(
      stanza.get());
  message_loop_.PostTask(FROM_HERE,
                         base::Bind(base::MessageLoop::QuitWhenIdleClosure()));
  message_loop_.Run();
}

TEST_F(HostChangeNotificationListenerTest, ReceiveInvalidBotJidNotification) {
  EXPECT_CALL(mock_listener_, OnHostDeleted())
      .Times(0);
  scoped_ptr<XmlElement> stanza = GetNotificationStanza(
      "delete", kHostId, "notremotingbot@bot.talk.google.com");
  host_change_notification_listener_->OnSignalStrategyIncomingStanza(
      stanza.get());
  message_loop_.PostTask(FROM_HERE,
                         base::Bind(base::MessageLoop::QuitWhenIdleClosure()));
  message_loop_.Run();
}

TEST_F(HostChangeNotificationListenerTest, ReceiveNonDeleteNotification) {
  EXPECT_CALL(mock_listener_, OnHostDeleted())
      .Times(0);
  scoped_ptr<XmlElement> stanza = GetNotificationStanza(
      "update", kHostId, kTestBotJid);
  host_change_notification_listener_->OnSignalStrategyIncomingStanza(
      stanza.get());
  message_loop_.PostTask(FROM_HERE,
                         base::Bind(base::MessageLoop::QuitWhenIdleClosure()));
  message_loop_.Run();
}

}  // namespace remoting
