/*
 * Copyright (C) 2013 Google Inc.  All rights reserved.
 * Copyright (C) 2014 Apple 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 "config.h"
#include "VTTRegion.h"

#if ENABLE(VIDEO)

#include "DOMRect.h"
#include "DOMTokenList.h"
#include "ElementChildIterator.h"
#include "HTMLDivElement.h"
#include "HTMLParserIdioms.h"
#include "Logging.h"
#include "RenderElement.h"
#include "ShadowPseudoIds.h"
#include "VTTCue.h"
#include "VTTScanner.h"
#include "WebVTTParser.h"
#include <wtf/MathExtras.h>

namespace WebCore {

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

// Default region line-height (vh units)
static const float lineHeight = 5.33;

// Default scrolling animation time period (s).
static const Seconds scrollTime { 433_ms };

VTTRegion::VTTRegion(ScriptExecutionContext& context)
    : ContextDestructionObserver(&context)
    , m_id(emptyString())
    , m_scrollTimer(*this, &VTTRegion::scrollTimerFired)
{
}

VTTRegion::~VTTRegion() = default;

void VTTRegion::setTrack(TextTrack* track)
{
    m_track = track;
}

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

ExceptionOr<void> VTTRegion::setWidth(double value)
{
    if (!(value >= 0 && value <= 100))
        return Exception { IndexSizeError };
    m_width = value;
    return { };
}

ExceptionOr<void> VTTRegion::setLines(int value)
{
    if (value < 0)
        return Exception { IndexSizeError };
    m_lines = value;
    return { };
}

ExceptionOr<void> VTTRegion::setRegionAnchorX(double value)
{
    if (!(value >= 0 && value <= 100))
        return Exception { IndexSizeError };
    m_regionAnchor.setX(value);
    return { };
}

ExceptionOr<void> VTTRegion::setRegionAnchorY(double value)
{
    if (!(value >= 0 && value <= 100))
        return Exception { IndexSizeError };
    m_regionAnchor.setY(value);
    return { };
}

ExceptionOr<void> VTTRegion::setViewportAnchorX(double value)
{
    if (!(value >= 0 && value <= 100))
        return Exception { IndexSizeError };
    m_viewportAnchor.setX(value);
    return { };
}

ExceptionOr<void> VTTRegion::setViewportAnchorY(double value)
{
    if (!(value >= 0 && value <= 100))
        return Exception { IndexSizeError };
    m_viewportAnchor.setY(value);
    return { };
}

static const AtomString& upKeyword()
{
    static MainThreadNeverDestroyed<const AtomString> upKeyword("up"_s);
    return upKeyword;
}

const AtomString& VTTRegion::scroll() const
{
    return m_scroll ? upKeyword() : emptyAtom();
}

ExceptionOr<void> VTTRegion::setScroll(const AtomString& value)
{
    if (value.isEmpty()) {
        m_scroll = false;
        return { };
    }
    if (value == upKeyword()) {
        m_scroll = true;
        return { };
    }
    return Exception { SyntaxError };
}

void VTTRegion::updateParametersFromRegion(const VTTRegion& other)
{
    m_lines = other.m_lines;
    m_width = other.m_width;
    m_regionAnchor = other.m_regionAnchor;
    m_viewportAnchor = other.m_viewportAnchor;
    m_scroll = other.m_scroll;
}

void VTTRegion::setRegionSettings(const String& inputString)
{
    m_settings = inputString;
    VTTScanner input(inputString);

    while (!input.isAtEnd()) {
        input.skipWhile<WebVTTParser::isValidSettingDelimiter>();
        if (input.isAtEnd())
            break;

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

        // Verify that we're looking at a ':'.
        if (name == None || !input.scan(':')) {
            input.skipUntil<isHTMLSpace<UChar>>();
            continue;
        }

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

VTTRegion::RegionSetting VTTRegion::scanSettingName(VTTScanner& input)
{
    if (input.scan("id"))
        return Id;
    if (input.scan("lines"))
        return Lines;
    if (input.scan("width"))
        return Width;
    if (input.scan("viewportanchor"))
        return ViewportAnchor;
    if (input.scan("regionanchor"))
        return RegionAnchor;
    if (input.scan("scroll"))
        return Scroll;

    return None;
}

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

void VTTRegion::parseSettingValue(RegionSetting setting, VTTScanner& input)
{
    VTTScanner::Run valueRun = input.collectUntil<isHTMLSpace<UChar>>();

    switch (setting) {
    case Id: {
        String stringValue = input.extractString(valueRun);
        if (stringValue.find("-->"_s) == notFound)
            m_id = stringValue;
        break;
    }
    case Width: {
        float floatWidth;
        if (WebVTTParser::parseFloatPercentageValue(input, floatWidth) && parsedEntireRun(input, valueRun))
            m_width = floatWidth;
        else
            LOG(Media, "VTTRegion::parseSettingValue, invalid Width");
        break;
    }
    case Lines: {
        int number;
        if (input.scanDigits(number) && parsedEntireRun(input, valueRun))
            m_lines = number;
        else
            LOG(Media, "VTTRegion::parseSettingValue, invalid Height");
        break;
    }
    case RegionAnchor: {
        FloatPoint anchor;
        if (WebVTTParser::parseFloatPercentageValuePair(input, ',', anchor) && parsedEntireRun(input, valueRun))
            m_regionAnchor = anchor;
        else
            LOG(Media, "VTTRegion::parseSettingValue, invalid RegionAnchor");
        break;
    }
    case ViewportAnchor: {
        FloatPoint anchor;
        if (WebVTTParser::parseFloatPercentageValuePair(input, ',', anchor) && parsedEntireRun(input, valueRun))
            m_viewportAnchor = anchor;
        else
            LOG(Media, "VTTRegion::parseSettingValue, invalid ViewportAnchor");
        break;
    }
    case Scroll:
        if (input.scanRun(valueRun, upKeyword()))
            m_scroll = true;
        else
            LOG(Media, "VTTRegion::parseSettingValue, invalid Scroll");
        break;
    case None:
        break;
    }

    input.skipRun(valueRun);
}

const AtomString& VTTRegion::textTrackCueContainerScrollingClass()
{
    static MainThreadNeverDestroyed<const AtomString> trackRegionCueContainerScrollingClass("scrolling"_s);

    return trackRegionCueContainerScrollingClass;
}

void VTTRegion::appendTextTrackCueBox(Ref<TextTrackCueBox>&& displayBox)
{
    ASSERT(m_cueContainer);

    if (m_cueContainer->contains(displayBox.ptr()))
        return;

    m_cueContainer->appendChild(displayBox);
    displayLastTextTrackCueBox();
}

void VTTRegion::displayLastTextTrackCueBox()
{
    ASSERT(m_cueContainer);

    // The container needs to be rendered, if it is not empty and the region is not currently scrolling.
    if (!m_cueContainer->renderer() || !m_cueContainer->hasChildNodes() || m_scrollTimer.isActive())
        return;

    // If it's a scrolling region, add the scrolling class.
    if (isScrollingRegion())
        m_cueContainer->classList().add(textTrackCueContainerScrollingClass());

    float regionBottom = m_regionDisplayTree->boundingClientRect().maxY();

    // Find first cue that is not entirely displayed and scroll it upwards.
    for (auto& child : childrenOfType<Element>(*m_cueContainer)) {
        auto rect = child.boundingClientRect();
        float childTop = rect.y();
        float childBottom = rect.maxY();

        if (regionBottom >= childBottom)
            continue;

        float height = childBottom - childTop;

        m_currentTop -= std::min(height, childBottom - regionBottom);
        m_cueContainer->setInlineStyleProperty(CSSPropertyTop, m_currentTop, CSSUnitType::CSS_PX);

        startTimer();
        break;
    }
}

void VTTRegion::willRemoveTextTrackCueBox(VTTCueBox* box)
{
    LOG(Media, "VTTRegion::willRemoveTextTrackCueBox");
    ASSERT(m_cueContainer->contains(box));

    double boxHeight = box->boundingClientRect().height();

    m_cueContainer->classList().remove(textTrackCueContainerScrollingClass());

    m_currentTop += boxHeight;
    m_cueContainer->setInlineStyleProperty(CSSPropertyTop, m_currentTop, CSSUnitType::CSS_PX);
}

HTMLDivElement& VTTRegion::getDisplayTree()
{
    if (!m_regionDisplayTree) {
        m_regionDisplayTree = HTMLDivElement::create(downcast<Document>(*scriptExecutionContext()));
        m_regionDisplayTree->setPseudo(ShadowPseudoIds::webkitMediaTextTrackRegion());
        m_recalculateStyles = true;
    }

    if (m_recalculateStyles)
        prepareRegionDisplayTree();

    return *m_regionDisplayTree;
}

void VTTRegion::prepareRegionDisplayTree()
{
    ASSERT(m_regionDisplayTree);

    // 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)
    m_regionDisplayTree->setInlineStyleProperty(CSSPropertyWidth, m_width, CSSUnitType::CSS_PERCENTAGE);

    // 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 = lineHeight * m_lines;
    m_regionDisplayTree->setInlineStyleProperty(CSSPropertyHeight, height, CSSUnitType::CSS_VH);

    // 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 leftOffset = m_regionAnchor.x() * m_width / 100;
    m_regionDisplayTree->setInlineStyleProperty(CSSPropertyLeft, m_viewportAnchor.x() - leftOffset, CSSUnitType::CSS_PERCENTAGE);

    // 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 topOffset = m_regionAnchor.y() * height / 100;
    m_regionDisplayTree->setInlineStyleProperty(CSSPropertyTop, m_viewportAnchor.y() - topOffset, CSSUnitType::CSS_PERCENTAGE);

    // 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.
    if (!m_cueContainer) {
        m_cueContainer = HTMLDivElement::create(downcast<Document>(*scriptExecutionContext()));
        m_cueContainer->setPseudo(ShadowPseudoIds::webkitMediaTextTrackRegionContainer());
        m_regionDisplayTree->appendChild(*m_cueContainer);
    }
    m_cueContainer->setInlineStyleProperty(CSSPropertyTop, 0.0f, CSSUnitType::CSS_PX);

    // 7.5 Every WebVTT region object is initialised with the following CSS

    m_recalculateStyles = false;
}

void VTTRegion::startTimer()
{
    LOG(Media, "VTTRegion::startTimer");

    if (m_scrollTimer.isActive())
        return;

    Seconds duration = isScrollingRegion() ? scrollTime : 0_s;
    m_scrollTimer.startOneShot(duration);
}

void VTTRegion::stopTimer()
{
    LOG(Media, "VTTRegion::stopTimer");

    if (m_scrollTimer.isActive())
        m_scrollTimer.stop();
}

void VTTRegion::scrollTimerFired()
{
    LOG(Media, "VTTRegion::scrollTimerFired");

    stopTimer();
    displayLastTextTrackCueBox();
}

} // namespace WebCore

#endif
