/*
 * 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 "third_party/blink/renderer/core/layout/layout_slider_container.h"

#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/html/forms/slider_thumb_element.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/core/html/shadow/shadow_element_names.h"
#include "third_party/blink/renderer/core/layout/layout_slider.h"
#include "third_party/blink/renderer/core/layout/layout_theme.h"

namespace blink {

LayoutSliderContainer::LayoutSliderContainer(SliderContainerElement* element)
    : LayoutFlexibleBox(element) {}

inline static Decimal SliderPosition(HTMLInputElement* element) {
  const StepRange step_range(element->CreateStepRange(kRejectAny));
  const Decimal old_value =
      ParseToDecimalForNumberType(element->value(), step_range.DefaultValue());
  return step_range.ProportionFromValue(step_range.ClampValue(old_value));
}

inline static bool HasVerticalAppearance(HTMLInputElement* input) {
  DCHECK(input->GetLayoutObject());
  if (!input->GetLayoutObject() || !input->GetLayoutObject()->Style())
    return false;
  const ComputedStyle& slider_style = input->GetLayoutObject()->StyleRef();
  return slider_style.Appearance() == kSliderVerticalPart;
}

void LayoutSliderContainer::ComputeLogicalHeight(
    LayoutUnit logical_height,
    LayoutUnit logical_top,
    LogicalExtentComputedValues& computed_values) const {
  HTMLInputElement* input = ToHTMLInputElement(GetNode()->OwnerShadowHost());
  bool is_vertical = HasVerticalAppearance(input);

  if (input->GetLayoutObject()->IsSlider() && !is_vertical && input->list()) {
    int offset_from_center =
        LayoutTheme::GetTheme().SliderTickOffsetFromTrackCenter();
    LayoutUnit track_height;
    if (offset_from_center < 0) {
      track_height = LayoutUnit(-2 * offset_from_center);
    } else {
      int tick_length = LayoutTheme::GetTheme().SliderTickSize().Height();
      track_height = LayoutUnit(2 * (offset_from_center + tick_length));
    }
    float zoom_factor = StyleRef().EffectiveZoom();
    if (zoom_factor != 1.0)
      track_height *= zoom_factor;

    // FIXME: The trackHeight should have been added before updateLogicalHeight
    // was called to avoid this hack.
    SetIntrinsicContentLogicalHeight(track_height);

    LayoutBox::ComputeLogicalHeight(track_height, logical_top, computed_values);
    return;
  }
  if (is_vertical)
    logical_height = LayoutUnit(LayoutSlider::kDefaultTrackLength);

  // FIXME: The trackHeight should have been added before updateLogicalHeight
  // was called to avoid this hack.
  SetIntrinsicContentLogicalHeight(logical_height);

  LayoutBox::ComputeLogicalHeight(logical_height, logical_top, computed_values);
}

void LayoutSliderContainer::UpdateLayout() {
  HTMLInputElement* input = ToHTMLInputElement(GetNode()->OwnerShadowHost());
  bool is_vertical = HasVerticalAppearance(input);

  Element* thumb_element = input->UserAgentShadowRoot()->getElementById(
      shadow_element_names::SliderThumb());
  Element* track_element = input->UserAgentShadowRoot()->getElementById(
      shadow_element_names::SliderTrack());
  LayoutBox* thumb = thumb_element ? thumb_element->GetLayoutBox() : nullptr;
  LayoutBox* track = track_element ? track_element->GetLayoutBox() : nullptr;

  SubtreeLayoutScope layout_scope(*this);
  // Force a layout to reset the position of the thumb so the code below doesn't
  // move the thumb to the wrong place.
  // FIXME: Make a custom layout class for the track and move the thumb
  // positioning code there.
  if (track)
    layout_scope.SetChildNeedsLayout(track);

  LayoutFlexibleBox::UpdateLayout();

  // These should always exist, unless someone mutates the shadow DOM (e.g., in
  // the inspector).
  if (!thumb || !track)
    return;

  double percentage_offset = SliderPosition(input).ToDouble();
  LayoutUnit available_extent =
      is_vertical ? track->ContentHeight() : track->ContentWidth();
  available_extent -=
      is_vertical ? thumb->Size().Height() : thumb->Size().Width();
  LayoutUnit offset(percentage_offset * available_extent);
  LayoutPoint thumb_location = thumb->Location();
  if (is_vertical) {
    thumb_location.SetY(thumb_location.Y() + track->ContentHeight() -
                        thumb->Size().Height() - offset);
  } else if (StyleRef().IsLeftToRightDirection()) {
    thumb_location.SetX(thumb_location.X() + offset);
  } else {
    thumb_location.SetX(thumb_location.X() - offset);
  }
  thumb->SetLocation(thumb_location);

  // We need one-off invalidation code here because painting of the timeline
  // element does not go through style.
  // Instead it has a custom implementation in C++ code.
  // Therefore the style system cannot understand when it needs to be paint
  // invalidated.
  SetShouldDoFullPaintInvalidation();
}

}  // namespace blink
