/*
 * Copyright (C) 2017-2018 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.
 */

#pragma once

#include "ActiveDOMObject.h"
#include "DOMPromiseProxy.h"
#include "EventTarget.h"
#include "ExceptionOr.h"
#include <wtf/Forward.h>
#include <wtf/Optional.h>
#include <wtf/Ref.h>
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
#include <wtf/Seconds.h>
#include <wtf/UniqueRef.h>

namespace WebCore {

class AnimationEffectReadOnly;
class AnimationPlaybackEvent;
class AnimationTimeline;
class Document;
class Element;
class RenderStyle;

class WebAnimation : public RefCounted<WebAnimation>, public EventTargetWithInlineData, public ActiveDOMObject {
public:
    static Ref<WebAnimation> create(Document&, AnimationEffectReadOnly*);
    static Ref<WebAnimation> create(Document&, AnimationEffectReadOnly*, AnimationTimeline*);
    ~WebAnimation();

    virtual bool isDeclarativeAnimation() const { return false; }
    virtual bool isCSSAnimation() const { return false; }
    virtual bool isCSSTransition() const { return false; }

    virtual bool canBeListed() const;

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

    AnimationEffectReadOnly* effect() const { return m_effect.get(); }
    void setEffect(RefPtr<AnimationEffectReadOnly>&&);
    AnimationTimeline* timeline() const { return m_timeline.get(); }
    virtual void setTimeline(RefPtr<AnimationTimeline>&&);

    std::optional<double> bindingsStartTime() const;
    void setBindingsStartTime(std::optional<double>);
    std::optional<Seconds> startTime() const;
    void setStartTime(std::optional<Seconds>);

    std::optional<double> bindingsCurrentTime() const;
    ExceptionOr<void> setBindingsCurrentTime(std::optional<double>);
    std::optional<Seconds> currentTime() const;
    ExceptionOr<void> setCurrentTime(std::optional<Seconds>);

    enum class Silently { Yes, No };
    double playbackRate() const { return m_playbackRate; }
    void setPlaybackRate(double, Silently silently = Silently::No );

    enum class PlayState { Idle, Running, Paused, Finished };
    PlayState playState() const;

    bool pending() const { return hasPendingPauseTask() || hasPendingPlayTask(); }

    using ReadyPromise = DOMPromiseProxyWithResolveCallback<IDLInterface<WebAnimation>>;
    ReadyPromise& ready() { return m_readyPromise.get(); }

    using FinishedPromise = DOMPromiseProxyWithResolveCallback<IDLInterface<WebAnimation>>;
    FinishedPromise& finished() { return m_finishedPromise.get(); }

    virtual void cancel();
    ExceptionOr<void> finish();
    ExceptionOr<void> play();
    ExceptionOr<void> pause();
    ExceptionOr<void> reverse();

    Seconds timeToNextRequiredTick() const;
    void resolve(RenderStyle&);
    void effectTargetDidChange(Element* previousTarget, Element* newTarget);
    void acceleratedRunningStateDidChange();
    void startOrStopAccelerated();

    void timingModelDidChange();
    void suspendEffectInvalidation();
    void unsuspendEffectInvalidation();

    String description();

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

protected:
    explicit WebAnimation(Document&);

    bool isEffectInvalidationSuspended() { return m_suspendCount; }

private:
    enum class DidSeek { Yes, No };
    enum class SynchronouslyNotify { Yes, No };
    enum class RespectHoldTime { Yes, No };
    enum class AutoRewind { Yes, No };
    enum class TimeToRunPendingTask { NotScheduled, ASAP, WhenReady };

    void updateFinishedState(DidSeek, SynchronouslyNotify);
    void enqueueAnimationPlaybackEvent(const AtomicString&, std::optional<Seconds>, std::optional<Seconds>);
    Seconds effectEndTime() const;
    WebAnimation& readyPromiseResolve();
    WebAnimation& finishedPromiseResolve();
    void setHoldTime(std::optional<Seconds>);
    std::optional<Seconds> currentTime(RespectHoldTime) const;
    ExceptionOr<void> silentlySetCurrentTime(std::optional<Seconds>);
    void finishNotificationSteps();
    void scheduleMicrotaskIfNeeded();
    void performMicrotask();
    void setTimeToRunPendingPauseTask(TimeToRunPendingTask);
    void setTimeToRunPendingPlayTask(TimeToRunPendingTask);
    bool hasPendingPauseTask() const { return m_timeToRunPendingPauseTask != TimeToRunPendingTask::NotScheduled; }
    bool hasPendingPlayTask() const { return m_timeToRunPendingPlayTask != TimeToRunPendingTask::NotScheduled; }
    void updatePendingTasks();
    ExceptionOr<void> play(AutoRewind);
    void runPendingPauseTask();
    void runPendingPlayTask();
    void resetPendingTasks();
    
    String m_id;
    RefPtr<AnimationEffectReadOnly> m_effect;
    RefPtr<AnimationTimeline> m_timeline;
    std::optional<Seconds> m_previousCurrentTime;
    std::optional<Seconds> m_startTime;
    std::optional<Seconds> m_holdTime;
    int m_suspendCount { 0 };
    double m_playbackRate { 1 };
    bool m_isStopped { false };
    bool m_finishNotificationStepsMicrotaskPending;
    bool m_scheduledMicrotask;
    UniqueRef<ReadyPromise> m_readyPromise;
    UniqueRef<FinishedPromise> m_finishedPromise;
    TimeToRunPendingTask m_timeToRunPendingPlayTask { TimeToRunPendingTask::NotScheduled };
    TimeToRunPendingTask m_timeToRunPendingPauseTask { TimeToRunPendingTask::NotScheduled };

    // ActiveDOMObject.
    const char* activeDOMObjectName() const final;
    bool canSuspendForDocumentSuspension() const final;
    void stop() final;

    // EventTarget
    EventTargetInterface eventTargetInterface() const final { return WebAnimationEventTargetInterfaceType; }
    void refEventTarget() final { ref(); }
    void derefEventTarget() final { deref(); }
    ScriptExecutionContext* scriptExecutionContext() const final { return ActiveDOMObject::scriptExecutionContext(); }
};

} // namespace WebCore

#define SPECIALIZE_TYPE_TRAITS_WEB_ANIMATION(ToValueTypeName, predicate) \
SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ToValueTypeName) \
static bool isType(const WebCore::WebAnimation& value) { return value.predicate; } \
SPECIALIZE_TYPE_TRAITS_END()
