/*
 * Copyright (C) 2019 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. 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 INC. 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 "TaskSource.h"
#include <wtf/Function.h>
#include <wtf/RefCounted.h>
#include <wtf/StdLibExtras.h>
#include <wtf/WeakHashSet.h>
#include <wtf/WeakPtr.h>

namespace WebCore {

class ActiveDOMCallbackMicrotask;
class EventLoopTaskGroup;
class EventTarget;
class Microtask;
class MicrotaskQueue;
class ScriptExecutionContext;

class EventLoopTask {
    WTF_MAKE_NONCOPYABLE(EventLoopTask);
    WTF_MAKE_FAST_ALLOCATED;

public:
    virtual ~EventLoopTask() = default;

    TaskSource taskSource() { return m_taskSource; }
    virtual void execute() = 0;

    EventLoopTaskGroup* group() const { return m_group.get(); }

protected:
    EventLoopTask(TaskSource, EventLoopTaskGroup&);

private:
    const TaskSource m_taskSource;
    WeakPtr<EventLoopTaskGroup> m_group;
};

// https://html.spec.whatwg.org/multipage/webappapis.html#event-loop
class EventLoop : public RefCounted<EventLoop>, public CanMakeWeakPtr<EventLoop> {
public:
    virtual ~EventLoop() = default;

    typedef Function<void ()> TaskFunction;
    void queueTask(std::unique_ptr<EventLoopTask>&&);

    // https://html.spec.whatwg.org/multipage/webappapis.html#queue-a-microtask
    void queueMicrotask(std::unique_ptr<EventLoopTask>&&);

    // https://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint
    void performMicrotaskCheckpoint();
    virtual MicrotaskQueue& microtaskQueue() = 0;

    void resumeGroup(EventLoopTaskGroup&);
    void stopGroup(EventLoopTaskGroup&);

protected:
    EventLoop() = default;
    void run();
    void clearAllTasks();

private:
    void scheduleToRunIfNeeded();
    virtual void scheduleToRun() = 0;
    virtual bool isContextThread() const = 0;

    // Use a global queue instead of multiple task queues since HTML5 spec allows UA to pick arbitrary queue.
    Vector<std::unique_ptr<EventLoopTask>> m_tasks;
    WeakHashSet<EventLoopTaskGroup> m_groupsWithSuspenedTasks;
    bool m_isScheduledToRun { false };
};

class EventLoopTaskGroup : public CanMakeWeakPtr<EventLoopTaskGroup> {
    WTF_MAKE_NONCOPYABLE(EventLoopTaskGroup);
    WTF_MAKE_FAST_ALLOCATED;

public:
    EventLoopTaskGroup(EventLoop& eventLoop)
        : m_eventLoop(makeWeakPtr(eventLoop))
    {
    }

    bool hasSameEventLoopAs(EventLoopTaskGroup& otherGroup)
    {
        ASSERT(m_eventLoop);
        return m_eventLoop == otherGroup.m_eventLoop;
    }

    bool matchesTask(EventLoopTask& task) const
    {
        auto* group = task.group();
        return group == this;
    }

    void stopAndDiscardAllTasks()
    {
        m_state = State::Stopped;
        if (auto* eventLoop = m_eventLoop.get())
            eventLoop->stopGroup(*this);
    }

    void suspend()
    {
        ASSERT(m_state != State::Stopped);
        m_state = State::Suspended;
        // We don't remove suspended tasks to preserve the ordering.
        // EventLoop::run checks whether each task's group is suspended or not.
    }

    void resume()
    {
        ASSERT(m_state != State::Stopped);
        m_state = State::Running;
        if (auto* eventLoop = m_eventLoop.get())
            eventLoop->resumeGroup(*this);
    }

    bool isStoppedPermanently() { return m_state == State::Stopped; }
    bool isSuspended() { return m_state == State::Suspended; }

    void queueTask(std::unique_ptr<EventLoopTask>&&);
    WEBCORE_EXPORT void queueTask(TaskSource, EventLoop::TaskFunction&&);

    // https://html.spec.whatwg.org/multipage/webappapis.html#queue-a-microtask
    WEBCORE_EXPORT void queueMicrotask(EventLoop::TaskFunction&&);
    MicrotaskQueue& microtaskQueue() { return m_eventLoop->microtaskQueue(); }

    // https://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint
    void performMicrotaskCheckpoint();

private:
    enum class State : uint8_t { Running, Suspended, Stopped };

    WeakPtr<EventLoop> m_eventLoop;
    State m_state { State::Running };
};

inline EventLoopTask::EventLoopTask(TaskSource source, EventLoopTaskGroup& group)
    : m_taskSource(source)
    , m_group(makeWeakPtr(group))
{ }

} // namespace WebCore
