/*
 * Copyright (C) 2007 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. 
 * 3.  Neither the name of Apple Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 "Animation.h"
#include "CSSPropertyBlendingClient.h"
#include "CSSPropertyNames.h"
#include "RenderStyleConstants.h"

namespace WebCore {

class CompositeAnimation;
class Element;
class FloatRect;
class LayoutRect;
class RenderBoxModelObject;
class RenderElement;
class RenderStyle;
class TimingFunction;

class AnimationBase : public RefCounted<AnimationBase>
    , public CSSPropertyBlendingClient {
    friend class CompositeAnimation;
    friend class CSSPropertyAnimation;
    WTF_MAKE_FAST_ALLOCATED;
public:
    AnimationBase(const Animation& transition, Element&, CompositeAnimation&);
    virtual ~AnimationBase();

    Element* element() const { return m_element.get(); }
    const RenderStyle& currentStyle() const override;
    RenderElement* renderer() const override;
    RenderBoxModelObject* compositedRenderer() const;
    void clear();

    double duration() const;

    // Animations and Transitions go through the states below. When entering the STARTED state
    // the animation is started. This may or may not require deferred response from the animator.
    // If so, we stay in this state until that response is received (and it returns the start time).
    // Otherwise, we use the current time as the start time and go immediately to AnimationState::Looping
    // or AnimationState::Ending.
    enum class AnimationState {
        New,                        // animation just created, animation not running yet
        StartWaitTimer,             // start timer running, waiting for fire
        StartWaitStyleAvailable,    // waiting for style setup so we can start animations
        StartWaitResponse,          // animation started, waiting for response
        Looping,                    // response received, animation running, loop timer running, waiting for fire
        Ending,                     // received, animation running, end timer running, waiting for fire
        PausedNew,                  // in pause mode when animation was created
        PausedWaitTimer,            // in pause mode when animation started
        PausedWaitStyleAvailable,   // in pause mode when waiting for style setup
        PausedWaitResponse,         // animation paused when in STARTING state
        PausedRun,                  // animation paused when in LOOPING or ENDING state
        Done,                       // end timer fired, animation finished and removed
        FillingForwards             // animation has ended and is retaining its final value
    };

    enum class AnimationStateInput {
        MakeNew,           // reset back to new from any state
        StartAnimation,    // animation requests a start
        RestartAnimation,  // force a restart from any state
        StartTimerFired,   // start timer fired
        StyleAvailable,    // style is setup, ready to start animating
        StartTimeSet,      // m_startTime was set
        LoopTimerFired,    // loop timer fired
        EndTimerFired,     // end timer fired
        PauseOverride,     // pause an animation due to override
        ResumeOverride,    // resume an overridden animation
        PlayStateRunning,  // play state paused -> running
        PlayStatePaused,   // play state running -> paused
        EndAnimation       // force an end from any state
    };

    // Called when animation is in AnimationState::New to start animation
    void updateStateMachine(AnimationStateInput, double param);

    // Animation has actually started, at passed time
    void onAnimationStartResponse(MonotonicTime startTime)
    {
        updateStateMachine(AnimationStateInput::StartTimeSet, startTime.secondsSinceEpoch().seconds());
    }

    // Called to change to or from paused state
    void updatePlayState(EAnimPlayState);
    bool playStatePlaying() const;

    bool waitingToStart() const { return m_animationState == AnimationState::New || m_animationState == AnimationState::StartWaitTimer || m_animationState == AnimationState::PausedNew; }
    bool preActive() const
    {
        return m_animationState == AnimationState::New || m_animationState == AnimationState::StartWaitTimer || m_animationState == AnimationState::StartWaitStyleAvailable || m_animationState == AnimationState::StartWaitResponse;
    }

    bool postActive() const { return m_animationState == AnimationState::Done; }
    bool fillingForwards() const { return m_animationState == AnimationState::FillingForwards; }
    bool active() const { return !postActive() && !preActive(); }
    bool running() const { return !isNew() && !postActive(); }
    bool paused() const { return m_pauseTime || m_animationState == AnimationState::PausedNew; }
    bool inPausedState() const { return m_animationState >= AnimationState::PausedNew && m_animationState <= AnimationState::PausedRun; }
    bool isNew() const { return m_animationState == AnimationState::New || m_animationState == AnimationState::PausedNew; }
    bool waitingForStartTime() const { return m_animationState == AnimationState::StartWaitResponse; }
    bool waitingForStyleAvailable() const { return m_animationState == AnimationState::StartWaitStyleAvailable; }

    bool isAccelerated() const override { return m_isAccelerated; }

    virtual std::optional<Seconds> timeToNextService();

    double progress(double scale = 1, double offset = 0, const TimingFunction* = nullptr) const;

    virtual void getAnimatedStyle(std::unique_ptr<RenderStyle>& /*animatedStyle*/) = 0;

    virtual bool computeExtentOfTransformAnimation(LayoutRect&) const = 0;

    virtual bool shouldFireEvents() const { return false; }

    void fireAnimationEventsIfNeeded();

    bool animationsMatch(const Animation&) const;

    const Animation& animation() const { return m_animation; }
    void setAnimation(const Animation& animation) { m_animation = const_cast<Animation&>(animation); }

    // Return true if this animation is overridden. This will only be the case for
    // ImplicitAnimations and is used to determine whether or not we should force
    // set the start time. If an animation is overridden, it will probably not get
    // back the AnimationStateInput::StartTimeSet input.
    virtual bool overridden() const { return false; }

    // Does this animation/transition involve the given property?
    virtual bool affectsProperty(CSSPropertyID /*property*/) const { return false; }

    enum RunningStates {
        Delaying = 1 << 0,
        Paused = 1 << 1,
        Running = 1 << 2,
    };
    typedef unsigned RunningState;
    bool isAnimatingProperty(CSSPropertyID property, bool acceleratedOnly, RunningState runningState) const
    {
        if (acceleratedOnly && !m_isAccelerated)
            return false;

        if (!affectsProperty(property))
            return false;

        if ((runningState & Delaying) && preActive())
            return true;

        if ((runningState & Paused) && inPausedState())
            return true;

        if ((runningState & Running) && !inPausedState() && (m_animationState >= AnimationState::StartWaitStyleAvailable && m_animationState < AnimationState::Done))
            return true;

        return false;
    }

    bool transformFunctionListsMatch() const override { return m_transformFunctionListsMatch; }
    bool filterFunctionListsMatch() const override { return m_filterFunctionListsMatch; }
#if ENABLE(FILTERS_LEVEL_2)
    bool backdropFilterFunctionListsMatch() const override { return m_backdropFilterFunctionListsMatch; }
#endif

    // Freeze the animation; used by DumpRenderTree.
    void freezeAtTime(double t);

    // Play and pause API
    void play();
    void pause();
    
    double beginAnimationUpdateTime() const;
    
    double getElapsedTime() const;
    // Setting the elapsed time will adjust the start time and possibly pause time.
    void setElapsedTime(double);
    
    void styleAvailable() 
    {
        ASSERT(waitingForStyleAvailable());
        updateStateMachine(AnimationStateInput::StyleAvailable, -1);
    }

protected:
    virtual void overrideAnimations() { }
    virtual void resumeOverriddenAnimations() { }

    CompositeAnimation* compositeAnimation() { return m_compositeAnimation; }

    // These are called when the corresponding timer fires so subclasses can do any extra work
    virtual void onAnimationStart(double /*elapsedTime*/) { }
    virtual void onAnimationIteration(double /*elapsedTime*/) { }
    virtual void onAnimationEnd(double /*elapsedTime*/) { }
    
    // timeOffset is an offset from the current time when the animation should start. Negative values are OK.
    // Return value indicates whether to expect an asynchronous notifyAnimationStarted() callback.
    virtual bool startAnimation(double /*timeOffset*/) { return false; }
    // timeOffset is the time at which the animation is being paused.
    virtual void pauseAnimation(double /*timeOffset*/) { }
    virtual void endAnimation() { }

    virtual const RenderStyle& unanimatedStyle() const = 0;

    void goIntoEndingOrLoopingState();

    AnimationState state() const { return m_animationState; }

    static void setNeedsStyleRecalc(Element*);
    
    void getTimeToNextEvent(Seconds& time, bool& isLooping) const;

    double fractionalTime(double scale, double elapsedTime, double offset) const;

    // These return true if we can easily compute a bounding box by applying the style's transform to the bounds rect.
    bool computeTransformedExtentViaTransformList(const FloatRect& rendererBox, const RenderStyle&, LayoutRect& bounds) const;
    bool computeTransformedExtentViaMatrix(const FloatRect& rendererBox, const RenderStyle&, LayoutRect& bounds) const;

private:
    RefPtr<Element> m_element;

protected:
    CompositeAnimation* m_compositeAnimation; // Ideally this would be a reference, but it has to be cleared if an animation is destroyed inside an event callback.
    Ref<Animation> m_animation;

    std::optional<double> m_startTime;
    std::optional<double> m_pauseTime;
    double m_requestedStartTime { 0 };
    std::optional<double> m_totalDuration;
    std::optional<double> m_nextIterationDuration;

    AnimationState m_animationState { AnimationState::New };
    bool m_isAccelerated { false };
    bool m_transformFunctionListsMatch { false };
    bool m_filterFunctionListsMatch { false };
#if ENABLE(FILTERS_LEVEL_2)
    bool m_backdropFilterFunctionListsMatch { false };
#endif
};

} // namespace WebCore
