#ifndef DocumentTimeline_h
#define DocumentTimeline_h
#include "core/animation/AnimationEffect.h"
#include "core/animation/AnimationPlayer.h"
#include "core/dom/Element.h"
#include "core/events/Event.h"
#include "platform/Timer.h"
#include "wtf/RefCounted.h"
#include "wtf/RefPtr.h"
#include "wtf/Vector.h"
namespace WebCore {
class Document;
class TimedItem;
class DocumentTimeline : public RefCounted<DocumentTimeline> {
public:
    class PlatformTiming {
    public:
        
        virtual void wakeAfter(double duration) = 0;
        virtual void cancelWake() = 0;
        virtual void serviceOnNextFrame() = 0;
        virtual ~PlatformTiming() { }
    };
    static PassRefPtr<DocumentTimeline> create(Document*, PassOwnPtr<PlatformTiming> = nullptr);
    ~DocumentTimeline();
    void serviceAnimations(AnimationPlayer::UpdateReason);
    
    AnimationPlayer* createAnimationPlayer(TimedItem*);
    AnimationPlayer* play(TimedItem*);
    void playerDestroyed(AnimationPlayer* player)
    {
        ASSERT(m_players.contains(player));
        m_players.remove(player);
    }
    
    
    void setZeroTime(double);
    bool hasStarted() const { return !isNull(m_zeroTime); }
    bool hasPendingUpdates() const { return !m_playersNeedingUpdate.isEmpty(); }
    double zeroTime() const { return m_zeroTime; }
    double currentTime(bool& isNull);
    double currentTime();
    double effectiveTime();
    void pauseAnimationsForTesting(double);
    size_t numberOfActiveAnimationsForTesting() const;
    void setOutdatedAnimationPlayer(AnimationPlayer*);
    bool hasOutdatedAnimationPlayer() const { return m_hasOutdatedAnimationPlayer; }
    Document* document() { return m_document; }
    void detachFromDocument();
protected:
    DocumentTimeline(Document*, PassOwnPtr<PlatformTiming>);
private:
    double m_zeroTime;
    Document* m_document;
    
    
    HashSet<RefPtr<AnimationPlayer> > m_playersNeedingUpdate;
    HashSet<AnimationPlayer*> m_players;
    bool m_hasOutdatedAnimationPlayer;
    void wake();
    friend class SMILTimeContainer;
    static const double s_minimumDelay;
    OwnPtr<PlatformTiming> m_timing;
    class DocumentTimelineTiming FINAL : public PlatformTiming {
    public:
        DocumentTimelineTiming(DocumentTimeline* documentTimeline)
            : m_timeline(documentTimeline)
            , m_timer(this, &DocumentTimelineTiming::timerFired)
        {
            ASSERT(m_timeline);
        }
        virtual void wakeAfter(double duration) OVERRIDE;
        virtual void cancelWake() OVERRIDE;
        virtual void serviceOnNextFrame() OVERRIDE;
        void timerFired(Timer<DocumentTimelineTiming>*) { m_timeline->wake(); }
    private:
        DocumentTimeline* m_timeline;
        Timer<DocumentTimelineTiming> m_timer;
    };
    friend class AnimationDocumentTimelineTest;
};
} 
#endif