/*
 * Copyright (C) 2011, 2013 Google Inc.  All rights reserved.
 * Copyright (C) 2013 Cable Television Labs, Inc.
 * Copyright (C) 2011-2020 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"

#if ENABLE(VIDEO_TRACK)

#include "WebVTTParser.h"

#include "HTMLParserIdioms.h"
#include "ISOVTTCue.h"
#include "ProcessingInstruction.h"
#include "StyleRule.h"
#include "StyleRuleImport.h"
#include "StyleSheetContents.h"
#include "Text.h"
#include "VTTScanner.h"
#include "WebVTTElement.h"
#include "WebVTTTokenizer.h"

namespace WebCore {

const double secondsPerHour = 3600;
const double secondsPerMinute = 60;
const double secondsPerMillisecond = 0.001;
const char* fileIdentifier = "WEBVTT";
const unsigned fileIdentifierLength = 6;
const unsigned regionIdentifierLength = 6;
const unsigned styleIdentifierLength = 5;

bool WebVTTParser::parseFloatPercentageValue(VTTScanner& valueScanner, float& percentage)
{
    float number;
    if (!valueScanner.scanFloat(number))
        return false;
    // '%' must be present and at the end of the setting value.
    if (!valueScanner.scan('%'))
        return false;

    if (number < 0 || number > 100)
        return false;

    percentage = number;
    return true;
}

bool WebVTTParser::parseFloatPercentageValuePair(VTTScanner& valueScanner, char delimiter, FloatPoint& valuePair)
{
    float firstCoord;
    if (!parseFloatPercentageValue(valueScanner, firstCoord))
        return false;

    if (!valueScanner.scan(delimiter))
        return false;

    float secondCoord;
    if (!parseFloatPercentageValue(valueScanner, secondCoord))
        return false;

    valuePair = FloatPoint(firstCoord, secondCoord);
    return true;
}

WebVTTParser::WebVTTParser(WebVTTParserClient& client, Document& document)
    : m_document(document)
    , m_decoder(TextResourceDecoder::create("text/plain", UTF8Encoding()))
    , m_client(client)
{
}

Vector<Ref<WebVTTCueData>> WebVTTParser::takeCues()
{
    return WTFMove(m_cuelist);
}

Vector<Ref<VTTRegion>> WebVTTParser::takeRegions()
{
    return WTFMove(m_regionList);
}

Vector<String> WebVTTParser::takeStyleSheets()
{
    return WTFMove(m_styleSheets);
}

void WebVTTParser::parseFileHeader(String&& data)
{
    m_state = Initial;
    m_lineReader.reset();
    m_lineReader.append(WTFMove(data));
    parse();
}

void WebVTTParser::parseBytes(const char* data, unsigned length)
{
    m_lineReader.append(m_decoder->decode(data, length));
    parse();
}

void WebVTTParser::parseCueData(const ISOWebVTTCue& data)
{
    auto cue = WebVTTCueData::create();

    MediaTime startTime = data.presentationTime();
    cue->setStartTime(startTime);
    cue->setEndTime(startTime + data.duration());

    cue->setContent(data.cueText());
    cue->setId(data.id());
    cue->setSettings(data.settings());

    MediaTime originalStartTime;
    if (WebVTTParser::collectTimeStamp(data.originalStartTime(), originalStartTime))
        cue->setOriginalStartTime(originalStartTime);

    m_cuelist.append(WTFMove(cue));
    m_client.newCuesParsed();
}

void WebVTTParser::flush()
{
    m_lineReader.append(m_decoder->flush());
    m_lineReader.appendEndOfStream();
    parse();
    flushPendingCue();
}

void WebVTTParser::parse()
{    
    // WebVTT parser algorithm. (5.1 WebVTT file parsing.)
    // Steps 1 - 3 - Initial setup.
    while (auto line = m_lineReader.nextLine()) {
        switch (m_state) {
        case Initial:
            // Steps 4 - 9 - Check for a valid WebVTT signature.
            if (!hasRequiredFileIdentifier(*line)) {
                m_client.fileFailedToParse();
                return;
            }

            m_state = Header;
            break;

        case Header:
            // Steps 11 - 14 - Collect WebVTT block
            m_state = collectWebVTTBlock(*line);
            break;

        case Region:
            m_state = collectRegionSettings(*line);
            break;

        case Style:
            m_state = collectStyleSheet(*line);
            break;

        case Id:
            // Steps 17 - 20 - Allow any number of line terminators, then initialize new cue values.
            if (line->isEmpty())
                break;

            // Step 21 - Cue creation (start a new cue).
            resetCueValues();

            // Steps 22 - 25 - Check if this line contains an optional identifier or timing data.
            m_state = collectCueId(*line);
            break;

        case TimingsAndSettings:
            // Steps 26 - 27 - Discard current cue if the line is empty.
            if (line->isEmpty()) {
                m_state = Id;
                break;
            }

            // Steps 28 - 29 - Collect cue timings and settings.
            m_state = collectTimingsAndSettings(*line);
            break;

        case CueText:
            // Steps 31 - 41 - Collect the cue text, create a cue, and add it to the output.
            m_state = collectCueText(*line);
            break;

        case BadCue:
            // Steps 42 - 48 - Discard lines until an empty line or a potential timing line is seen.
            m_state = ignoreBadCue(*line);
            break;

        case Finished:
            ASSERT_NOT_REACHED();
            break;
        }
    }
}

void WebVTTParser::fileFinished()
{
    ASSERT(m_state != Finished);
    parseBytes("\n\n", 2);
    m_state = Finished;
}

void WebVTTParser::flushPendingCue()
{
    ASSERT(m_lineReader.isAtEndOfStream());
    // If we're in the CueText state when we run out of data, we emit the pending cue.
    if (m_state == CueText)
        createNewCue();
}

bool WebVTTParser::hasRequiredFileIdentifier(const String& line)
{
    // A WebVTT file identifier consists of an optional BOM character,
    // the string "WEBVTT" followed by an optional space or tab character,
    // and any number of characters that are not line terminators ...
    if (!line.startsWith(fileIdentifier))
        return false;
    if (line.length() > fileIdentifierLength && !isHTMLSpace(line[fileIdentifierLength]))
        return false;
    return true;
}

WebVTTParser::ParseState WebVTTParser::collectRegionSettings(const String& line)
{
    // End of region block
    if (checkAndStoreRegion(line))
        return checkAndRecoverCue(line);
    
    m_currentRegion->setRegionSettings(line);
    return Region;
}

WebVTTParser::ParseState WebVTTParser::collectWebVTTBlock(const String& line)
{
    // collect a WebVTT block parsing. (WebVTT parser algorithm step 14)
    
    if (checkAndCreateRegion(line))
        return Region;
    
    if (checkStyleSheet(line))
        return Style;

    // Handle cue block.
    ParseState state = checkAndRecoverCue(line);
    if (state != Header) {
        if (!m_regionList.isEmpty())
            m_client.newRegionsParsed();
        if (!m_styleSheets.isEmpty())
            m_client.newStyleSheetsParsed();
        if (!m_previousLine.isEmpty() && !m_previousLine.contains("-->"))
            m_currentId = m_previousLine;
        
        return state;
    }
    
    // store previous line for cue id.
    // length is more than 1 line clear m_previousLine and ignore line.
    if (m_previousLine.isEmpty())
        m_previousLine = line;
    else
        m_previousLine = emptyString();

    return state;
}

WebVTTParser::ParseState WebVTTParser::checkAndRecoverCue(const String& line)
{
    // parse cue timings and settings
    if (line.contains("-->")) {
        ParseState state = recoverCue(line);
        if (state != BadCue)
            return state;
    }
    return Header;
}

WebVTTParser::ParseState WebVTTParser::collectStyleSheet(const String& line)
{
    // End of style block
    if (checkAndStoreStyleSheet(line))
        return checkAndRecoverCue(line);

    m_currentSourceStyleSheet.append(line);
    return Style;
}

bool WebVTTParser::checkAndCreateRegion(const String& line)
{
    if (m_previousLine.contains("-->"))
        return false;
    // line starts with the substring "REGION" and remaining characters
    // zero or more U+0020 SPACE characters or U+0009 CHARACTER TABULATION
    // (tab) characters expected other than these charecters it is invalid.
    if (line.startsWith("REGION") && line.substring(regionIdentifierLength).isAllSpecialCharacters<isASpace>()) {
        m_currentRegion = VTTRegion::create(m_document);
        return true;
    }
    return false;
}

bool WebVTTParser::checkAndStoreRegion(const String& line)
{
    if (!line.isEmpty() && !line.contains("-->"))
        return false;

    if (!m_currentRegion->id().isEmpty()) {
        m_regionList.removeFirstMatching([this] (auto& region) {
            return region->id() == m_currentRegion->id();
        });
        m_regionList.append(m_currentRegion.releaseNonNull());
    }
    m_currentRegion = nullptr;
    return true;
}

bool WebVTTParser::checkStyleSheet(const String& line)
{
    if (m_previousLine.contains("-->"))
        return false;
    // line starts with the substring "STYLE" and remaining characters
    // zero or more U+0020 SPACE characters or U+0009 CHARACTER TABULATION
    // (tab) characters expected other than these charecters it is invalid.
    if (line.startsWith("STYLE") && line.substring(styleIdentifierLength).isAllSpecialCharacters<isASpace>())
        return true;

    return false;
}

bool WebVTTParser::checkAndStoreStyleSheet(const String& line)
{
    if (!line.isEmpty() && !line.contains("-->"))
        return false;
    
    auto styleSheetText = WTFMove(m_currentSourceStyleSheet);

    // WebVTTMode disallows non-data URLs.
    auto contents = StyleSheetContents::create(CSSParserContext(WebVTTMode));
    if (!contents->parseString(styleSheetText))
        return true;

    auto& namespaceRules = contents->namespaceRules();
    if (namespaceRules.size())
        return true;

    auto& importRules = contents->importRules();
    if (importRules.size())
        return true;

    auto& childRules = contents->childRules();
    if (!childRules.size())
        return true;

    StringBuilder sanitizedStyleSheetBuilder;
    
    for (const auto& rule : childRules) {
        if (!rule->isStyleRule())
            return true;
        const auto& styleRule = downcast<StyleRule>(*rule);

        const auto& selectorList = styleRule.selectorList();
        if (selectorList.listSize() != 1)
            return true;
        auto selector = selectorList.selectorAt(0);
        auto selectorText = selector->selectorText();
        
        bool isCue = selectorText == "::cue" || selectorText.startsWith("::cue(");
        if (!isCue)
            return true;

        if (styleRule.properties().isEmpty())
            continue;

        sanitizedStyleSheetBuilder.append(selectorText, " { ", styleRule.properties().asText(), "  }\n");
    }

    // It would be more stylish to parse the stylesheet only once instead of serializing a sanitized version.
    if (!sanitizedStyleSheetBuilder.isEmpty())
        m_styleSheets.append(sanitizedStyleSheetBuilder.toString());

    return true;
}

WebVTTParser::ParseState WebVTTParser::collectCueId(const String& line)
{
    if (line.contains("-->"))
        return collectTimingsAndSettings(line);
    m_currentId = line;
    return TimingsAndSettings;
}

WebVTTParser::ParseState WebVTTParser::collectTimingsAndSettings(const String& line)
{
    if (line.isEmpty())
        return BadCue;

    VTTScanner input(line);

    // Collect WebVTT cue timings and settings. (5.3 WebVTT cue timings and settings parsing.)
    // Steps 1 - 3 - Let input be the string being parsed and position be a pointer into input
    input.skipWhile<isHTMLSpace<UChar>>();

    // Steps 4 - 5 - Collect a WebVTT timestamp. If that fails, then abort and return failure. Otherwise, let cue's text track cue start time be the collected time.
    if (!collectTimeStamp(input, m_currentStartTime))
        return BadCue;
    
    input.skipWhile<isHTMLSpace<UChar>>();

    // Steps 6 - 9 - If the next three characters are not "-->", abort and return failure.
    if (!input.scan("-->"))
        return BadCue;
    
    input.skipWhile<isHTMLSpace<UChar>>();

    // Steps 10 - 11 - Collect a WebVTT timestamp. If that fails, then abort and return failure. Otherwise, let cue's text track cue end time be the collected time.
    if (!collectTimeStamp(input, m_currentEndTime))
        return BadCue;

    input.skipWhile<isHTMLSpace<UChar>>();

    // Step 12 - Parse the WebVTT settings for the cue (conducted in TextTrackCue).
    m_currentSettings = input.restOfInputAsString();
    return CueText;
}

WebVTTParser::ParseState WebVTTParser::collectCueText(const String& line)
{
    // Step 34.
    if (line.isEmpty()) {
        createNewCue();
        return Id;
    }
    // Step 35.
    if (line.contains("-->")) {
        // Step 39-40.
        createNewCue();

        // Step 41 - New iteration of the cue loop.
        return recoverCue(line);
    }
    if (!m_currentContent.isEmpty())
        m_currentContent.append('\n');
    m_currentContent.append(line);

    return CueText;
}

WebVTTParser::ParseState WebVTTParser::recoverCue(const String& line)
{
    // Step 17 and 21.
    resetCueValues();

    // Step 22.
    return collectTimingsAndSettings(line);
}

WebVTTParser::ParseState WebVTTParser::ignoreBadCue(const String& line)
{
    if (line.isEmpty())
        return Id;
    if (line.contains("-->"))
        return recoverCue(line);
    return BadCue;
}

// A helper class for the construction of a "cue fragment" from the cue text.
class WebVTTTreeBuilder {
public:
    WebVTTTreeBuilder(Document& document)
        : m_document(document) { }

    Ref<DocumentFragment> buildFromString(const String& cueText);

private:
    void constructTreeFromToken(Document&);

    WebVTTToken m_token;
    RefPtr<ContainerNode> m_currentNode;
    Vector<AtomString> m_languageStack;
    Document& m_document;
};

Ref<DocumentFragment> WebVTTTreeBuilder::buildFromString(const String& cueText)
{
    // Cue text processing based on
    // 5.4 WebVTT cue text parsing rules, and
    // 5.5 WebVTT cue text DOM construction rules.
    auto fragment = DocumentFragment::create(m_document);

    if (cueText.isEmpty()) {
        fragment->parserAppendChild(Text::create(m_document, emptyString()));
        return fragment;
    }

    m_currentNode = fragment.ptr();

    WebVTTTokenizer tokenizer(cueText);
    m_languageStack.clear();

    while (tokenizer.nextToken(m_token))
        constructTreeFromToken(m_document);
    
    return fragment;
}

Ref<DocumentFragment> WebVTTParser::createDocumentFragmentFromCueText(Document& document, const String& cueText)
{
    WebVTTTreeBuilder treeBuilder(document);
    return treeBuilder.buildFromString(cueText);
}

void WebVTTParser::createNewCue()
{
    auto cue = WebVTTCueData::create();
    cue->setStartTime(m_currentStartTime);
    cue->setEndTime(m_currentEndTime);
    cue->setContent(m_currentContent.toString());
    cue->setId(m_currentId);
    cue->setSettings(m_currentSettings);

    m_cuelist.append(WTFMove(cue));
    m_client.newCuesParsed();
}

void WebVTTParser::resetCueValues()
{
    m_currentId = emptyString();
    m_currentSettings = emptyString();
    m_currentStartTime = MediaTime::zeroTime();
    m_currentEndTime = MediaTime::zeroTime();
    m_currentContent.clear();
}

bool WebVTTParser::collectTimeStamp(const String& line, MediaTime& timeStamp)
{
    if (line.isEmpty())
        return false;

    VTTScanner input(line);
    return collectTimeStamp(input, timeStamp);
}

bool WebVTTParser::collectTimeStamp(VTTScanner& input, MediaTime& timeStamp)
{
    // Collect a WebVTT timestamp (5.3 WebVTT cue timings and settings parsing.)
    // Steps 1 - 4 - Initial checks, let most significant units be minutes.
    enum Mode { minutes, hours };
    Mode mode = minutes;

    // Steps 5 - 7 - Collect a sequence of characters that are 0-9.
    // If not 2 characters or value is greater than 59, interpret as hours.
    int value1;
    unsigned value1Digits = input.scanDigits(value1);
    if (!value1Digits)
        return false;
    if (value1Digits != 2 || value1 > 59)
        mode = hours;

    // Steps 8 - 11 - Collect the next sequence of 0-9 after ':' (must be 2 chars).
    int value2;
    if (!input.scan(':') || input.scanDigits(value2) != 2)
        return false;

    // Step 12 - Detect whether this timestamp includes hours.
    int value3;
    if (mode == hours || input.match(':')) {
        if (!input.scan(':') || input.scanDigits(value3) != 2)
            return false;
    } else {
        value3 = value2;
        value2 = value1;
        value1 = 0;
    }

    // Steps 13 - 17 - Collect next sequence of 0-9 after '.' (must be 3 chars).
    int value4;
    if (!input.scan('.') || input.scanDigits(value4) != 3)
        return false;
    if (value2 > 59 || value3 > 59)
        return false;

    // Steps 18 - 19 - Calculate result.
    timeStamp = MediaTime::createWithDouble((value1 * secondsPerHour) + (value2 * secondsPerMinute) + value3 + (value4 * secondsPerMillisecond));
    return true;
}

static WebVTTNodeType tokenToNodeType(WebVTTToken& token)
{
    switch (token.name().length()) {
    case 1:
        if (token.name()[0] == 'c')
            return WebVTTNodeTypeClass;
        if (token.name()[0] == 'v')
            return WebVTTNodeTypeVoice;
        if (token.name()[0] == 'b')
            return WebVTTNodeTypeBold;
        if (token.name()[0] == 'i')
            return WebVTTNodeTypeItalic;
        if (token.name()[0] == 'u')
            return WebVTTNodeTypeUnderline;
        break;
    case 2:
        if (token.name()[0] == 'r' && token.name()[1] == 't')
            return WebVTTNodeTypeRubyText;
        break;
    case 4:
        if (token.name()[0] == 'r' && token.name()[1] == 'u' && token.name()[2] == 'b' && token.name()[3] == 'y')
            return WebVTTNodeTypeRuby;
        if (token.name()[0] == 'l' && token.name()[1] == 'a' && token.name()[2] == 'n' && token.name()[3] == 'g')
            return WebVTTNodeTypeLanguage;
        break;
    }
    return WebVTTNodeTypeNone;
}

void WebVTTTreeBuilder::constructTreeFromToken(Document& document)
{
    // http://dev.w3.org/html5/webvtt/#webvtt-cue-text-dom-construction-rules

    switch (m_token.type()) {
    case WebVTTTokenTypes::Character: {
        m_currentNode->parserAppendChild(Text::create(document, m_token.characters()));
        break;
    }
    case WebVTTTokenTypes::StartTag: {
        WebVTTNodeType nodeType = tokenToNodeType(m_token);
        if (nodeType == WebVTTNodeTypeNone)
            break;

        WebVTTNodeType currentType = is<WebVTTElement>(*m_currentNode) ? downcast<WebVTTElement>(*m_currentNode).webVTTNodeType() : WebVTTNodeTypeNone;
        // <rt> is only allowed if the current node is <ruby>.
        if (nodeType == WebVTTNodeTypeRubyText && currentType != WebVTTNodeTypeRuby)
            break;

        auto child = WebVTTElement::create(nodeType, document);
        if (!m_token.classes().isEmpty())
            child->setAttributeWithoutSynchronization(classAttr, m_token.classes());

        if (nodeType == WebVTTNodeTypeVoice)
            child->setAttributeWithoutSynchronization(WebVTTElement::voiceAttributeName(), m_token.annotation());
        else if (nodeType == WebVTTNodeTypeLanguage) {
            m_languageStack.append(m_token.annotation());
            child->setAttributeWithoutSynchronization(WebVTTElement::langAttributeName(), m_languageStack.last());
        }
        if (!m_languageStack.isEmpty())
            child->setLanguage(m_languageStack.last());
        m_currentNode->parserAppendChild(child);
        m_currentNode = WTFMove(child);
        break;
    }
    case WebVTTTokenTypes::EndTag: {
        WebVTTNodeType nodeType = tokenToNodeType(m_token);
        if (nodeType == WebVTTNodeTypeNone)
            break;
        
        // The only non-VTTElement would be the DocumentFragment root. (Text
        // nodes and PIs will never appear as m_currentNode.)
        if (!is<WebVTTElement>(*m_currentNode))
            break;

        WebVTTNodeType currentType = downcast<WebVTTElement>(*m_currentNode).webVTTNodeType();
        bool matchesCurrent = nodeType == currentType;
        if (!matchesCurrent) {
            // </ruby> auto-closes <rt>
            if (currentType == WebVTTNodeTypeRubyText && nodeType == WebVTTNodeTypeRuby) {
                if (m_currentNode->parentNode())
                    m_currentNode = m_currentNode->parentNode();
            } else
                break;
        }
        if (nodeType == WebVTTNodeTypeLanguage)
            m_languageStack.removeLast();
        if (m_currentNode->parentNode())
            m_currentNode = m_currentNode->parentNode();
        break;
    }
    case WebVTTTokenTypes::TimestampTag: {
        String charactersString = m_token.characters();
        MediaTime parsedTimeStamp;
        if (WebVTTParser::collectTimeStamp(charactersString, parsedTimeStamp))
            m_currentNode->parserAppendChild(ProcessingInstruction::create(document, "timestamp", charactersString));
        break;
    }
    default:
        break;
    }
}

}

#endif
