// Copyright 2017 Google Inc. 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/layout/topmost_event_target.h"

#include <string>

#include "cobalt/base/token.h"
#include "cobalt/base/tokens.h"
#include "cobalt/cssom/keyword_value.h"
#include "cobalt/dom/document.h"
#include "cobalt/dom/event.h"
#include "cobalt/dom/html_element.h"
#include "cobalt/dom/html_html_element.h"
#include "cobalt/dom/mouse_event.h"
#include "cobalt/dom/mouse_event_init.h"
#include "cobalt/dom/pointer_event.h"
#include "cobalt/dom/pointer_event_init.h"
#include "cobalt/dom/ui_event.h"
#include "cobalt/dom/wheel_event.h"
#include "cobalt/layout/container_box.h"
#include "cobalt/layout/used_style.h"
#include "cobalt/math/vector2d.h"
#include "cobalt/math/vector2d_f.h"

namespace cobalt {
namespace layout {

void TopmostEventTarget::FindTopmostEventTarget(
    const scoped_refptr<dom::Document>& document,
    const math::Vector2dF& coordinate) {
  const scoped_refptr<dom::HTMLElement>& html_element = document->html();
  DCHECK(!box_);
  DCHECK(render_sequence_.empty());
  html_element_ = html_element;
  if (html_element) {
    dom::LayoutBoxes* boxes = html_element->layout_boxes();
    if (boxes && boxes->type() == dom::LayoutBoxes::kLayoutLayoutBoxes) {
      LayoutBoxes* layout_boxes = base::polymorphic_downcast<LayoutBoxes*>(
          html_element->layout_boxes());
      if (!layout_boxes->boxes().empty()) {
        ConsiderElement(html_element, coordinate);
      }
    }
  }
  box_ = NULL;
  render_sequence_.clear();
}

void TopmostEventTarget::ConsiderElement(
    const scoped_refptr<dom::HTMLElement>& html_element,
    const math::Vector2dF& coordinate) {
  if (!html_element) return;
  math::Vector2dF element_coordinate(coordinate);
  if (html_element->CanbeDesignatedByPointerIfDisplayed()) {
    dom::LayoutBoxes* dom_layout_boxes = html_element->layout_boxes();
    if (dom_layout_boxes &&
        dom_layout_boxes->type() == dom::LayoutBoxes::kLayoutLayoutBoxes) {
      DCHECK(html_element->computed_style());
      LayoutBoxes* layout_boxes =
          base::polymorphic_downcast<LayoutBoxes*>(dom_layout_boxes);
      const Boxes& boxes = layout_boxes->boxes();
      if (!boxes.empty()) {
        const Box* box = boxes.front();
        box->UpdateCoordinateForTransform(&element_coordinate);
        ConsiderBoxes(html_element, layout_boxes, element_coordinate);
      }
    }
  }

  for (dom::Element* element = html_element->first_element_child(); element;
       element = element->next_element_sibling()) {
    dom::HTMLElement* child_html_element = element->AsHTMLElement();
    if (child_html_element && child_html_element->computed_style()) {
      ConsiderElement(child_html_element, element_coordinate);
    }
  }
}

void TopmostEventTarget::ConsiderBoxes(
    const scoped_refptr<dom::HTMLElement>& html_element,
    LayoutBoxes* layout_boxes, const math::Vector2dF& coordinate) {
  const Boxes& boxes = layout_boxes->boxes();
  Vector2dLayoutUnit layout_coordinate(LayoutUnit(coordinate.x()),
                                       LayoutUnit(coordinate.y()));
  for (Boxes::const_iterator box_iterator = boxes.begin();
       box_iterator != boxes.end(); ++box_iterator) {
    Box* box = *box_iterator;
    do {
      if (box->IsUnderCoordinate(layout_coordinate)) {
        Box::RenderSequence render_sequence = box->GetRenderSequence();
        if (Box::IsRenderedLater(render_sequence, render_sequence_)) {
          html_element_ = html_element;
          box_ = box;
          render_sequence_.swap(render_sequence);
        }
      }
      box = box->GetSplitSibling();
    } while (box != NULL);
  }
}

void TopmostEventTarget::MaybeSendPointerEvents(
    const scoped_refptr<dom::Event>& event) {
  const dom::MouseEvent* const mouse_event =
      base::polymorphic_downcast<const dom::MouseEvent* const>(event.get());
  DCHECK(mouse_event);
  DCHECK(!html_element_);
  scoped_refptr<dom::Window> view = mouse_event->view();

  math::Vector2dF coordinate(static_cast<float>(mouse_event->client_x()),
                             static_cast<float>(mouse_event->client_y()));
  FindTopmostEventTarget(view->document(), coordinate);

  if (html_element_) {
    html_element_->DispatchEvent(event);
  }
  if (event->GetWrappableType() == base::GetTypeId<dom::PointerEvent>()) {
    const dom::PointerEvent* const pointer_event =
        base::polymorphic_downcast<const dom::PointerEvent* const>(event.get());

    // Send compatibility mapping mouse events if needed.
    //  https://www.w3.org/TR/2015/REC-pointerevents-20150224/#compatibility-mapping-with-mouse-events
    if (html_element_) {
      bool has_compatibility_mouse_event = false;
      base::Token type;
      if (pointer_event->type() == base::Tokens::pointerdown()) {
        type = base::Tokens::mousedown();
        has_compatibility_mouse_event = true;
      } else if (pointer_event->type() == base::Tokens::pointerup()) {
        type = base::Tokens::mouseup();
        has_compatibility_mouse_event = true;
      } else if (pointer_event->type() == base::Tokens::pointermove()) {
        type = base::Tokens::mousemove();
        has_compatibility_mouse_event = true;
      }
      if (has_compatibility_mouse_event) {
        dom::MouseEventInit mouse_event_init;
        mouse_event_init.set_screen_x(pointer_event->screen_x());
        mouse_event_init.set_screen_y(pointer_event->screen_y());
        mouse_event_init.set_client_x(pointer_event->screen_x());
        mouse_event_init.set_client_y(pointer_event->screen_y());
        mouse_event_init.set_button(pointer_event->button());
        mouse_event_init.set_buttons(pointer_event->buttons());
        html_element_->DispatchEvent(
            new dom::MouseEvent(type, view, mouse_event_init));
        if (pointer_event->type() == base::Tokens::pointerup()) {
          type = base::Tokens::click();
          html_element_->DispatchEvent(
              new dom::MouseEvent(type, view, mouse_event_init));
        }
      }
    }

    scoped_refptr<dom::HTMLElement> previous_html_element(
        previous_html_element_weak_);

    // Send enter/leave/over/out (status change) events when needed.
    if (previous_html_element != html_element_) {
      // Store the data for the status change event(s).
      dom::PointerEventInit event_init;
      event_init.set_related_target(previous_html_element);
      event_init.set_screen_x(mouse_event->screen_x());
      event_init.set_screen_y(mouse_event->screen_y());
      event_init.set_client_x(mouse_event->screen_x());
      event_init.set_client_y(mouse_event->screen_y());
      if (event->GetWrappableType() == base::GetTypeId<dom::PointerEvent>()) {
        event_init.set_pointer_id(pointer_event->pointer_id());
        event_init.set_width(pointer_event->width());
        event_init.set_height(pointer_event->height());
        event_init.set_pressure(pointer_event->pressure());
        event_init.set_tilt_x(pointer_event->tilt_x());
        event_init.set_tilt_y(pointer_event->tilt_y());
        event_init.set_pointer_type(pointer_event->pointer_type());
        event_init.set_is_primary(pointer_event->is_primary());
      }

      // The enter/leave status change events apply to all ancestors up to the
      // nearest common ancestor between the previous and current element.
      scoped_refptr<dom::Element> nearest_common_ancestor;

      if (previous_html_element) {
        previous_html_element->DispatchEvent(new dom::PointerEvent(
            base::Tokens::pointerout(), view, event_init));
        previous_html_element->DispatchEvent(
            new dom::MouseEvent(base::Tokens::mouseout(), view, event_init));

        // Find the nearest common ancestor, if there is any.
        dom::Document* previous_document =
            previous_html_element->node_document();
        if (previous_document) {
          if (html_element_ &&
              previous_document == html_element_->node_document()) {
            // The nearest ancestor of the current element that is already
            // designated is the nearest common ancestor of it and the previous
            // element.
            nearest_common_ancestor = html_element_;
            while (nearest_common_ancestor &&
                   nearest_common_ancestor->AsHTMLElement() &&
                   !nearest_common_ancestor->AsHTMLElement()->IsDesignated()) {
              nearest_common_ancestor =
                  nearest_common_ancestor->parent_element();
            }
          }

          for (scoped_refptr<dom::Element> element = previous_html_element;
               element != nearest_common_ancestor;
               element = element->parent_element()) {
            element->DispatchEvent(new dom::PointerEvent(
                base::Tokens::pointerleave(), dom::Event::kNotBubbles,
                dom::Event::kNotCancelable, view, event_init));
            element->DispatchEvent(new dom::MouseEvent(
                base::Tokens::mouseleave(), dom::Event::kNotBubbles,
                dom::Event::kNotCancelable, view, event_init));
          }

          if (!html_element_ ||
              previous_document != html_element_->node_document()) {
            previous_document->SetIndicatedElement(NULL);
          }
        }
      }
      if (html_element_) {
        html_element_->DispatchEvent(new dom::PointerEvent(
            base::Tokens::pointerover(), view, event_init));
        html_element_->DispatchEvent(
            new dom::MouseEvent(base::Tokens::mouseover(), view, event_init));

        for (scoped_refptr<dom::Element> element = html_element_;
             element != nearest_common_ancestor;
             element = element->parent_element()) {
          element->DispatchEvent(new dom::PointerEvent(
              base::Tokens::pointerenter(), dom::Event::kNotBubbles,
              dom::Event::kNotCancelable, view, event_init));
          element->DispatchEvent(new dom::MouseEvent(
              base::Tokens::mouseenter(), dom::Event::kNotBubbles,
              dom::Event::kNotCancelable, view, event_init));
        }

        dom::Document* document = html_element_->node_document();
        if (document) {
          document->SetIndicatedElement(html_element_);
        }
      }
      previous_html_element_weak_ = base::AsWeakPtr(html_element_.get());
    }
  }
  html_element_ = NULL;
}

}  // namespace layout
}  // namespace cobalt
