/*
 * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
 * Copyright (C) 2010 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "core/html/shadow/SliderThumbElement.h"

#include "core/dom/shadow/ShadowRoot.h"
#include "core/events/Event.h"
#include "core/events/MouseEvent.h"
#include "core/events/TouchEvent.h"
#include "core/frame/EventHandlerRegistry.h"
#include "core/frame/LocalFrame.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/forms/StepRange.h"
#include "core/html/parser/HTMLParserIdioms.h"
#include "core/html/shadow/ShadowElementNames.h"
#include "core/input/EventHandler.h"
#include "core/layout/LayoutSliderContainer.h"
#include "core/layout/LayoutSliderThumb.h"
#include "core/layout/LayoutTheme.h"

namespace blink {

using namespace HTMLNames;

inline static bool hasVerticalAppearance(HTMLInputElement* input) {
  DCHECK(input->layoutObject());
  const ComputedStyle& sliderStyle = input->layoutObject()->styleRef();

  return sliderStyle.appearance() == SliderVerticalPart;
}

inline SliderThumbElement::SliderThumbElement(Document& document)
    : HTMLDivElement(document), m_inDragMode(false) {}

SliderThumbElement* SliderThumbElement::create(Document& document) {
  SliderThumbElement* element = new SliderThumbElement(document);
  element->setAttribute(idAttr, ShadowElementNames::sliderThumb());
  return element;
}

void SliderThumbElement::setPositionFromValue() {
  // Since the code to calculate position is in the LayoutSliderThumb layout
  // path, we don't actually update the value here. Instead, we poke at the
  // layoutObject directly to trigger layout.
  if (layoutObject())
    layoutObject()->setNeedsLayoutAndFullPaintInvalidation(
        LayoutInvalidationReason::SliderValueChanged);
}

LayoutObject* SliderThumbElement::createLayoutObject(const ComputedStyle&) {
  return new LayoutSliderThumb(this);
}

bool SliderThumbElement::isDisabledFormControl() const {
  return hostInput() && hostInput()->isDisabledFormControl();
}

bool SliderThumbElement::matchesReadOnlyPseudoClass() const {
  return hostInput() && hostInput()->matchesReadOnlyPseudoClass();
}

bool SliderThumbElement::matchesReadWritePseudoClass() const {
  return hostInput() && hostInput()->matchesReadWritePseudoClass();
}

Node* SliderThumbElement::focusDelegate() {
  return hostInput();
}

void SliderThumbElement::dragFrom(const LayoutPoint& point) {
  startDragging();
  setPositionFromPoint(point);
}

void SliderThumbElement::setPositionFromPoint(const LayoutPoint& point) {
  HTMLInputElement* input(hostInput());
  Element* trackElement = input->userAgentShadowRoot()->getElementById(
      ShadowElementNames::sliderTrack());

  if (!input->layoutObject() || !layoutBox() || !trackElement->layoutBox())
    return;

  LayoutPoint offset = roundedLayoutPoint(
      input->layoutObject()->absoluteToLocal(FloatPoint(point), UseTransforms));
  bool isVertical = hasVerticalAppearance(input);
  bool isLeftToRightDirection = layoutBox()->style()->isLeftToRightDirection();
  LayoutUnit trackSize;
  LayoutUnit position;
  LayoutUnit currentPosition;
  // We need to calculate currentPosition from absolute points becaue the
  // layoutObject for this node is usually on a layer and layoutBox()->x() and
  // y() are unusable.
  // FIXME: This should probably respect transforms.
  LayoutPoint absoluteThumbOrigin =
      layoutBox()->absoluteBoundingBoxRectIgnoringTransforms().location();
  LayoutPoint absoluteSliderContentOrigin =
      roundedLayoutPoint(input->layoutObject()->localToAbsolute());
  IntRect trackBoundingBox =
      trackElement->layoutObject()->absoluteBoundingBoxRectIgnoringTransforms();
  IntRect inputBoundingBox =
      input->layoutObject()->absoluteBoundingBoxRectIgnoringTransforms();
  if (isVertical) {
    trackSize = trackElement->layoutBox()->contentHeight() -
                layoutBox()->size().height();
    position = offset.y() - layoutBox()->size().height() / 2 -
               trackBoundingBox.y() + inputBoundingBox.y() -
               layoutBox()->marginBottom();
    currentPosition = absoluteThumbOrigin.y() - absoluteSliderContentOrigin.y();
  } else {
    trackSize =
        trackElement->layoutBox()->contentWidth() - layoutBox()->size().width();
    position = offset.x() - layoutBox()->size().width() / 2 -
               trackBoundingBox.x() + inputBoundingBox.x();
    position -= isLeftToRightDirection ? layoutBox()->marginLeft()
                                       : layoutBox()->marginRight();
    currentPosition = absoluteThumbOrigin.x() - absoluteSliderContentOrigin.x();
  }
  position = std::min(position, trackSize).clampNegativeToZero();
  const Decimal ratio =
      Decimal::fromDouble(static_cast<double>(position) / trackSize);
  const Decimal fraction =
      isVertical || !isLeftToRightDirection ? Decimal(1) - ratio : ratio;
  StepRange stepRange(input->createStepRange(RejectAny));
  Decimal value = stepRange.clampValue(stepRange.valueFromProportion(fraction));

  Decimal closest = input->findClosestTickMarkValue(value);
  if (closest.isFinite()) {
    double closestFraction = stepRange.proportionFromValue(closest).toDouble();
    double closestRatio = isVertical || !isLeftToRightDirection
                              ? 1.0 - closestFraction
                              : closestFraction;
    LayoutUnit closestPosition(trackSize * closestRatio);
    const LayoutUnit snappingThreshold(5);
    if ((closestPosition - position).abs() <= snappingThreshold)
      value = closest;
  }

  String valueString = serializeForNumberType(value);
  if (valueString == input->value())
    return;

  // FIXME: This is no longer being set from renderer. Consider updating the
  // method name.
  input->setValueFromRenderer(valueString);
  if (layoutObject())
    layoutObject()->setNeedsLayoutAndFullPaintInvalidation(
        LayoutInvalidationReason::SliderValueChanged);
}

void SliderThumbElement::startDragging() {
  if (LocalFrame* frame = document().frame()) {
    frame->eventHandler().setCapturingMouseEventsNode(this);
    m_inDragMode = true;
  }
}

void SliderThumbElement::stopDragging() {
  if (!m_inDragMode)
    return;

  if (LocalFrame* frame = document().frame())
    frame->eventHandler().setCapturingMouseEventsNode(nullptr);
  m_inDragMode = false;
  if (layoutObject())
    layoutObject()->setNeedsLayoutAndFullPaintInvalidation(
        LayoutInvalidationReason::SliderValueChanged);
  if (hostInput())
    hostInput()->dispatchFormControlChangeEvent();
}

void SliderThumbElement::defaultEventHandler(Event* event) {
  if (!event->isMouseEvent()) {
    HTMLDivElement::defaultEventHandler(event);
    return;
  }

  // FIXME: Should handle this readonly/disabled check in more general way.
  // Missing this kind of check is likely to occur elsewhere if adding it in
  // each shadow element.
  HTMLInputElement* input = hostInput();
  if (!input || input->isDisabledOrReadOnly()) {
    stopDragging();
    HTMLDivElement::defaultEventHandler(event);
    return;
  }

  MouseEvent* mouseEvent = toMouseEvent(event);
  bool isLeftButton = mouseEvent->button() ==
                      static_cast<short>(WebPointerProperties::Button::Left);
  const AtomicString& eventType = event->type();

  // We intentionally do not call event->setDefaultHandled() here because
  // MediaControlTimelineElement::defaultEventHandler() wants to handle these
  // mouse events.
  if (eventType == EventTypeNames::mousedown && isLeftButton) {
    startDragging();
    return;
  }
  if (eventType == EventTypeNames::mouseup && isLeftButton) {
    stopDragging();
    return;
  }
  if (eventType == EventTypeNames::mousemove) {
    if (m_inDragMode)
      setPositionFromPoint(mouseEvent->absoluteLocation());
    return;
  }

  HTMLDivElement::defaultEventHandler(event);
}

bool SliderThumbElement::willRespondToMouseMoveEvents() {
  const HTMLInputElement* input = hostInput();
  if (input && !input->isDisabledOrReadOnly() && m_inDragMode)
    return true;

  return HTMLDivElement::willRespondToMouseMoveEvents();
}

bool SliderThumbElement::willRespondToMouseClickEvents() {
  const HTMLInputElement* input = hostInput();
  if (input && !input->isDisabledOrReadOnly())
    return true;

  return HTMLDivElement::willRespondToMouseClickEvents();
}

void SliderThumbElement::detachLayoutTree(const AttachContext& context) {
  if (m_inDragMode) {
    if (LocalFrame* frame = document().frame())
      frame->eventHandler().setCapturingMouseEventsNode(nullptr);
  }
  HTMLDivElement::detachLayoutTree(context);
}

HTMLInputElement* SliderThumbElement::hostInput() const {
  // Only HTMLInputElement creates SliderThumbElement instances as its shadow
  // nodes.  So, ownerShadowHost() must be an HTMLInputElement.
  return toHTMLInputElement(ownerShadowHost());
}

static const AtomicString& sliderThumbShadowPartId() {
  DEFINE_STATIC_LOCAL(const AtomicString, sliderThumb,
                      ("-webkit-slider-thumb"));
  return sliderThumb;
}

static const AtomicString& mediaSliderThumbShadowPartId() {
  DEFINE_STATIC_LOCAL(const AtomicString, mediaSliderThumb,
                      ("-webkit-media-slider-thumb"));
  return mediaSliderThumb;
}

const AtomicString& SliderThumbElement::shadowPseudoId() const {
  HTMLInputElement* input = hostInput();
  if (!input || !input->layoutObject())
    return sliderThumbShadowPartId();

  const ComputedStyle& sliderStyle = input->layoutObject()->styleRef();
  switch (sliderStyle.appearance()) {
    case MediaSliderPart:
    case MediaSliderThumbPart:
    case MediaVolumeSliderPart:
    case MediaVolumeSliderThumbPart:
    case MediaFullscreenVolumeSliderPart:
    case MediaFullscreenVolumeSliderThumbPart:
      return mediaSliderThumbShadowPartId();
    default:
      return sliderThumbShadowPartId();
  }
}

// --------------------------------

inline SliderContainerElement::SliderContainerElement(Document& document)
    : HTMLDivElement(document),
      m_hasTouchEventHandler(false),
      m_touchStarted(false),
      m_slidingDirection(NoMove) {
  updateTouchEventHandlerRegistry();
}

DEFINE_NODE_FACTORY(SliderContainerElement)

HTMLInputElement* SliderContainerElement::hostInput() const {
  return toHTMLInputElement(ownerShadowHost());
}

LayoutObject* SliderContainerElement::createLayoutObject(const ComputedStyle&) {
  return new LayoutSliderContainer(this);
}

void SliderContainerElement::defaultEventHandler(Event* event) {
  if (event->isTouchEvent()) {
    handleTouchEvent(toTouchEvent(event));
    return;
  }
}

void SliderContainerElement::handleTouchEvent(TouchEvent* event) {
  HTMLInputElement* input = hostInput();
  if (input->isDisabledOrReadOnly())
    return;

  if (event->type() == EventTypeNames::touchend) {
    input->dispatchFormControlChangeEvent();
    event->setDefaultHandled();
    m_slidingDirection = NoMove;
    m_touchStarted = false;
    return;
  }

  // The direction of this series of touch actions has been determined, which is
  // perpendicular to the slider, so no need to adjust the value.
  if (!canSlide()) {
    return;
  }

  TouchList* touches = event->targetTouches();
  SliderThumbElement* thumb = toSliderThumbElement(
      treeScope().getElementById(ShadowElementNames::sliderThumb()));
  if (touches->length() == 1) {
    if (event->type() == EventTypeNames::touchstart) {
      m_startPoint = touches->item(0)->absoluteLocation();
      m_slidingDirection = NoMove;
      m_touchStarted = true;
      thumb->setPositionFromPoint(touches->item(0)->absoluteLocation());
    } else if (m_touchStarted) {
      LayoutPoint currentPoint = touches->item(0)->absoluteLocation();
      if (m_slidingDirection ==
          NoMove) {  // Still needs to update the direction.
        m_slidingDirection = getDirection(currentPoint, m_startPoint);
      }

      // m_slidingDirection has been updated, so check whether it's okay to
      // slide again.
      if (canSlide()) {
        thumb->setPositionFromPoint(touches->item(0)->absoluteLocation());
        event->setDefaultHandled();
      }
    }
  }
}

SliderContainerElement::Direction SliderContainerElement::getDirection(
    LayoutPoint& point1,
    LayoutPoint& point2) {
  if (point1 == point2) {
    return NoMove;
  }
  if ((point1.x() - point2.x()).abs() >= (point1.y() - point2.y()).abs()) {
    return Horizontal;
  }
  return Vertical;
}

bool SliderContainerElement::canSlide() {
  if (!hostInput() || !hostInput()->layoutObject() ||
      !hostInput()->layoutObject()->style()) {
    return false;
  }
  const ComputedStyle* sliderStyle = hostInput()->layoutObject()->style();
  const TransformOperations& transforms = sliderStyle->transform();
  int transformSize = transforms.size();
  if (transformSize > 0) {
    for (int i = 0; i < transformSize; ++i) {
      if (transforms.at(i)->type() == TransformOperation::Rotate) {
        return true;
      }
    }
  }
  if ((m_slidingDirection == Vertical &&
       sliderStyle->appearance() == SliderHorizontalPart) ||
      (m_slidingDirection == Horizontal &&
       sliderStyle->appearance() == SliderVerticalPart)) {
    return false;
  }
  return true;
}

const AtomicString& SliderContainerElement::shadowPseudoId() const {
  DEFINE_STATIC_LOCAL(const AtomicString, mediaSliderContainer,
                      ("-webkit-media-slider-container"));
  DEFINE_STATIC_LOCAL(const AtomicString, sliderContainer,
                      ("-webkit-slider-container"));

  if (!ownerShadowHost() || !ownerShadowHost()->layoutObject())
    return sliderContainer;

  const ComputedStyle& sliderStyle =
      ownerShadowHost()->layoutObject()->styleRef();
  switch (sliderStyle.appearance()) {
    case MediaSliderPart:
    case MediaSliderThumbPart:
    case MediaVolumeSliderPart:
    case MediaVolumeSliderThumbPart:
    case MediaFullscreenVolumeSliderPart:
    case MediaFullscreenVolumeSliderThumbPart:
      return mediaSliderContainer;
    default:
      return sliderContainer;
  }
}

void SliderContainerElement::updateTouchEventHandlerRegistry() {
  if (m_hasTouchEventHandler) {
    return;
  }
  if (document().frameHost() &&
      document().lifecycle().state() < DocumentLifecycle::Stopping) {
    EventHandlerRegistry& registry =
        document().frameHost()->eventHandlerRegistry();
    registry.didAddEventHandler(
        *this, EventHandlerRegistry::TouchStartOrMoveEventPassive);
    m_hasTouchEventHandler = true;
  }
}

void SliderContainerElement::didMoveToNewDocument(Document& oldDocument) {
  updateTouchEventHandlerRegistry();
  HTMLElement::didMoveToNewDocument(oldDocument);
}

void SliderContainerElement::removeAllEventListeners() {
  Node::removeAllEventListeners();
  m_hasTouchEventHandler = false;
}

}  // namespace blink
