/*
 * Copyright (C) 2013 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/html/track/vtt/vtt_region.h"

#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/core/dom/dom_token_list.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/geometry/dom_rect.h"
#include "third_party/blink/renderer/core/html/html_div_element.h"
#include "third_party/blink/renderer/core/html/track/vtt/vtt_parser.h"
#include "third_party/blink/renderer/core/html/track/vtt/vtt_scanner.h"
#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"

#define VTT_LOG_LEVEL 3

namespace blink {

namespace {
// The following values default values are defined within the WebVTT Regions
// Spec.
// https://dvcs.w3.org/hg/text-tracks/raw-file/default/608toVTT/region.html

// The region occupies by default 100% of the width of the video viewport.
constexpr double kDefaultRegionWidth = 100;

// The region has, by default, 3 lines of text.
constexpr int kDefaultHeightInLines = 3;

// The region and viewport are anchored in the bottom left corner.
constexpr double kDefaultAnchorPointX = 0;
constexpr double kDefaultAnchorPointY = 100;

// The region doesn't have scrolling text, by default.
constexpr bool kDefaultScroll = false;

// Default region line-height (vh units)
constexpr float kLineHeight = 5.33;

// Default scrolling animation time period (s).
constexpr TimeDelta kScrollTime = TimeDelta::FromMilliseconds(433);

bool IsNonPercentage(double value,
                     const char* method,
                     ExceptionState& exception_state) {
  if (value < 0 || value > 100) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kIndexSizeError,
        ExceptionMessages::IndexOutsideRange(
            "value", value, 0.0, ExceptionMessages::kInclusiveBound, 100.0,
            ExceptionMessages::kInclusiveBound));
    return true;
  }
  return false;
}

}  // namespace

VTTRegion::VTTRegion()
    : id_(g_empty_string),
      width_(kDefaultRegionWidth),
      lines_(kDefaultHeightInLines),
      region_anchor_(DoublePoint(kDefaultAnchorPointX, kDefaultAnchorPointY)),
      viewport_anchor_(DoublePoint(kDefaultAnchorPointX, kDefaultAnchorPointY)),
      scroll_(kDefaultScroll),
      current_top_(0),
      scroll_timer_(Thread::Current()->GetTaskRunner(),
                    this,
                    &VTTRegion::ScrollTimerFired) {}

VTTRegion::~VTTRegion() = default;

void VTTRegion::setId(const String& id) {
  id_ = id;
}

void VTTRegion::setWidth(double value, ExceptionState& exception_state) {
  if (IsNonPercentage(value, "width", exception_state))
    return;

  width_ = value;
}

void VTTRegion::setLines(unsigned value) {
  lines_ = value;
}

void VTTRegion::setRegionAnchorX(double value,
                                 ExceptionState& exception_state) {
  if (IsNonPercentage(value, "regionAnchorX", exception_state))
    return;

  region_anchor_.SetX(value);
}

void VTTRegion::setRegionAnchorY(double value,
                                 ExceptionState& exception_state) {
  if (IsNonPercentage(value, "regionAnchorY", exception_state))
    return;

  region_anchor_.SetY(value);
}

void VTTRegion::setViewportAnchorX(double value,
                                   ExceptionState& exception_state) {
  if (IsNonPercentage(value, "viewportAnchorX", exception_state))
    return;

  viewport_anchor_.SetX(value);
}

void VTTRegion::setViewportAnchorY(double value,
                                   ExceptionState& exception_state) {
  if (IsNonPercentage(value, "viewportAnchorY", exception_state))
    return;

  viewport_anchor_.SetY(value);
}

const AtomicString VTTRegion::scroll() const {
  DEFINE_STATIC_LOCAL(const AtomicString, up_scroll_value_keyword, ("up"));
  return scroll_ ? up_scroll_value_keyword : g_empty_atom;
}

void VTTRegion::setScroll(const AtomicString& value) {
  DCHECK(value == "up" || value == g_empty_atom);
  scroll_ = value != g_empty_atom;
}

void VTTRegion::SetRegionSettings(const String& input_string) {
  VTTScanner input(input_string);

  while (!input.IsAtEnd()) {
    input.SkipWhile<VTTParser::IsASpace>();

    if (input.IsAtEnd())
      break;

    // Scan the name part.
    RegionSetting name = ScanSettingName(input);

    // Verify that we're looking at a ':'.
    if (name == kNone || !input.Scan(':')) {
      input.SkipUntil<VTTParser::IsASpace>();
      continue;
    }

    // Scan the value part.
    ParseSettingValue(name, input);
  }
}

VTTRegion::RegionSetting VTTRegion::ScanSettingName(VTTScanner& input) {
  if (input.Scan("id"))
    return kId;
  if (input.Scan("lines"))
    return kLines;
  if (input.Scan("width"))
    return kWidth;
  if (input.Scan("viewportanchor"))
    return kViewportAnchor;
  if (input.Scan("regionanchor"))
    return kRegionAnchor;
  if (input.Scan("scroll"))
    return kScroll;

  return kNone;
}

static inline bool ParsedEntireRun(const VTTScanner& input,
                                   const VTTScanner::Run& run) {
  return input.IsAt(run.end());
}

void VTTRegion::ParseSettingValue(RegionSetting setting, VTTScanner& input) {
  DEFINE_STATIC_LOCAL(const AtomicString, scroll_up_value_keyword, ("up"));

  VTTScanner::Run value_run = input.CollectUntil<VTTParser::IsASpace>();

  switch (setting) {
    case kId: {
      String string_value = input.ExtractString(value_run);
      if (string_value.Find("-->") == kNotFound)
        id_ = string_value;
      break;
    }
    case kWidth: {
      double width;
      if (VTTParser::ParsePercentageValue(input, width) &&
          ParsedEntireRun(input, value_run))
        width_ = width;
      else
        DVLOG(VTT_LOG_LEVEL) << "parseSettingValue, invalid Width";
      break;
    }
    case kLines: {
      unsigned number;
      if (input.ScanDigits(number) && ParsedEntireRun(input, value_run))
        lines_ = number;
      else
        DVLOG(VTT_LOG_LEVEL) << "parseSettingValue, invalid Lines";
      break;
    }
    case kRegionAnchor: {
      DoublePoint anchor;
      if (VTTParser::ParsePercentageValuePair(input, ',', anchor) &&
          ParsedEntireRun(input, value_run))
        region_anchor_ = anchor;
      else
        DVLOG(VTT_LOG_LEVEL) << "parseSettingValue, invalid RegionAnchor";
      break;
    }
    case kViewportAnchor: {
      DoublePoint anchor;
      if (VTTParser::ParsePercentageValuePair(input, ',', anchor) &&
          ParsedEntireRun(input, value_run))
        viewport_anchor_ = anchor;
      else
        DVLOG(VTT_LOG_LEVEL) << "parseSettingValue, invalid ViewportAnchor";
      break;
    }
    case kScroll:
      if (input.ScanRun(value_run, scroll_up_value_keyword))
        scroll_ = true;
      else
        DVLOG(VTT_LOG_LEVEL) << "parseSettingValue, invalid Scroll";
      break;
    case kNone:
      break;
  }

  input.SkipRun(value_run);
}

const AtomicString& VTTRegion::TextTrackCueContainerScrollingClass() {
  DEFINE_STATIC_LOCAL(const AtomicString,
                      track_region_cue_container_scrolling_class,
                      ("scrolling"));

  return track_region_cue_container_scrolling_class;
}

HTMLDivElement* VTTRegion::GetDisplayTree(Document& document) {
  if (!region_display_tree_) {
    region_display_tree_ = HTMLDivElement::Create(document);
    PrepareRegionDisplayTree();
  }

  return region_display_tree_;
}

void VTTRegion::WillRemoveVTTCueBox(VTTCueBox* box) {
  DVLOG(VTT_LOG_LEVEL) << "willRemoveVTTCueBox";
  DCHECK(cue_container_->contains(box));

  double box_height = box->getBoundingClientRect()->height();

  cue_container_->classList().Remove(TextTrackCueContainerScrollingClass());

  current_top_ += box_height;
  cue_container_->SetInlineStyleProperty(CSSPropertyTop, current_top_,
                                         CSSPrimitiveValue::UnitType::kPixels);
}

void VTTRegion::AppendVTTCueBox(VTTCueBox* display_box) {
  DCHECK(cue_container_);

  if (cue_container_->contains(display_box))
    return;

  cue_container_->AppendChild(display_box);
  DisplayLastVTTCueBox();
}

void VTTRegion::DisplayLastVTTCueBox() {
  DVLOG(VTT_LOG_LEVEL) << "displayLastVTTCueBox";
  DCHECK(cue_container_);

  // FIXME: This should not be causing recalc styles in a loop to set the "top"
  // css property to move elements. We should just scroll the text track cues on
  // the compositor with an animation.

  if (scroll_timer_.IsActive())
    return;

  // If it's a scrolling region, add the scrolling class.
  if (IsScrollingRegion())
    cue_container_->classList().Add(TextTrackCueContainerScrollingClass());

  double region_bottom =
      region_display_tree_->getBoundingClientRect()->bottom();

  // Find first cue that is not entirely displayed and scroll it upwards.
  for (Element& child : ElementTraversal::ChildrenOf(*cue_container_)) {
    DOMRect* client_rect = child.getBoundingClientRect();
    double child_bottom = client_rect->bottom();

    if (region_bottom >= child_bottom)
      continue;

    current_top_ -=
        std::min(client_rect->height(), child_bottom - region_bottom);
    cue_container_->SetInlineStyleProperty(
        CSSPropertyTop, current_top_, CSSPrimitiveValue::UnitType::kPixels);

    StartTimer();
    break;
  }
}

void VTTRegion::PrepareRegionDisplayTree() {
  DCHECK(region_display_tree_);

  // 7.2 Prepare region CSS boxes

  // FIXME: Change the code below to use viewport units when
  // http://crbug/244618 is fixed.

  // Let regionWidth be the text track region width.
  // Let width be 'regionWidth vw' ('vw' is a CSS unit)
  region_display_tree_->SetInlineStyleProperty(
      CSSPropertyWidth, width_, CSSPrimitiveValue::UnitType::kPercentage);

  // Let lineHeight be '0.0533vh' ('vh' is a CSS unit) and regionHeight be
  // the text track region height. Let height be 'lineHeight' multiplied
  // by regionHeight.
  double height = kLineHeight * lines_;
  region_display_tree_->SetInlineStyleProperty(
      CSSPropertyHeight, height, CSSPrimitiveValue::UnitType::kViewportHeight);

  // Let viewportAnchorX be the x dimension of the text track region viewport
  // anchor and regionAnchorX be the x dimension of the text track region
  // anchor. Let leftOffset be regionAnchorX multiplied by width divided by
  // 100.0. Let left be leftOffset subtracted from 'viewportAnchorX vw'.
  double left_offset = region_anchor_.X() * width_ / 100;
  region_display_tree_->SetInlineStyleProperty(
      CSSPropertyLeft, viewport_anchor_.X() - left_offset,
      CSSPrimitiveValue::UnitType::kPercentage);

  // Let viewportAnchorY be the y dimension of the text track region viewport
  // anchor and regionAnchorY be the y dimension of the text track region
  // anchor. Let topOffset be regionAnchorY multiplied by height divided by
  // 100.0. Let top be topOffset subtracted from 'viewportAnchorY vh'.
  double top_offset = region_anchor_.Y() * height / 100;
  region_display_tree_->SetInlineStyleProperty(
      CSSPropertyTop, viewport_anchor_.Y() - top_offset,
      CSSPrimitiveValue::UnitType::kPercentage);

  // The cue container is used to wrap the cues and it is the object which is
  // gradually scrolled out as multiple cues are appended to the region.
  cue_container_ = HTMLDivElement::Create(region_display_tree_->GetDocument());
  cue_container_->SetInlineStyleProperty(CSSPropertyTop, 0.0,
                                         CSSPrimitiveValue::UnitType::kPixels);

  cue_container_->SetShadowPseudoId(
      AtomicString("-webkit-media-text-track-region-container"));
  region_display_tree_->AppendChild(cue_container_);

  // 7.5 Every WebVTT region object is initialised with the following CSS
  region_display_tree_->SetShadowPseudoId(
      AtomicString("-webkit-media-text-track-region"));
}

void VTTRegion::StartTimer() {
  DVLOG(VTT_LOG_LEVEL) << "startTimer";

  if (scroll_timer_.IsActive())
    return;

  TimeDelta duration = IsScrollingRegion() ? kScrollTime : TimeDelta();
  scroll_timer_.StartOneShot(duration, FROM_HERE);
}

void VTTRegion::StopTimer() {
  DVLOG(VTT_LOG_LEVEL) << "stopTimer";
  scroll_timer_.Stop();
}

void VTTRegion::ScrollTimerFired(TimerBase*) {
  DVLOG(VTT_LOG_LEVEL) << "scrollTimerFired";

  StopTimer();
  DisplayLastVTTCueBox();
}

void VTTRegion::Trace(blink::Visitor* visitor) {
  visitor->Trace(cue_container_);
  visitor->Trace(region_display_tree_);
  ScriptWrappable::Trace(visitor);
}

}  // namespace blink
