// Copyright 2017 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/mouse_event.h"

#include <string>

#include "cobalt/base/token.h"
#include "cobalt/dom/html_element.h"

namespace cobalt {
namespace dom {

MouseEvent::MouseEvent(const std::string& type)
    : UIEventWithKeyState(base::Token(type), kBubbles, kCancelable, NULL),
      screen_x_(0),
      screen_y_(0),
      client_x_(0),
      client_y_(0),
      button_(0),
      buttons_(0) {}

MouseEvent::MouseEvent(const std::string& type, const MouseEventInit& init_dict)
    : UIEventWithKeyState(base::Token(type), kBubbles, kCancelable,
                          init_dict.view(), init_dict),
      screen_x_(static_cast<float>(init_dict.screen_x())),
      screen_y_(static_cast<float>(init_dict.screen_y())),
      client_x_(static_cast<float>(init_dict.client_x())),
      client_y_(static_cast<float>(init_dict.client_y())),
      button_(init_dict.button()),
      buttons_(init_dict.buttons()),
      related_target_(init_dict.related_target()) {}

MouseEvent::MouseEvent(base::Token type, const scoped_refptr<Window>& view,
                       const MouseEventInit& init_dict)
    : UIEventWithKeyState(type, kBubbles, kCancelable, view, init_dict),
      screen_x_(static_cast<float>(init_dict.screen_x())),
      screen_y_(static_cast<float>(init_dict.screen_y())),
      client_x_(static_cast<float>(init_dict.client_x())),
      client_y_(static_cast<float>(init_dict.client_y())),
      button_(init_dict.button()),
      buttons_(init_dict.buttons()),
      related_target_(init_dict.related_target()) {}

MouseEvent::MouseEvent(base::Token type, Bubbles bubbles, Cancelable cancelable,
                       const scoped_refptr<Window>& view,
                       const MouseEventInit& init_dict)
    : UIEventWithKeyState(type, bubbles, cancelable, view, init_dict),
      screen_x_(static_cast<float>(init_dict.screen_x())),
      screen_y_(static_cast<float>(init_dict.screen_y())),
      client_x_(static_cast<float>(init_dict.client_x())),
      client_y_(static_cast<float>(init_dict.client_y())),
      button_(init_dict.button()),
      buttons_(init_dict.buttons()),
      related_target_(init_dict.related_target()) {}

MouseEvent::MouseEvent(UninitializedFlag uninitialized_flag)
    : UIEventWithKeyState(uninitialized_flag),
      screen_x_(0),
      screen_y_(0),
      client_x_(0),
      client_y_(0),
      button_(0),
      buttons_(0) {}

void MouseEvent::InitMouseEvent(
    const std::string& type, bool bubbles, bool cancelable,
    const scoped_refptr<Window>& view, int32 detail, int32 screen_x,
    int32 screen_y, int32 client_x, int32 client_y, bool ctrl_key, bool alt_key,
    bool shift_key, bool meta_key, uint16 button,
    const scoped_refptr<web::EventTarget>& related_target) {
  InitUIEventWithKeyState(type, bubbles, cancelable, view, detail, ctrl_key,
                          alt_key, shift_key, meta_key);
  screen_x_ = screen_x;
  screen_y_ = screen_y;
  client_x_ = client_x;
  client_y_ = client_y;
  button_ = button;
  buttons_ = 0;
  related_target_ = related_target;
}

void MouseEvent::InitMouseEvent(
    const std::string& type, bool bubbles, bool cancelable,
    const scoped_refptr<Window>& view, int32 detail, int32 screen_x,
    int32 screen_y, int32 client_x, int32 client_y,
    const std::string& modifierslist, uint16 button,
    const scoped_refptr<web::EventTarget>& related_target) {
  InitUIEventWithKeyState(type, bubbles, cancelable, view, detail,
                          modifierslist);
  screen_x_ = screen_x;
  screen_y_ = screen_y;
  client_x_ = client_x;
  client_y_ = client_y;
  button_ = button;
  buttons_ = 0;
  related_target_ = related_target;
}

float MouseEvent::page_x() const {
  // Algorithm for pageX
  //  https://www.w3.org/TR/2013/WD-cssom-view-20131217/#dom-mouseevent-pagex

  // In Cobalt all steps are equivalent to returning clientX.
  return static_cast<float>(client_x());
}

float MouseEvent::page_y() const {
  // Algorithm for pageY
  //  https://www.w3.org/TR/2013/WD-cssom-view-20131217/#dom-mouseevent-pagey

  // In Cobalt all steps are equivalent to returning clientY.
  return static_cast<float>(client_y());
}

float MouseEvent::offset_x() {
  // Algorithm for offsetX
  //  https://www.w3.org/TR/2013/WD-cssom-view-20131217/#dom-mouseevent-offsetx

  // If the event's dispatch flag is set,
  if (IsBeingDispatched()) {
    // return the x-coordinate of the position where the event occurred relative
    // to the origin of the padding edge of the target node, ignoring the
    // transforms that apply to the element and its ancestors and terminate
    // these steps.
    float target_node_padding_edge = 0.0f;

    Node* node = base::polymorphic_downcast<Node*>(target().get());
    if (node && node->IsElement()) {
      scoped_refptr<HTMLElement> html_element =
          node->AsElement()->AsHTMLElement();
      if (html_element && html_element->layout_boxes()) {
        target_node_padding_edge =
            html_element->layout_boxes()->GetPaddingEdgeOffset().x();
      }
    }
    return client_x() - target_node_padding_edge;
  }

  // Return the value of the event's pageX attribute.
  return page_x();
}

float MouseEvent::offset_y() const {
  // Algorithm for offsetY
  //  https://www.w3.org/TR/2013/WD-cssom-view-20131217/#dom-mouseevent-offsety

  // If the event's dispatch flag is set,
  if (IsBeingDispatched()) {
    // return the y-coordinate of the position where the event occurred relative
    // to the origin of the padding edge of the target node, ignoring the
    // transforms that apply to the element and its ancestors, and terminate
    // these steps.
    float target_node_padding_edge = 0.0f;

    Node* node = base::polymorphic_downcast<Node*>(target().get());
    if (node && node->IsElement()) {
      scoped_refptr<HTMLElement> html_element =
          node->AsElement()->AsHTMLElement();
      if (html_element && html_element->layout_boxes()) {
        target_node_padding_edge =
            html_element->layout_boxes()->GetPaddingEdgeOffset().y();
      }
    }
    return client_y() - target_node_padding_edge;
  }

  // Return the value of the event's pageY attribute.
  return page_y();
}

uint32 MouseEvent::which() const { return button_ + 1; }

void MouseEvent::TraceMembers(script::Tracer* tracer) {
  UIEventWithKeyState::TraceMembers(tracer);

  tracer->Trace(related_target_);
}

}  // namespace dom
}  // namespace cobalt
