// Copyright 2020 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/cssom/percentage_value.h"
#include "cobalt/cssom/testing/mock_css_parser.h"
#include "cobalt/dom/document.h"
#include "cobalt/dom/dom_stat_tracker.h"
#include "cobalt/dom/element.h"
#include "cobalt/dom/html_element_context.h"
#include "cobalt/dom/testing/fake_exception_state.h"
#include "cobalt/dom/testing/mock_layout_boxes.h"
#include "cobalt/dom/testing/stub_environment_settings.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using cobalt::cssom::PercentageValue;
using cobalt::cssom::PropertyListValue;
using cobalt::dom::testing::MockLayoutBoxes;
using ::testing::NiceMock;
using ::testing::_;
using ::testing::Return;

namespace cobalt {
namespace dom {

class MockDocumentObserver : public DocumentObserver {
 public:
  MOCK_METHOD0(OnLoad, void());

  MOCK_METHOD0(OnMutation, void());

  MOCK_METHOD0(OnFocusChanged, void());
};

class IntersectionCallbackMock {
 public:
  MOCK_METHOD2(
      NativeIntersectionObserverCallback,
      void(const IntersectionObserver::IntersectionObserverEntrySequence&,
           const scoped_refptr<IntersectionObserver>&));
};

class IntersectionObserverTest : public ::testing::Test {
 protected:
  IntersectionObserverTest()
      : dom_stat_tracker_(new DomStatTracker("IntersectionObserverTest")),
        html_element_context_(&environment_settings_, NULL, NULL, &css_parser_,
                              NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                              NULL, NULL, NULL, NULL, dom_stat_tracker_.get(),
                              "", base::kApplicationStateStarted, NULL),
        document_(new Document(&html_element_context_)) {}

  scoped_refptr<Document> document() { return document_; }
  scoped_refptr<IntersectionObserver> CreateIntersectionObserver();
  void CreateDocumentWithTwoChildrenAndMockLayoutBoxes();

 private:
  std::unique_ptr<DomStatTracker> dom_stat_tracker_;
  testing::StubEnvironmentSettings environment_settings_;
  NiceMock<cssom::testing::MockCSSParser> css_parser_;
  testing::FakeExceptionState exception_state_;
  HTMLElementContext html_element_context_;
  scoped_refptr<Document> document_;
  IntersectionCallbackMock callback_mock_;
};

scoped_refptr<IntersectionObserver>
IntersectionObserverTest::CreateIntersectionObserver() {
  // The intersection observer constructor will use the mock css parser to parse
  // the root margin property value. Because "ParsePropertyValue()"" returns a
  // "PropertyValue", which is not a built-in type, we must set a default
  // action and return type here.
  std::unique_ptr<PropertyListValue::Builder> builder(
      new PropertyListValue::Builder());
  builder->push_back(new PercentageValue(0.0f));
  scoped_refptr<PropertyListValue> property_list_value =
      new PropertyListValue(std::move(builder));
  ON_CALL(css_parser_, ParsePropertyValue(_, _, _))
      .WillByDefault(Return(property_list_value));

  return new IntersectionObserver(
      document_, &css_parser_,
      base::Bind(&IntersectionCallbackMock::NativeIntersectionObserverCallback,
                 base::Unretained(&callback_mock_)),
      &exception_state_);
}

void IntersectionObserverTest::
    CreateDocumentWithTwoChildrenAndMockLayoutBoxes() {
  scoped_refptr<HTMLElement> first_child_element_ =
      document_->CreateElement("div")->AsHTMLElement();
  document_->AppendChild(first_child_element_);

  scoped_refptr<HTMLElement> second_child_element_ =
      document_->CreateElement("div")->AsHTMLElement();
  first_child_element_->AppendChild(second_child_element_);

  std::unique_ptr<MockLayoutBoxes> layout_boxes(new MockLayoutBoxes);
  document_->document_element()->AsHTMLElement()->set_layout_boxes(
      std::unique_ptr<LayoutBoxes>(layout_boxes.release()));
}

TEST_F(IntersectionObserverTest, RegisterIntersectionObserverForTarget) {
  CreateDocumentWithTwoChildrenAndMockLayoutBoxes();

  NiceMock<MockDocumentObserver> document_observer;
  document()->AddObserver(&document_observer);

  std::unique_ptr<ElementIntersectionObserverModule>
      element_intersection_observer_module =
          std::make_unique<ElementIntersectionObserverModule>(
              document()->last_element_child());

  // Treat the second child element as an intersection observer target
  // (the first child element is the same as the document element).
  // When the observer is registered, it should record a mutation on the
  // document and invalidate the layout boxes up to the document element.
  EXPECT_NE(document()->document_element()->AsHTMLElement()->layout_boxes(),
            nullptr);
  EXPECT_CALL(document_observer, OnMutation()).Times(1);
  scoped_refptr<IntersectionObserver> intersection_observer =
      CreateIntersectionObserver();
  element_intersection_observer_module->RegisterIntersectionObserverForTarget(
      intersection_observer);
  EXPECT_EQ(document()->document_element()->AsHTMLElement()->layout_boxes(),
            nullptr);
}

}  // namespace dom
}  // namespace cobalt
