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

#include "config.h"
#include "PromiseTimer.h"

#include "JSPromise.h"
#include "StrongInlines.h"
#include "VM.h"
#include <wtf/Locker.h>
#include <wtf/RunLoop.h>

namespace JSC {

namespace PromiseTimerInternal {
static constexpr bool verbose = false;
}

PromiseTimer::PromiseTimer(VM& vm)
    : Base(vm)
{
}

void PromiseTimer::doWork(VM& vm)
{
    ASSERT(vm.currentThreadIsHoldingAPILock());
    m_taskLock.lock();
    cancelTimer();
    if (!m_runTasks) {
        m_taskLock.unlock();
        return;
    }

    while (!m_tasks.isEmpty()) {
        auto [ticket, task] = m_tasks.takeLast();
        dataLogLnIf(PromiseTimerInternal::verbose, "Doing work on promise: ", RawPointer(ticket));

        // We may have already canceled these promises.
        if (m_pendingPromises.contains(ticket)) {
            // Allow tasks we run now to schedule work.
            m_currentlyRunningTask = true;
            m_taskLock.unlock(); 

            task();
            vm.drainMicrotasks();

            m_taskLock.lock();
            m_currentlyRunningTask = false;
        }
    }

    if (m_pendingPromises.isEmpty() && m_shouldStopRunLoopWhenAllPromisesFinish) {
#if USE(CF)
        CFRunLoopStop(vm.runLoop());
#else
        RunLoop::current().stop();
#endif
    }

    m_taskLock.unlock();
}

void PromiseTimer::runRunLoop()
{
    ASSERT(!m_apiLock->vm()->currentThreadIsHoldingAPILock());
#if USE(CF)
    ASSERT(CFRunLoopGetCurrent() == m_apiLock->vm()->runLoop());
#endif
    m_shouldStopRunLoopWhenAllPromisesFinish = true;
    if (m_pendingPromises.size()) {
#if USE(CF)
        CFRunLoopRun();
#else
        RunLoop::run();
#endif
    }
}

void PromiseTimer::addPendingPromise(VM& vm, JSPromise* ticket, Vector<Strong<JSCell>>&& dependencies)
{
    ASSERT(vm.currentThreadIsHoldingAPILock());
    for (unsigned i = 0; i < dependencies.size(); ++i)
        ASSERT(dependencies[i].get() != ticket);

    auto result = m_pendingPromises.add(ticket, Vector<Strong<JSCell>>());
    if (result.isNewEntry) {
        dataLogLnIf(PromiseTimerInternal::verbose, "Adding new pending promise: ", RawPointer(ticket));
        dependencies.append(Strong<JSCell>(vm, ticket));
        result.iterator->value = WTFMove(dependencies);
    } else {
        dataLogLnIf(PromiseTimerInternal::verbose, "Adding new dependencies for promise: ", RawPointer(ticket));
        result.iterator->value.appendVector(dependencies);
    }
}

bool PromiseTimer::hasPendingPromise(JSPromise* ticket)
{
    ASSERT(ticket->vm().currentThreadIsHoldingAPILock());
    return m_pendingPromises.contains(ticket);
}

bool PromiseTimer::hasDependancyInPendingPromise(JSPromise* ticket, JSCell* dependency)
{
    ASSERT(ticket->vm().currentThreadIsHoldingAPILock());
    ASSERT(m_pendingPromises.contains(ticket));

    auto result = m_pendingPromises.get(ticket);
    return result.contains(dependency);
}

bool PromiseTimer::cancelPendingPromise(JSPromise* ticket)
{
    ASSERT(ticket->vm().currentThreadIsHoldingAPILock());
    bool result = m_pendingPromises.remove(ticket);

    if (result)
        dataLogLnIf(PromiseTimerInternal::verbose, "Canceling promise: ", RawPointer(ticket));

    return result;
}

void PromiseTimer::scheduleWorkSoon(JSPromise* ticket, Task&& task)
{
    LockHolder locker(m_taskLock);
    m_tasks.append(std::make_tuple(ticket, WTFMove(task)));
    if (!isScheduled() && !m_currentlyRunningTask)
        setTimeUntilFire(0_s);
}

} // namespace JSC
