// Copyright 2019 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/dom/element_intersection_observer_module.h"

#include <algorithm>

#include "cobalt/dom/document.h"
#include "cobalt/dom/dom_rect_read_only.h"
#include "cobalt/dom/element.h"
#include "cobalt/dom/intersection_observer_entry_init.h"
#include "cobalt/dom/performance.h"

namespace cobalt {
namespace dom {

ElementIntersectionObserverModule::ElementIntersectionObserverModule(
    Element* element)
    : element_(element) {}

ElementIntersectionObserverModule::~ElementIntersectionObserverModule() {
  // The intersection observer vectors may hold the last reference to the
  // corresponding intersection observer object. Since the intersection observer
  // dtor calls UnregisterIntersectionObserverForRoot, make sure the call
  // doesn't try to release the scoped_refptr<IntersectionObserver> again during
  // destruction.
  IntersectionObserverVector temp_root_registered_observers;
  IntersectionObserverVector temp_target_registered_observers;

  // Swap out the intersection observer vectors so that the call to
  // UnregisterIntersectionObserverForRoot won't do anything, as the objects are
  // already being destroyed here.
  temp_root_registered_observers.swap(root_registered_intersection_observers_);
  temp_target_registered_observers.swap(
      target_registered_intersection_observers_);

  // Force destruction of the intersection observer objects here so that the
  // call to UnregisterIntersectionObserverForRoot occurs before this object is
  // fully destroyed.
  temp_root_registered_observers.clear();
  temp_target_registered_observers.clear();
}

void ElementIntersectionObserverModule::RegisterIntersectionObserverForRoot(
    IntersectionObserver* observer) {
  auto it = std::find(root_registered_intersection_observers_.begin(),
                      root_registered_intersection_observers_.end(), observer);
  if (it != root_registered_intersection_observers_.end()) {
    return;
  }
  root_registered_intersection_observers_.push_back(
      base::WrapRefCounted(observer));

  // Also create the observer's layout root at this time.
  scoped_refptr<layout::IntersectionObserverRoot> new_root =
      new layout::IntersectionObserverRoot(
          observer->root_margin_property_value(),
          observer->thresholds_vector());
  observer->set_layout_root(new_root);

  InvalidateLayoutBoxesForElement();
}

void ElementIntersectionObserverModule::UnregisterIntersectionObserverForRoot(
    IntersectionObserver* observer) {
  auto it = std::find(root_registered_intersection_observers_.begin(),
                      root_registered_intersection_observers_.end(), observer);
  if (it != root_registered_intersection_observers_.end()) {
    root_registered_intersection_observers_.erase(it);
    InvalidateLayoutBoxesForElement();
    return;
  }
  DLOG(WARNING)
      << "Did not find an intersection observer to unregister for the root.";
}

void ElementIntersectionObserverModule::RegisterIntersectionObserverForTarget(
    IntersectionObserver* observer) {
  auto it =
      std::find(target_registered_intersection_observers_.begin(),
                target_registered_intersection_observers_.end(), observer);
  if (it != target_registered_intersection_observers_.end()) {
    return;
  }
  target_registered_intersection_observers_.push_back(
      base::WrapRefCounted(observer));
  AddLayoutTargetForObserver(observer);

  InvalidateLayoutBoxesForElement();
}

void ElementIntersectionObserverModule::UnregisterIntersectionObserverForTarget(
    IntersectionObserver* observer) {
  auto it =
      std::find(target_registered_intersection_observers_.begin(),
                target_registered_intersection_observers_.end(), observer);
  if (it != target_registered_intersection_observers_.end()) {
    target_registered_intersection_observers_.erase(it);
    RemoveLayoutTargetForObserver(observer);
    InvalidateLayoutBoxesForElement();
    return;
  }
  DLOG(WARNING)
      << "Did not find an intersection observer to unregister for the target.";
}

ElementIntersectionObserverModule::LayoutIntersectionObserverRootVector
ElementIntersectionObserverModule::
    GetLayoutIntersectionObserverRootsForElement() {
  ElementIntersectionObserverModule::LayoutIntersectionObserverRootVector
      layout_roots;
  for (const auto& intersection_observer :
       root_registered_intersection_observers_) {
    layout_roots.push_back(intersection_observer->layout_root());
  }
  return layout_roots;
}

ElementIntersectionObserverModule::LayoutIntersectionObserverTargetVector
ElementIntersectionObserverModule::
    GetLayoutIntersectionObserverTargetsForElement() {
  return layout_targets_;
}

void ElementIntersectionObserverModule::
    CreateIntersectionObserverEntryForObserver(
        const base::WeakPtr<IntersectionObserver>& observer,
        math::RectF root_bounds, math::RectF target_rect,
        math::RectF intersection_rect, bool is_intersecting,
        float intersection_ratio) {
  if (!observer) {
    return;
  }

  IntersectionObserverEntryInit init_dict;
  init_dict.set_time(element_->owner_document()
                         ->window()
                         ->performance()
                         ->timing()
                         ->GetNavigationStartClock()
                         ->Now()
                         .InMillisecondsF());
  init_dict.set_root_bounds(
      base::WrapRefCounted(new DOMRectReadOnly(root_bounds)));
  init_dict.set_bounding_client_rect(
      base::WrapRefCounted(new DOMRectReadOnly(target_rect)));
  init_dict.set_intersection_rect(
      base::WrapRefCounted(new DOMRectReadOnly(intersection_rect)));
  init_dict.set_is_intersecting(is_intersecting);
  init_dict.set_intersection_ratio(intersection_ratio);
  init_dict.set_target(base::WrapRefCounted(element_));
  observer->QueueIntersectionObserverEntry(
      base::WrapRefCounted(new IntersectionObserverEntry(init_dict)));
}

void ElementIntersectionObserverModule::TraceMembers(script::Tracer* tracer) {
  tracer->TraceItems(root_registered_intersection_observers_);
  tracer->TraceItems(target_registered_intersection_observers_);
}

void ElementIntersectionObserverModule::AddLayoutTargetForObserver(
    IntersectionObserver* observer) {
  layout::IntersectionObserverTarget::OnIntersectionCallback
      on_intersection_callback =
          base::Bind(&ElementIntersectionObserverModule::
                         CreateIntersectionObserverEntryForObserver,
                     base::Unretained(this), base::AsWeakPtr(observer));
  scoped_refptr<layout::IntersectionObserverTarget> layout_target =
      new layout::IntersectionObserverTarget(on_intersection_callback,
                                             observer->layout_root());
  layout_targets_.push_back(layout_target);
}

void ElementIntersectionObserverModule::RemoveLayoutTargetForObserver(
    IntersectionObserver* observer) {
  for (auto it = layout_targets_.begin(); it != layout_targets_.end(); ++it) {
    if ((*it)->intersection_observer_root() == observer->layout_root()) {
      layout_targets_.erase(it);
      return;
    }
  }
  NOTREACHED() << "Did not find a layout target to remove";
}

void ElementIntersectionObserverModule::InvalidateLayoutBoxesForElement() {
  HTMLElement* html_element = element_->AsHTMLElement();
  if (!html_element) {
    NOTREACHED();
    return;
  }
  html_element->InvalidateLayoutBoxesOfNodeAndDescendants();
}

}  // namespace dom
}  // namespace cobalt
