/*
 * Copyright (C) 2021, 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.
 */

#include "config.h"
#include "WebLockRegistry.h"

#include "Exception.h"
#include "WebLockManager.h"
#include "WebLockManagerSnapshot.h"
#include <wtf/CompletionHandler.h>
#include <wtf/NeverDestroyed.h>
#include <wtf/RobinHoodHashMap.h>
#include <wtf/text/StringConcatenateNumbers.h>

namespace WebCore {

static RefPtr<WebLockRegistry>& sharedRegistry()
{
    static MainThreadNeverDestroyed<RefPtr<WebLockRegistry>> registry;
    return registry;
}

WebLockRegistry& WebLockRegistry::shared()
{
    auto& registry = sharedRegistry();
    if (!registry)
        registry= LocalWebLockRegistry::create();
    return *registry;
}

void WebLockRegistry::setSharedRegistry(Ref<WebLockRegistry>&& registry)
{
    ASSERT(!sharedRegistry());
    sharedRegistry() = WTFMove(registry);
}

class LocalWebLockRegistry::PerOriginRegistry : public RefCounted<PerOriginRegistry>, public CanMakeWeakPtr<PerOriginRegistry> {
public:
    static Ref<PerOriginRegistry> create(LocalWebLockRegistry&, PAL::SessionID, const ClientOrigin&);
    ~PerOriginRegistry();

    struct LockInfo {
        Ref<PerOriginRegistry> registry;
        WebLockIdentifier lockIdentifier;
        ScriptExecutionContextIdentifier clientID;
        WebLockMode mode;
        Function<void()> lockStolenHandler;
    };

    void requestLock(WebLockIdentifier, ScriptExecutionContextIdentifier, const String& name, WebLockMode, bool steal, bool ifAvailable, Function<void(bool)>&& grantedHandler, Function<void()>&& lockStolenHandler);
    void releaseLock(WebLockIdentifier, const String& name);
    void abortLockRequest(WebLockIdentifier, const String& name, CompletionHandler<void(bool)>&&);
    void snapshot(CompletionHandler<void(WebLockManagerSnapshot&&)>&&);
    void clientsAreGoingAway(const Function<bool(const LockInfo&)>& matchClient);

private:
    PerOriginRegistry(LocalWebLockRegistry&, PAL::SessionID, const ClientOrigin&);

    struct LockRequest : LockInfo {
        String name;
        Function<void(bool)> grantedHandler;
    };

    void processLockRequestQueue(const String& name, Deque<LockRequest>&);
    bool isGrantable(const LockRequest&) const;

    WeakPtr<LocalWebLockRegistry> m_globalRegistry;
    PAL::SessionID m_sessionID;
    ClientOrigin m_clientOrigin;
    FastRobinHoodHashMap<String, Deque<LockRequest>> m_lockRequestQueueMap;
    FastRobinHoodHashMap<String, Vector<LockInfo>> m_heldLocks;
};

LocalWebLockRegistry::LocalWebLockRegistry() = default;

LocalWebLockRegistry::~LocalWebLockRegistry() = default;

auto LocalWebLockRegistry::ensureRegistryForOrigin(PAL::SessionID sessionID, const ClientOrigin& clientOrigin) -> Ref<PerOriginRegistry>
{
    if (auto existingRegistry = m_perOriginRegistries.get({ sessionID, clientOrigin }))
        return *existingRegistry;

    return PerOriginRegistry::create(*this, sessionID, clientOrigin);
}

auto LocalWebLockRegistry::existingRegistryForOrigin(PAL::SessionID sessionID, const ClientOrigin& clientOrigin) const -> RefPtr<PerOriginRegistry>
{
    return m_perOriginRegistries.get({ sessionID, clientOrigin }).get();
}

Ref<LocalWebLockRegistry::PerOriginRegistry> LocalWebLockRegistry::PerOriginRegistry::create(LocalWebLockRegistry& globalRegistry, PAL::SessionID sessionID, const ClientOrigin& clientOrigin)
{
    return adoptRef(*new PerOriginRegistry(globalRegistry, sessionID, clientOrigin));
}

LocalWebLockRegistry::PerOriginRegistry::PerOriginRegistry(LocalWebLockRegistry& globalRegistry, PAL::SessionID sessionID, const ClientOrigin& clientOrigin)
    : m_globalRegistry(globalRegistry)
    , m_sessionID(sessionID)
    , m_clientOrigin(clientOrigin)
{
    globalRegistry.m_perOriginRegistries.add({ sessionID, clientOrigin }, WeakPtr { * this });
}

LocalWebLockRegistry::PerOriginRegistry::~PerOriginRegistry()
{
    if (m_globalRegistry)
        m_globalRegistry->m_perOriginRegistries.remove({ m_sessionID, m_clientOrigin });
}

void LocalWebLockRegistry::requestLock(PAL::SessionID sessionID, const ClientOrigin& clientOrigin, WebLockIdentifier lockIdentifier, ScriptExecutionContextIdentifier clientID, const String& name, WebLockMode mode, bool steal, bool ifAvailable, Function<void(bool)>&& grantedHandler, Function<void()>&& lockStolenHandler)
{
    ensureRegistryForOrigin(sessionID, clientOrigin)->requestLock(lockIdentifier, clientID, name, mode, steal, ifAvailable, WTFMove(grantedHandler), WTFMove(lockStolenHandler));
}

// https://wicg.github.io/web-locks/#request-a-lock
void LocalWebLockRegistry::PerOriginRegistry::requestLock(WebLockIdentifier lockIdentifier, ScriptExecutionContextIdentifier clientID, const String& name, WebLockMode mode, bool steal, bool ifAvailable, Function<void(bool)>&& grantedHandler, Function<void()>&& lockStolenHandler)
{
    LockRequest request { { *this, lockIdentifier, clientID, mode, WTFMove(lockStolenHandler) }, name, WTFMove(grantedHandler) };

    if (steal) {
        auto it = m_heldLocks.find(name);
        if (it != m_heldLocks.end()) {
            for (auto& lockInfo : it->value)
                lockInfo.lockStolenHandler();
            m_heldLocks.remove(it);
        }
    } else if (ifAvailable && !isGrantable(request)) {
        request.grantedHandler(false);
        return;
    }
    auto& queue = m_lockRequestQueueMap.ensure(name, [] { return Deque<LockRequest> { }; }).iterator->value;
    if (steal)
        queue.prepend(WTFMove(request));
    else
        queue.append(WTFMove(request));
    processLockRequestQueue(name, queue);
}

void LocalWebLockRegistry::releaseLock(PAL::SessionID sessionID, const ClientOrigin& clientOrigin, WebLockIdentifier lockIdentifier, ScriptExecutionContextIdentifier, const String& name)
{
    if (auto registry = existingRegistryForOrigin(sessionID, clientOrigin))
        registry->releaseLock(lockIdentifier, name);
}

// https://wicg.github.io/web-locks/#algorithm-release-lock
void LocalWebLockRegistry::PerOriginRegistry::releaseLock(WebLockIdentifier lockIdentifier, const String& name)
{
    auto it = m_heldLocks.find(name);
    if (it == m_heldLocks.end())
        return;

    auto& locksWithName = it->value;
    locksWithName.removeFirstMatching([lockIdentifier](auto& lockInfo) { return lockIdentifier == lockInfo.lockIdentifier; });
    if (locksWithName.isEmpty())
        m_heldLocks.remove(it);

    auto queueIterator = m_lockRequestQueueMap.find(name);
    if (queueIterator != m_lockRequestQueueMap.end())
        processLockRequestQueue(name, queueIterator->value);
}

void LocalWebLockRegistry::abortLockRequest(PAL::SessionID sessionID, const ClientOrigin& clientOrigin, WebLockIdentifier lockIdentifier, ScriptExecutionContextIdentifier, const String& name, CompletionHandler<void(bool)>&& completionHandler)
{
    auto registry = existingRegistryForOrigin(sessionID, clientOrigin);
    if (!registry)
        return completionHandler(false);

    registry->abortLockRequest(lockIdentifier, name, WTFMove(completionHandler));
}

// https://wicg.github.io/web-locks/#abort-the-request
void LocalWebLockRegistry::PerOriginRegistry::abortLockRequest(WebLockIdentifier lockIdentifier, const String& name, CompletionHandler<void(bool)>&& completionHandler)
{
    auto queueIterator = m_lockRequestQueueMap.find(name);
    if (queueIterator == m_lockRequestQueueMap.end())
        return completionHandler(false);

    auto& queue = queueIterator->value;
    auto requestIterator = queue.findIf([lockIdentifier](auto& request) { return request.lockIdentifier == lockIdentifier; });
    if (requestIterator == queue.end())
        return completionHandler(false);

    queue.remove(requestIterator);
    if (queue.isEmpty()) {
        m_lockRequestQueueMap.remove(queueIterator);
        return completionHandler(true);
    }

    processLockRequestQueue(name, queue);
    completionHandler(true);
}

// https://wicg.github.io/web-locks/#grantable
bool LocalWebLockRegistry::PerOriginRegistry::isGrantable(const LockRequest& request) const
{
    auto queueIterator = m_lockRequestQueueMap.find(request.name);
    if (queueIterator != m_lockRequestQueueMap.end() && &queueIterator->value.first() != &request)
        return false;

    switch (request.mode) {
    case WebLockMode::Exclusive:
        return !m_heldLocks.contains(request.name);
    case WebLockMode::Shared:
        break;
    }
    auto it = m_heldLocks.find(request.name);
    return it == m_heldLocks.end() || it->value.first().mode != WebLockMode::Exclusive;
}

// https://wicg.github.io/web-locks/#process-the-lock-request-queue
void LocalWebLockRegistry::PerOriginRegistry::processLockRequestQueue(const String& name, Deque<LockRequest>& queue)
{
    while (!queue.isEmpty()) {
        if (!isGrantable(queue.first()))
            return;
        auto request = queue.takeFirst();
        auto& locksForName = m_heldLocks.ensure(request.name, [] { return Vector<LockInfo> { }; }).iterator->value;
        auto grantedHandler = WTFMove(request.grantedHandler);
        locksForName.append(WTFMove(request));
        grantedHandler(true);
    }
    auto removedQueue = m_lockRequestQueueMap.take(name);
    ASSERT_UNUSED(removedQueue, removedQueue.isEmpty());
}

void LocalWebLockRegistry::snapshot(PAL::SessionID sessionID, const ClientOrigin& clientOrigin, CompletionHandler<void(WebLockManager::Snapshot&&)>&& completionHandler)
{
    auto registry = existingRegistryForOrigin(sessionID, clientOrigin);
    if (!registry)
        return completionHandler({ });

    registry->snapshot(WTFMove(completionHandler));
}

// https://wicg.github.io/web-locks/#snapshot-the-lock-state
void LocalWebLockRegistry::PerOriginRegistry::snapshot(CompletionHandler<void(WebLockManager::Snapshot&&)>&& completionHandler)
{
    WebLockManager::Snapshot snapshot;
    for (auto& pair : m_lockRequestQueueMap) {
        for (auto& request : pair.value)
            snapshot.pending.append({ pair.key, request.mode, request.clientID.toString() });
    }
    for (auto& pair : m_heldLocks) {
        for (auto& lockInfo : pair.value)
            snapshot.held.append({ pair.key, lockInfo.mode, lockInfo.clientID.toString() });
    }

    completionHandler(WTFMove(snapshot));
}

void LocalWebLockRegistry::clientIsGoingAway(PAL::SessionID sessionID, const ClientOrigin& clientOrigin, ScriptExecutionContextIdentifier clientID)
{
    if (auto registry = existingRegistryForOrigin(sessionID, clientOrigin))
        registry->clientsAreGoingAway([clientID](auto& lockInfo) { return lockInfo.clientID == clientID; });
}

// https://wicg.github.io/web-locks/#agent-integration
void LocalWebLockRegistry::PerOriginRegistry::clientsAreGoingAway(const Function<bool(const LockInfo&)>& matchClient)
{
    // FIXME: This is inefficient. We could optimize this by keeping track of which locks map to which clients.
    HashSet<String> namesOfQueuesToProcess;

    Vector<String> namesWithoutRequests;
    for (auto& pair : m_lockRequestQueueMap) {
        if (!pair.value.removeAllMatching(matchClient))
            continue;
        if (pair.value.isEmpty())
            namesWithoutRequests.append(pair.key);
        else
            namesOfQueuesToProcess.add(pair.key);
    }
    for (auto& name : namesWithoutRequests)
        m_lockRequestQueueMap.remove(name);

    Vector<String> namesWithoutLocks;
    for (auto& pair : m_heldLocks) {
        if (!pair.value.removeAllMatching(matchClient))
            continue;
        if (pair.value.isEmpty())
            namesWithoutLocks.append(pair.key);
        namesOfQueuesToProcess.add(pair.key);
    }
    for (auto& name : namesWithoutLocks)
        m_heldLocks.remove(name);

    for (auto& name : namesOfQueuesToProcess) {
        auto queueIterator = m_lockRequestQueueMap.find(name);
        if (queueIterator != m_lockRequestQueueMap.end())
            processLockRequestQueue(name, queueIterator->value);
    }
}

void LocalWebLockRegistry::clientsAreGoingAway(ProcessIdentifier processIdentifier)
{
    Vector<std::pair<PAL::SessionID, ClientOrigin>> clientOrigins = copyToVector(m_perOriginRegistries.keys());
    for (auto& [sessionID, clientOrigin] : clientOrigins) {
        if (auto registry = existingRegistryForOrigin(sessionID, clientOrigin))
            registry->clientsAreGoingAway([processIdentifier](auto& lockInfo) { return lockInfo.clientID.processIdentifier() == processIdentifier; });
    }
}

} // namespace WebCore
