/*
 * Copyright (C) 2011 Google Inc. All rights reserved.
 * 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:
 *
 *     * 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.
 */

#pragma once

#if ENABLE(VIDEO_TRACK)

#include "Document.h"
#include "DocumentFragment.h"
#include "HTMLElement.h"
#include <wtf/JSONValues.h>
#include <wtf/MediaTime.h>

namespace WebCore {

class TextTrack;
class TextTrackCue;

class TextTrackCueBox : public HTMLElement {
    WTF_MAKE_ISO_ALLOCATED(TextTrackCueBox);
public:
    static Ref<TextTrackCueBox> create(Document& document, TextTrackCue& cue)
    {
        return adoptRef(*new TextTrackCueBox(document, cue));
    }

    TextTrackCue* getCue() const;
    virtual void applyCSSProperties(const IntSize&) { }

protected:
    TextTrackCueBox(Document&, TextTrackCue&);
    ~TextTrackCueBox() { }

private:

    WeakPtr<TextTrackCue> m_cue;
};

class TextTrackCue : public RefCounted<TextTrackCue>, public EventTargetWithInlineData, public CanMakeWeakPtr<TextTrackCue> {
    WTF_MAKE_ISO_ALLOCATED(TextTrackCue);
public:
    static const AtomString& cueShadowPseudoId();
    static const AtomString& cueBackdropShadowPseudoId();
    static const AtomString& cueBoxShadowPseudoId();

    static ExceptionOr<Ref<TextTrackCue>> create(ScriptExecutionContext&, double start, double end, DocumentFragment&);

    TextTrack* track() const;
    void setTrack(TextTrack*);

    const String& id() const { return m_id; }
    void setId(const String&);

    double startTime() const { return startMediaTime().toDouble(); }
    void setStartTime(double);

    double endTime() const { return endMediaTime().toDouble(); }
    void setEndTime(double);

    bool pauseOnExit() const { return m_pauseOnExit; }
    void setPauseOnExit(bool);

    MediaTime startMediaTime() const { return m_startTime; }
    void setStartTime(const MediaTime&);

    MediaTime endMediaTime() const { return m_endTime; }
    void setEndTime(const MediaTime&);

    bool isActive();
    virtual void setIsActive(bool);

    virtual bool isOrderedBefore(const TextTrackCue*) const;
    virtual bool isPositionedAbove(const TextTrackCue* cue) const { return isOrderedBefore(cue); }

    bool hasEquivalentStartTime(const TextTrackCue&) const;

    enum CueType { Generic, Data, ConvertedToWebVTT, WebVTT };
    virtual CueType cueType() const { return CueType::Generic; }
    virtual bool isRenderable() const;

    enum CueMatchRules { MatchAllFields, IgnoreDuration };
    virtual bool isEqual(const TextTrackCue&, CueMatchRules) const;
    virtual bool doesExtendCue(const TextTrackCue&) const;

    void willChange();
    virtual void didChange();

    virtual RefPtr<TextTrackCueBox> getDisplayTree(const IntSize&, int);
    virtual void removeDisplayTree();

    virtual RefPtr<DocumentFragment> getCueAsHTML();

    String toJSONString() const;

    using RefCounted::ref;
    using RefCounted::deref;

    virtual void recalculateStyles() { m_displayTreeNeedsUpdate = true; }
    virtual void setFontSize(int, const IntSize&, bool important);
    virtual void updateDisplayTree(const MediaTime&) { };

protected:
    TextTrackCue(ScriptExecutionContext&, const MediaTime& start, const MediaTime& end, DocumentFragment&&);
    TextTrackCue(ScriptExecutionContext&, const MediaTime& start, const MediaTime& end);

    Document& ownerDocument() { return downcast<Document>(m_scriptExecutionContext); }

    virtual void toJSON(JSON::Object&) const;

private:
    void refEventTarget() final { ref(); }
    void derefEventTarget() final { deref(); }

    using EventTarget::dispatchEvent;
    void dispatchEvent(Event&) final;

    EventTargetInterface eventTargetInterface() const final { return TextTrackCueEventTargetInterfaceType; }
    ScriptExecutionContext* scriptExecutionContext() const final { return &m_scriptExecutionContext; }

    virtual bool cueContentsMatch(const TextTrackCue&) const;

    void rebuildDisplayTree();

    String m_id;
    MediaTime m_startTime;
    MediaTime m_endTime;
    int m_processingCueChanges { 0 };

    TextTrack* m_track { nullptr };

    ScriptExecutionContext& m_scriptExecutionContext;

    RefPtr<DocumentFragment> m_cueNode;
    RefPtr<TextTrackCueBox> m_displayTree;

    int m_fontSize { 0 };
    bool m_fontSizeIsImportant { false };

    bool m_isActive { false };
    bool m_pauseOnExit { false };
    bool m_displayTreeNeedsUpdate { true };
};

#ifndef NDEBUG
TextStream& operator<<(TextStream&, const TextTrackCue&);
#endif

} // namespace WebCore

namespace WTF {

template<typename> struct LogArgument;

template<> struct LogArgument<WebCore::TextTrackCue> {
    static String toString(const WebCore::TextTrackCue& cue) { return cue.toJSONString(); }
};

}

#endif
