// Copyright 2014 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 "ui/display/display_change_notifier.h"

#include <stdint.h>

#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/display/display.h"
#include "ui/display/display_observer.h"

namespace display {

class MockDisplayObserver : public DisplayObserver {
 public:
  MockDisplayObserver()
      : display_added_(0),
        display_removed_(0),
        display_changed_(0),
        latest_metrics_change_(DisplayObserver::DISPLAY_METRIC_NONE) {}

  ~MockDisplayObserver() override {}

  void OnDisplayAdded(const Display& display) override { display_added_++; }

  void OnDisplayRemoved(const Display& display) override { display_removed_++; }

  void OnDisplayMetricsChanged(const Display& display,
                               uint32_t metrics) override {
    display_changed_++;
    latest_metrics_change_ = metrics;
  }

  int display_added() const { return display_added_; }

  int display_removed() const { return display_removed_; }

  int display_changed() const { return display_changed_; }

  uint32_t latest_metrics_change() const { return latest_metrics_change_; }

 protected:
  int display_added_;
  int display_removed_;
  int display_changed_;
  uint32_t latest_metrics_change_;

  DISALLOW_COPY_AND_ASSIGN(MockDisplayObserver);
};

TEST(DisplayChangeNotifierTest, AddObserver_Smoke) {
  DisplayChangeNotifier change_notifier;
  MockDisplayObserver observer;

  change_notifier.NotifyDisplaysChanged(std::vector<Display>(),
                                        std::vector<Display>(1, Display()));
  EXPECT_EQ(0, observer.display_added());

  change_notifier.AddObserver(&observer);
  change_notifier.NotifyDisplaysChanged(std::vector<Display>(),
                                        std::vector<Display>(1, Display()));
  EXPECT_EQ(1, observer.display_added());
}

TEST(DisplayChangeNotifier, RemoveObserver_Smoke) {
  DisplayChangeNotifier change_notifier;
  MockDisplayObserver observer;

  change_notifier.NotifyDisplaysChanged(std::vector<Display>(),
                                        std::vector<Display>(1, Display()));
  EXPECT_EQ(0, observer.display_added());

  change_notifier.AddObserver(&observer);
  change_notifier.RemoveObserver(&observer);

  change_notifier.NotifyDisplaysChanged(std::vector<Display>(),
                                        std::vector<Display>(1, Display()));
  EXPECT_EQ(0, observer.display_added());
}

TEST(DisplayChangeNotifierTest, RemoveObserver_Unknown) {
  DisplayChangeNotifier change_notifier;
  MockDisplayObserver observer;

  change_notifier.RemoveObserver(&observer);
  // Should not crash.
}

TEST(DisplayChangeNotifierTest, NotifyDisplaysChanged_Removed) {
  DisplayChangeNotifier change_notifier;

  // If the previous display array is empty, no removal.
  {
    MockDisplayObserver observer;
    change_notifier.AddObserver(&observer);

    std::vector<Display> old_displays, new_displays;
    new_displays.push_back(Display());

    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
    EXPECT_EQ(0, observer.display_removed());

    change_notifier.RemoveObserver(&observer);
  }

  // If the previous and new display array are empty, no removal.
  {
    MockDisplayObserver observer;
    change_notifier.AddObserver(&observer);

    std::vector<Display> old_displays, new_displays;

    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
    EXPECT_EQ(0, observer.display_removed());

    change_notifier.RemoveObserver(&observer);
  }

  // If the new display array is empty, there are as many removal as old
  // displays.
  {
    MockDisplayObserver observer;
    change_notifier.AddObserver(&observer);

    std::vector<Display> old_displays, new_displays;
    old_displays.push_back(Display());
    old_displays.push_back(Display());
    old_displays.push_back(Display());

    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
    EXPECT_EQ(3, observer.display_removed());

    change_notifier.RemoveObserver(&observer);
  }

  // If displays don't use ids, as long as the new display array has one
  // element, there are no removals.
  {
    MockDisplayObserver observer;
    change_notifier.AddObserver(&observer);

    std::vector<Display> old_displays, new_displays;
    old_displays.push_back(Display());
    old_displays.push_back(Display());
    old_displays.push_back(Display());
    new_displays.push_back(Display());

    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
    EXPECT_EQ(0, observer.display_removed());

    change_notifier.RemoveObserver(&observer);
  }

  // If displays use ids (and they are unique), ids not present in the new
  // display array will be marked as removed.
  {
    MockDisplayObserver observer;
    change_notifier.AddObserver(&observer);

    std::vector<Display> old_displays, new_displays;
    old_displays.push_back(Display(1));
    old_displays.push_back(Display(2));
    old_displays.push_back(Display(3));
    new_displays.push_back(Display(2));

    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
    EXPECT_EQ(2, observer.display_removed());

    change_notifier.RemoveObserver(&observer);
  }
}

TEST(DisplayChangeNotifierTest, NotifyDisplaysChanged_Added) {
  DisplayChangeNotifier change_notifier;

  // If the new display array is empty, no addition.
  {
    MockDisplayObserver observer;
    change_notifier.AddObserver(&observer);

    std::vector<Display> old_displays, new_displays;
    old_displays.push_back(Display());

    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
    EXPECT_EQ(0, observer.display_added());

    change_notifier.RemoveObserver(&observer);
  }

  // If the old and new display arrays are empty, no addition.
  {
    MockDisplayObserver observer;
    change_notifier.AddObserver(&observer);

    std::vector<Display> old_displays, new_displays;

    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
    EXPECT_EQ(0, observer.display_added());

    change_notifier.RemoveObserver(&observer);
  }

  // If the old display array is empty, there are as many addition as new
  // displays.
  {
    MockDisplayObserver observer;
    change_notifier.AddObserver(&observer);

    std::vector<Display> old_displays, new_displays;
    new_displays.push_back(Display());
    new_displays.push_back(Display());
    new_displays.push_back(Display());

    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
    EXPECT_EQ(3, observer.display_added());

    change_notifier.RemoveObserver(&observer);
  }

  // If displays don't use ids, as long as the old display array has one
  // element, there are no additions.
  {
    MockDisplayObserver observer;
    change_notifier.AddObserver(&observer);

    std::vector<Display> old_displays, new_displays;
    old_displays.push_back(Display());
    new_displays.push_back(Display());
    new_displays.push_back(Display());
    new_displays.push_back(Display());

    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
    EXPECT_EQ(0, observer.display_added());

    change_notifier.RemoveObserver(&observer);
  }

  // If displays use ids (and they are unique), ids not present in the old
  // display array will be marked as added.
  {
    MockDisplayObserver observer;
    change_notifier.AddObserver(&observer);

    std::vector<Display> old_displays, new_displays;
    old_displays.push_back(Display(1));
    new_displays.push_back(Display(1));
    new_displays.push_back(Display(2));
    new_displays.push_back(Display(3));

    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
    EXPECT_EQ(2, observer.display_added());

    change_notifier.RemoveObserver(&observer);
  }
}

TEST(DisplayChangeNotifierTest, NotifyDisplaysChanged_Changed_Smoke) {
  DisplayChangeNotifier change_notifier;

  // If the old display array is empty, no change.
  {
    MockDisplayObserver observer;
    change_notifier.AddObserver(&observer);

    std::vector<Display> old_displays, new_displays;
    new_displays.push_back(Display());

    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
    EXPECT_EQ(0, observer.display_changed());

    change_notifier.RemoveObserver(&observer);
  }

  // If the new display array is empty, no change.
  {
    MockDisplayObserver observer;
    change_notifier.AddObserver(&observer);

    std::vector<Display> old_displays, new_displays;
    old_displays.push_back(Display());

    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
    EXPECT_EQ(0, observer.display_changed());

    change_notifier.RemoveObserver(&observer);
  }

  // If the old and new display arrays are empty, no change.
  {
    MockDisplayObserver observer;
    change_notifier.AddObserver(&observer);

    std::vector<Display> old_displays, new_displays;

    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
    EXPECT_EQ(0, observer.display_changed());

    change_notifier.RemoveObserver(&observer);
  }

  // If there is an intersection between old and new displays but there are no
  // metrics changes, there is no display change.
  {
    MockDisplayObserver observer;
    change_notifier.AddObserver(&observer);

    std::vector<Display> old_displays, new_displays;
    old_displays.push_back(Display(1));
    new_displays.push_back(Display(1));
    new_displays.push_back(Display(2));
    new_displays.push_back(Display(3));

    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
    EXPECT_EQ(0, observer.display_changed());

    change_notifier.RemoveObserver(&observer);
  }
}

TEST(DisplayChangeNotifierTest, NotifyDisplaysChanged_Changed_Bounds) {
  DisplayChangeNotifier change_notifier;

  {
    MockDisplayObserver observer;
    change_notifier.AddObserver(&observer);

    std::vector<Display> old_displays, new_displays;
    old_displays.push_back(Display(1, gfx::Rect(0, 0, 200, 200)));
    new_displays.push_back(Display(1, gfx::Rect(0, 0, 200, 200)));

    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
    EXPECT_EQ(0, observer.display_changed());

    change_notifier.RemoveObserver(&observer);
  }

  {
    MockDisplayObserver observer;
    change_notifier.AddObserver(&observer);

    std::vector<Display> old_displays, new_displays;
    old_displays.push_back(Display(1, gfx::Rect(0, 0, 200, 200)));
    new_displays.push_back(Display(1, gfx::Rect(10, 10, 300, 300)));

    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
    EXPECT_EQ(1, observer.display_changed());
    uint32_t metrics_change = DisplayObserver::DISPLAY_METRIC_BOUNDS |
                              DisplayObserver::DISPLAY_METRIC_WORK_AREA;
    EXPECT_EQ(metrics_change, observer.latest_metrics_change());

    change_notifier.RemoveObserver(&observer);
  }

  {
    MockDisplayObserver observer;
    change_notifier.AddObserver(&observer);

    std::vector<Display> old_displays, new_displays;
    old_displays.push_back(Display(1, gfx::Rect(0, 0, 200, 200)));
    new_displays.push_back(Display(1, gfx::Rect(0, 0, 200, 200)));
    new_displays[0].set_bounds(gfx::Rect(10, 10, 300, 300));

    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
    EXPECT_EQ(1, observer.display_changed());
    EXPECT_EQ(static_cast<uint32_t>(DisplayObserver::DISPLAY_METRIC_BOUNDS),
              observer.latest_metrics_change());

    change_notifier.RemoveObserver(&observer);
  }
}

TEST(DisplayChangeNotifierTest, NotifyDisplaysChanged_Changed_Rotation) {
  DisplayChangeNotifier change_notifier;
  MockDisplayObserver observer;
  change_notifier.AddObserver(&observer);

  std::vector<Display> old_displays, new_displays;
  old_displays.push_back(Display(1));
  old_displays[0].SetRotationAsDegree(0);
  new_displays.push_back(Display(1));
  new_displays[0].SetRotationAsDegree(180);

  change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
  EXPECT_EQ(1, observer.display_changed());
  EXPECT_EQ(static_cast<uint32_t>(DisplayObserver::DISPLAY_METRIC_ROTATION),
            observer.latest_metrics_change());
}

TEST(DisplayChangeNotifierTest, NotifyDisplaysChanged_Changed_WorkArea) {
  DisplayChangeNotifier change_notifier;
  MockDisplayObserver observer;
  change_notifier.AddObserver(&observer);

  std::vector<Display> old_displays, new_displays;
  old_displays.push_back(Display(1));
  old_displays[0].set_work_area(gfx::Rect(0, 0, 200, 200));
  new_displays.push_back(Display(1));
  new_displays[0].set_work_area(gfx::Rect(20, 20, 300, 300));

  change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
  EXPECT_EQ(1, observer.display_changed());
  EXPECT_EQ(static_cast<uint32_t>(DisplayObserver::DISPLAY_METRIC_WORK_AREA),
            observer.latest_metrics_change());
}

TEST(DisplayChangeNotifierTest, NotifyDisplaysChanged_Changed_DSF) {
  DisplayChangeNotifier change_notifier;
  MockDisplayObserver observer;
  change_notifier.AddObserver(&observer);

  std::vector<Display> old_displays, new_displays;
  old_displays.push_back(Display(1));
  old_displays[0].set_device_scale_factor(1.f);
  new_displays.push_back(Display(1));
  new_displays[0].set_device_scale_factor(2.f);

  change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
  EXPECT_EQ(1, observer.display_changed());
  EXPECT_EQ(static_cast<uint32_t>(
                DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR),
            observer.latest_metrics_change());
}

TEST(DisplayChangeNotifierTest, NotifyDisplaysChanged_Changed_Multi_Displays) {
  DisplayChangeNotifier change_notifier;
  MockDisplayObserver observer;
  change_notifier.AddObserver(&observer);

  std::vector<Display> old_displays, new_displays;
  old_displays.push_back(Display(1));
  old_displays.push_back(Display(2));
  old_displays.push_back(Display(3));
  new_displays.push_back(Display(1));
  new_displays.push_back(Display(2));
  new_displays.push_back(Display(3));

  old_displays[0].set_device_scale_factor(1.f);
  new_displays[0].set_device_scale_factor(2.f);

  old_displays[1].set_bounds(gfx::Rect(0, 0, 200, 200));
  new_displays[1].set_bounds(gfx::Rect(0, 0, 400, 400));

  old_displays[2].SetRotationAsDegree(0);
  new_displays[2].SetRotationAsDegree(90);

  change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
  EXPECT_EQ(3, observer.display_changed());
}

TEST(DisplayChangeNotifierTest, NotifyDisplaysChanged_Changed_Multi_Metrics) {
  DisplayChangeNotifier change_notifier;
  MockDisplayObserver observer;
  change_notifier.AddObserver(&observer);

  std::vector<Display> old_displays, new_displays;
  old_displays.push_back(Display(1, gfx::Rect(0, 0, 200, 200)));
  old_displays[0].set_device_scale_factor(1.f);
  old_displays[0].SetRotationAsDegree(0);

  new_displays.push_back(Display(1, gfx::Rect(100, 100, 200, 200)));
  new_displays[0].set_device_scale_factor(2.f);
  new_displays[0].SetRotationAsDegree(90);

  change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
  EXPECT_EQ(1, observer.display_changed());
  uint32_t metrics = DisplayObserver::DISPLAY_METRIC_BOUNDS |
                     DisplayObserver::DISPLAY_METRIC_ROTATION |
                     DisplayObserver::DISPLAY_METRIC_WORK_AREA |
                     DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR;
  EXPECT_EQ(metrics, observer.latest_metrics_change());
}

}  // namespace display
