/*
 * Copyright (C) 2012-2017 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:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 "InbandGenericTextTrack.h"

#if ENABLE(VIDEO_TRACK)

#include "DataCue.h"
#include "HTMLMediaElement.h"
#include "InbandTextTrackPrivate.h"
#include "Logging.h"
#include "VTTRegionList.h"
#include <math.h>
#include <wtf/text/CString.h>

namespace WebCore {

void GenericTextTrackCueMap::add(GenericCueData& cueData, TextTrackCueGeneric& cue)
{
    m_dataToCueMap.add(&cueData, &cue);
    m_cueToDataMap.add(&cue, &cueData);
}

TextTrackCueGeneric* GenericTextTrackCueMap::find(GenericCueData& cueData)
{
    return m_dataToCueMap.get(&cueData);
}

GenericCueData* GenericTextTrackCueMap::find(TextTrackCue& cue)
{
    return m_cueToDataMap.get(&cue);
}

void GenericTextTrackCueMap::remove(GenericCueData& cueData)
{
    if (auto cue = m_dataToCueMap.take(&cueData))
        m_cueToDataMap.remove(cue);
}

void GenericTextTrackCueMap::remove(TextTrackCue& cue)
{
    if (auto data = m_cueToDataMap.take(&cue))
        m_dataToCueMap.remove(data);
}

inline InbandGenericTextTrack::InbandGenericTextTrack(ScriptExecutionContext& context, TextTrackClient& client, InbandTextTrackPrivate& trackPrivate)
    : InbandTextTrack(context, client, trackPrivate)
{
}

Ref<InbandGenericTextTrack> InbandGenericTextTrack::create(ScriptExecutionContext& context, TextTrackClient& client, InbandTextTrackPrivate& trackPrivate)
{
    return adoptRef(*new InbandGenericTextTrack(context, client, trackPrivate));
}

InbandGenericTextTrack::~InbandGenericTextTrack() = default;

void InbandGenericTextTrack::updateCueFromCueData(TextTrackCueGeneric& cue, GenericCueData& cueData)
{
    cue.willChange();

    cue.setStartTime(cueData.startTime());
    MediaTime endTime = cueData.endTime();
    if (endTime.isPositiveInfinite() && mediaElement())
        endTime = mediaElement()->durationMediaTime();
    cue.setEndTime(endTime);
    cue.setText(cueData.content());
    cue.setId(cueData.id());
    cue.setBaseFontSizeRelativeToVideoHeight(cueData.baseFontSize());
    cue.setFontSizeMultiplier(cueData.relativeFontSize());
    cue.setFontName(cueData.fontName());

    if (cueData.position() > 0)
        cue.setPosition(std::round(cueData.position()));
    if (cueData.line() > 0)
        cue.setLine(std::round(cueData.line()));
    if (cueData.size() > 0)
        cue.setSize(std::round(cueData.size()));
    if (cueData.backgroundColor().isValid())
        cue.setBackgroundColor(cueData.backgroundColor().rgb());
    if (cueData.foregroundColor().isValid())
        cue.setForegroundColor(cueData.foregroundColor().rgb());
    if (cueData.highlightColor().isValid())
        cue.setHighlightColor(cueData.highlightColor().rgb());

    if (cueData.align() == GenericCueData::Start)
        cue.setAlign(ASCIILiteral("start"));
    else if (cueData.align() == GenericCueData::Middle)
        cue.setAlign(ASCIILiteral("middle"));
    else if (cueData.align() == GenericCueData::End)
        cue.setAlign(ASCIILiteral("end"));
    cue.setSnapToLines(false);

    cue.didChange();
}

void InbandGenericTextTrack::addGenericCue(GenericCueData& cueData)
{
    if (m_cueMap.find(cueData))
        return;

    auto cue = TextTrackCueGeneric::create(*scriptExecutionContext(), cueData.startTime(), cueData.endTime(), cueData.content());
    updateCueFromCueData(cue.get(), cueData);
    if (hasCue(cue.ptr(), TextTrackCue::IgnoreDuration)) {
        DEBUG_LOG(LOGIDENTIFIER, "ignoring already added cue: ", cue.get());
        return;
    }

    DEBUG_LOG(LOGIDENTIFIER, "added cue: ", cue.get());

    if (cueData.status() != GenericCueData::Complete)
        m_cueMap.add(cueData, cue);

    addCue(WTFMove(cue));
}

void InbandGenericTextTrack::updateGenericCue(GenericCueData& cueData)
{
    auto cue = makeRefPtr(m_cueMap.find(cueData));
    if (!cue)
        return;

    updateCueFromCueData(*cue, cueData);

    if (cueData.status() == GenericCueData::Complete)
        m_cueMap.remove(cueData);
}

void InbandGenericTextTrack::removeGenericCue(GenericCueData& cueData)
{
    auto cue = makeRefPtr(m_cueMap.find(cueData));
    if (cue) {
        DEBUG_LOG(LOGIDENTIFIER, *cue);
        removeCue(*cue);
    } else
        DEBUG_LOG(LOGIDENTIFIER, "UNABLE to find cue: ", *cue);

}

ExceptionOr<void> InbandGenericTextTrack::removeCue(TextTrackCue& cue)
{
    auto result = TextTrack::removeCue(cue);
    if (!result.hasException())
        m_cueMap.remove(cue);
    return result;
}

WebVTTParser& InbandGenericTextTrack::parser()
{
    if (!m_webVTTParser)
        m_webVTTParser = std::make_unique<WebVTTParser>(static_cast<WebVTTParserClient*>(this), scriptExecutionContext());
    return *m_webVTTParser;
}

void InbandGenericTextTrack::parseWebVTTCueData(const ISOWebVTTCue& cueData)
{
    parser().parseCueData(cueData);
}

void InbandGenericTextTrack::parseWebVTTFileHeader(String&& header)
{
    parser().parseFileHeader(WTFMove(header));
}

void InbandGenericTextTrack::newCuesParsed()
{
    Vector<RefPtr<WebVTTCueData>> cues;
    parser().getNewCues(cues);

    for (auto& cueData : cues) {
        auto vttCue = VTTCue::create(*scriptExecutionContext(), *cueData);

        if (hasCue(vttCue.ptr(), TextTrackCue::IgnoreDuration)) {
            DEBUG_LOG(LOGIDENTIFIER, "ignoring already added cue: ", vttCue.get());
            return;
        }

        DEBUG_LOG(LOGIDENTIFIER, vttCue.get());

        addCue(WTFMove(vttCue));
    }
}

void InbandGenericTextTrack::newRegionsParsed()
{
    Vector<RefPtr<VTTRegion>> newRegions;
    parser().getNewRegions(newRegions);

    for (auto& region : newRegions) {
        region->setTrack(this);
        regions()->add(region.releaseNonNull());
    }
}

void InbandGenericTextTrack::fileFailedToParse()
{
    ERROR_LOG(LOGIDENTIFIER);
}

} // namespace WebCore

#endif
