/*
 * 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 "WorkerFileSystemStorageConnection.h"

#include "WorkerGlobalScope.h"
#include "WorkerLoaderProxy.h"
#include "WorkerThread.h"

namespace WebCore {

Ref<WorkerFileSystemStorageConnection> WorkerFileSystemStorageConnection::create(WorkerGlobalScope& scope, Ref<FileSystemStorageConnection>&& mainThreadConnection)
{
    return adoptRef(*new WorkerFileSystemStorageConnection(scope, WTFMove(mainThreadConnection)));
}

WorkerFileSystemStorageConnection::WorkerFileSystemStorageConnection(WorkerGlobalScope& scope, Ref<FileSystemStorageConnection>&& connection)
    : m_scope(scope)
    , m_mainThreadConnection(WTFMove(connection))
{
}

WorkerFileSystemStorageConnection::~WorkerFileSystemStorageConnection()
{
    if (m_mainThreadConnection)
        callOnMainThread([mainThreadConenction = WTFMove(m_mainThreadConnection)]() { });
}

void WorkerFileSystemStorageConnection::connectionClosed()
{
    scopeClosed();
}

void WorkerFileSystemStorageConnection::scopeClosed()
{
    auto sameEntryCallbacks = std::exchange(m_sameEntryCallbacks, { });
    for (auto& callback : sameEntryCallbacks.values())
        callback(Exception { InvalidStateError });

    auto getHandleCallbacks = std::exchange(m_getHandleCallbacks, { });
    for (auto& callback : getHandleCallbacks.values())
        callback(Exception { InvalidStateError });

    auto removeEntryCallbacks = std::exchange(m_voidCallbacks, { });
    for (auto& callback : removeEntryCallbacks.values())
        callback(Exception { InvalidStateError });

    auto resolveCallbacks = std::exchange(m_resolveCallbacks, { });
    for (auto& callback : resolveCallbacks.values())
        callback(Exception { InvalidStateError });

    m_scope = nullptr;
}

void WorkerFileSystemStorageConnection::isSameEntry(FileSystemHandleIdentifier identifier, FileSystemHandleIdentifier otherIdentifier, FileSystemStorageConnection::SameEntryCallback&& callback)
{
    if (!m_scope)
        return callback(Exception { InvalidStateError });

    auto callbackIdentifier = CallbackIdentifier::generateThreadSafe();
    m_sameEntryCallbacks.add(callbackIdentifier, WTFMove(callback));

    callOnMainThread([callbackIdentifier, workerThread = Ref { m_scope->thread() }, mainThreadConnection = m_mainThreadConnection, identifier, otherIdentifier]() mutable {
        auto mainThreadCallback = [callbackIdentifier, workerThread = WTFMove(workerThread)](auto result) mutable {
            workerThread->runLoop().postTaskForMode([callbackIdentifier, result = crossThreadCopy(result)] (auto& scope) mutable {
                if (auto connection = downcast<WorkerGlobalScope>(scope).fileSystemStorageConnection())
                    connection->didIsSameEntry(callbackIdentifier, WTFMove(result));
            }, WorkerRunLoop::defaultMode());
        };

        mainThreadConnection->isSameEntry(identifier, otherIdentifier, WTFMove(mainThreadCallback));
    });
}

void WorkerFileSystemStorageConnection::didIsSameEntry(CallbackIdentifier callbackIdentifier, ExceptionOr<bool>&& result)
{
    if (auto callback = m_sameEntryCallbacks.take(callbackIdentifier))
        callback(WTFMove(result));
}

void WorkerFileSystemStorageConnection::getFileHandle(FileSystemHandleIdentifier identifier, const String& name, bool createIfNecessary, FileSystemStorageConnection::GetHandleCallback&& callback)
{
    if (!m_scope)
        return callback(Exception { InvalidStateError });

    auto callbackIdentifier = CallbackIdentifier::generateThreadSafe();
    m_getHandleCallbacks.add(callbackIdentifier, WTFMove(callback));

    callOnMainThread([callbackIdentifier, workerThread = Ref { m_scope->thread() }, mainThreadConnection = m_mainThreadConnection, identifier, name = name.isolatedCopy(), createIfNecessary]() mutable {
        auto mainThreadCallback = [callbackIdentifier, workerThread = WTFMove(workerThread)](auto result) mutable {
            workerThread->runLoop().postTaskForMode([callbackIdentifier, result = crossThreadCopy(result)] (auto& scope) mutable {
                if (auto connection = downcast<WorkerGlobalScope>(scope).fileSystemStorageConnection())
                    connection->didGetHandle(callbackIdentifier, WTFMove(result));
            }, WorkerRunLoop::defaultMode());
        };

        mainThreadConnection->getFileHandle(identifier, name, createIfNecessary, WTFMove(mainThreadCallback));
    });
}

void WorkerFileSystemStorageConnection::getDirectoryHandle(FileSystemHandleIdentifier identifier, const String& name, bool createIfNecessary, FileSystemStorageConnection::GetHandleCallback&& callback)
{
    if (!m_scope)
        return callback(Exception { InvalidStateError });

    auto callbackIdentifier = CallbackIdentifier::generateThreadSafe();
    m_getHandleCallbacks.add(callbackIdentifier, WTFMove(callback));

    callOnMainThread([callbackIdentifier, workerThread = Ref { m_scope->thread() }, mainThreadConnection = m_mainThreadConnection, identifier, name = name.isolatedCopy(), createIfNecessary]() mutable {
        auto mainThreadCallback = [callbackIdentifier, workerThread = WTFMove(workerThread)](auto result) mutable {
            workerThread->runLoop().postTaskForMode([callbackIdentifier, result = crossThreadCopy(result)] (auto& scope) mutable {
                if (auto connection = downcast<WorkerGlobalScope>(scope).fileSystemStorageConnection())
                    connection->didGetHandle(callbackIdentifier, WTFMove(result));
            }, WorkerRunLoop::defaultMode());
        };

        mainThreadConnection->getDirectoryHandle(identifier, name, createIfNecessary, WTFMove(mainThreadCallback));
    });
}

void WorkerFileSystemStorageConnection::didGetHandle(CallbackIdentifier callbackIdentifier, ExceptionOr<FileSystemHandleIdentifier>&& result)
{
    if (auto callback = m_getHandleCallbacks.take(callbackIdentifier))
        callback(WTFMove(result));
}

void WorkerFileSystemStorageConnection::removeEntry(FileSystemHandleIdentifier identifier, const String& name, bool deleteRecursively, FileSystemStorageConnection::VoidCallback&& callback)
{
    if (!m_scope)
        return callback(Exception { InvalidStateError });

    auto callbackIdentifier = CallbackIdentifier::generateThreadSafe();
    m_voidCallbacks.add(callbackIdentifier, WTFMove(callback));

    callOnMainThread([callbackIdentifier, workerThread = Ref { m_scope->thread() }, mainThreadConnection = m_mainThreadConnection, identifier, name = name.isolatedCopy(), deleteRecursively]() mutable {
        auto mainThreadCallback = [callbackIdentifier, workerThread = WTFMove(workerThread)](auto result) mutable {
            workerThread->runLoop().postTaskForMode([callbackIdentifier, result = crossThreadCopy(result)] (auto& scope) mutable {
                if (auto connection = downcast<WorkerGlobalScope>(scope).fileSystemStorageConnection())
                    connection->completeVoidCallback(callbackIdentifier, WTFMove(result));
            }, WorkerRunLoop::defaultMode());
        };

        mainThreadConnection->removeEntry(identifier, name, deleteRecursively, WTFMove(mainThreadCallback));
    });
}

void WorkerFileSystemStorageConnection::resolve(FileSystemHandleIdentifier identifier, FileSystemHandleIdentifier otherIdentifier, FileSystemStorageConnection::ResolveCallback&& callback)
{
    if (!m_scope)
        return callback(Exception { InvalidStateError });

    auto callbackIdentifier = CallbackIdentifier::generateThreadSafe();
    m_resolveCallbacks.add(callbackIdentifier, WTFMove(callback));

    callOnMainThread([callbackIdentifier, workerThread = Ref { m_scope->thread() }, mainThreadConnection = m_mainThreadConnection, identifier, otherIdentifier]() mutable {
        auto mainThreadCallback = [callbackIdentifier, workerThread = WTFMove(workerThread)](auto result) mutable {
            workerThread->runLoop().postTaskForMode([callbackIdentifier, result = crossThreadCopy(result)] (auto& scope) mutable {
                if (auto connection = downcast<WorkerGlobalScope>(scope).fileSystemStorageConnection())
                    connection->didResolve(callbackIdentifier, WTFMove(result));
            }, WorkerRunLoop::defaultMode());
        };

        mainThreadConnection->resolve(identifier, otherIdentifier, WTFMove(mainThreadCallback));
    });
}

void WorkerFileSystemStorageConnection::didResolve(CallbackIdentifier callbackIdentifier, ExceptionOr<Vector<String>>&& result)
{
    if (auto callback = m_resolveCallbacks.take(callbackIdentifier))
        callback(WTFMove(result));
}

void WorkerFileSystemStorageConnection::didCreateSyncAccessHandle(CallbackIdentifier callbackIdentifier, ExceptionOr<std::pair<FileSystemSyncAccessHandleIdentifier, FileSystem::PlatformFileHandle>>&& result)
{
    if (auto callback = m_getAccessHandlCallbacks.take(callbackIdentifier))
        callback(WTFMove(result));
}

void WorkerFileSystemStorageConnection::completeIntegerCallback(CallbackIdentifier callbackIdentifier, ExceptionOr<uint64_t>&& result)
{
    if (auto callback = m_integerCallbacks.take(callbackIdentifier))
        callback(WTFMove(result));
}

void WorkerFileSystemStorageConnection::completeVoidCallback(CallbackIdentifier callbackIdentifier, ExceptionOr<void>&& result)
{
    if (auto callback = m_voidCallbacks.take(callbackIdentifier))
        callback(WTFMove(result));
}

void WorkerFileSystemStorageConnection::createSyncAccessHandle(FileSystemHandleIdentifier identifier, FileSystemStorageConnection::GetAccessHandleCallback&& callback)
{
    if (!m_scope)
        return callback(Exception { InvalidStateError });

    auto callbackIdentifier = CallbackIdentifier::generateThreadSafe();
    m_getAccessHandlCallbacks.add(callbackIdentifier, WTFMove(callback));

    callOnMainThread([callbackIdentifier, workerThread = Ref { m_scope->thread() }, mainThreadConnection = m_mainThreadConnection, identifier]() mutable {
        auto mainThreadCallback = [callbackIdentifier, workerThread = WTFMove(workerThread)](auto result) mutable {
            auto crossThreadResult = result;
            if (result.hasException())
                crossThreadResult = crossThreadCopy(result.exception());
            workerThread->runLoop().postTaskForMode([callbackIdentifier, result = WTFMove(crossThreadResult)] (auto& scope) mutable {
                if (auto connection = downcast<WorkerGlobalScope>(scope).fileSystemStorageConnection())
                    connection->didCreateSyncAccessHandle(callbackIdentifier, WTFMove(result));
            }, WorkerRunLoop::defaultMode());
        };

        mainThreadConnection->createSyncAccessHandle(identifier, WTFMove(mainThreadCallback));
    });
}

void WorkerFileSystemStorageConnection::getSize(FileSystemHandleIdentifier identifier, FileSystemSyncAccessHandleIdentifier accessHandleIdentifier, FileSystemStorageConnection::IntegerCallback&& callback)
{
    if (!m_scope)
        return callback(Exception { InvalidStateError });

    auto callbackIdentifier = CallbackIdentifier::generateThreadSafe();
    m_integerCallbacks.add(callbackIdentifier, WTFMove(callback));

    callOnMainThread([callbackIdentifier, workerThread = Ref { m_scope->thread() }, mainThreadConnection = m_mainThreadConnection, identifier, accessHandleIdentifier]() mutable {
        auto mainThreadCallback = [callbackIdentifier, workerThread = WTFMove(workerThread)](auto result) mutable {
            workerThread->runLoop().postTaskForMode([callbackIdentifier, result = crossThreadCopy(result)] (auto& scope) mutable {
                if (auto connection = downcast<WorkerGlobalScope>(scope).fileSystemStorageConnection())
                    connection->completeIntegerCallback(callbackIdentifier, WTFMove(result));
            }, WorkerRunLoop::defaultMode());
        };

        mainThreadConnection->getSize(identifier, accessHandleIdentifier, WTFMove(mainThreadCallback));
    });
}

void WorkerFileSystemStorageConnection::truncate(FileSystemHandleIdentifier identifier, FileSystemSyncAccessHandleIdentifier accessHandleIdentifier, uint64_t size, FileSystemStorageConnection::VoidCallback&& callback)
{
    if (!m_scope)
        return callback(Exception { InvalidStateError });

    auto callbackIdentifier = CallbackIdentifier::generateThreadSafe();
    m_voidCallbacks.add(callbackIdentifier, WTFMove(callback));

    callOnMainThread([callbackIdentifier, workerThread = Ref { m_scope->thread() }, mainThreadConnection = m_mainThreadConnection, identifier, accessHandleIdentifier, size]() mutable {
        auto mainThreadCallback = [callbackIdentifier, workerThread = WTFMove(workerThread)](auto result) mutable {
            workerThread->runLoop().postTaskForMode([callbackIdentifier, result = crossThreadCopy(result)] (auto& scope) mutable {
                if (auto connection = downcast<WorkerGlobalScope>(scope).fileSystemStorageConnection())
                    connection->completeVoidCallback(callbackIdentifier, WTFMove(result));
            }, WorkerRunLoop::defaultMode());
        };

        mainThreadConnection->truncate(identifier, accessHandleIdentifier, size, WTFMove(mainThreadCallback));
    });
}

void WorkerFileSystemStorageConnection::flush(FileSystemHandleIdentifier identifier, FileSystemSyncAccessHandleIdentifier accessHandleIdentifier, FileSystemStorageConnection::VoidCallback&& callback)
{
    if (!m_scope)
        return callback(Exception { InvalidStateError });

    auto callbackIdentifier = CallbackIdentifier::generateThreadSafe();
    m_voidCallbacks.add(callbackIdentifier, WTFMove(callback));

    callOnMainThread([callbackIdentifier, workerThread = Ref { m_scope->thread() }, mainThreadConnection = m_mainThreadConnection, identifier, accessHandleIdentifier]() mutable {
        auto mainThreadCallback = [callbackIdentifier, workerThread = WTFMove(workerThread)](auto result) mutable {
            workerThread->runLoop().postTaskForMode([callbackIdentifier, result = crossThreadCopy(result)] (auto& scope) mutable {
                if (auto connection = downcast<WorkerGlobalScope>(scope).fileSystemStorageConnection())
                    connection->completeVoidCallback(callbackIdentifier, WTFMove(result));
            }, WorkerRunLoop::defaultMode());
        };

        mainThreadConnection->flush(identifier, accessHandleIdentifier, WTFMove(mainThreadCallback));
    });
}

void WorkerFileSystemStorageConnection::close(FileSystemHandleIdentifier identifier, FileSystemSyncAccessHandleIdentifier accessHandleIdentifier, FileSystemStorageConnection::VoidCallback&& callback)
{
    if (!m_scope)
        return callback(Exception { InvalidStateError });

    auto callbackIdentifier = CallbackIdentifier::generateThreadSafe();
    m_voidCallbacks.add(callbackIdentifier, WTFMove(callback));

    callOnMainThread([callbackIdentifier, workerThread = Ref { m_scope->thread() }, mainThreadConnection = m_mainThreadConnection, identifier, accessHandleIdentifier]() mutable {
        auto mainThreadCallback = [callbackIdentifier, workerThread = WTFMove(workerThread)](auto result) mutable {
            workerThread->runLoop().postTaskForMode([callbackIdentifier, result = crossThreadCopy(result)] (auto& scope) mutable {
                if (auto connection = downcast<WorkerGlobalScope>(scope).fileSystemStorageConnection())
                    connection->completeVoidCallback(callbackIdentifier, WTFMove(result));
            }, WorkerRunLoop::defaultMode());
        };

        mainThreadConnection->close(identifier, accessHandleIdentifier, WTFMove(mainThreadCallback));
    });
}

void WorkerFileSystemStorageConnection::getHandleNames(FileSystemHandleIdentifier identifier, GetHandleNamesCallback&& callback)
{
    if (!m_scope)
        return callback(Exception { InvalidStateError });

    auto callbackIdentifier = CallbackIdentifier::generateThreadSafe();
    m_getHandleNamesCallbacks.add(callbackIdentifier, WTFMove(callback));

    callOnMainThread([callbackIdentifier, workerThread = Ref { m_scope->thread() }, mainThreadConnection = m_mainThreadConnection, identifier]() mutable {
        auto mainThreadCallback = [callbackIdentifier, workerThread = WTFMove(workerThread)](auto result) mutable {
            workerThread->runLoop().postTaskForMode([callbackIdentifier, result = crossThreadCopy(result)] (auto& scope) mutable {
                if (auto connection = downcast<WorkerGlobalScope>(scope).fileSystemStorageConnection())
                    connection->didGetHandleNames(callbackIdentifier, WTFMove(result));
            }, WorkerRunLoop::defaultMode());
        };

        mainThreadConnection->getHandleNames(identifier, WTFMove(mainThreadCallback));
    });
}

void WorkerFileSystemStorageConnection::didGetHandleNames(CallbackIdentifier callbackIdentifier, ExceptionOr<Vector<String>>&& result)
{
    if (auto callback = m_getHandleNamesCallbacks.take(callbackIdentifier))
        callback(WTFMove(result));
}

void WorkerFileSystemStorageConnection::getHandle(FileSystemHandleIdentifier identifier, const String& name, GetHandleWithTypeCallback&& callback)
{
    if (!m_scope)
        return callback(Exception { InvalidStateError });

    auto callbackIdentifier = CallbackIdentifier::generateThreadSafe();
    m_getHandleWithTypeCallbacks.add(callbackIdentifier, WTFMove(callback));

    callOnMainThread([callbackIdentifier, workerThread = Ref { m_scope->thread() }, mainThreadConnection = m_mainThreadConnection, identifier, name = name.isolatedCopy()]() mutable {
        auto mainThreadCallback = [callbackIdentifier, workerThread = WTFMove(workerThread)](auto result) mutable {
            workerThread->runLoop().postTaskForMode([callbackIdentifier, result = crossThreadCopy(result)] (auto& scope) mutable {
                if (auto connection = downcast<WorkerGlobalScope>(scope).fileSystemStorageConnection())
                    connection->didGetHandleWithType(callbackIdentifier, WTFMove(result));
            }, WorkerRunLoop::defaultMode());
        };

        mainThreadConnection->getHandle(identifier, name, WTFMove(mainThreadCallback));
    });
}

void WorkerFileSystemStorageConnection::didGetHandleWithType(CallbackIdentifier callbackIdentifier, ExceptionOr<std::pair<FileSystemHandleIdentifier, bool>>&& result)
{
    if (auto callback = m_getHandleWithTypeCallbacks.take(callbackIdentifier))
        callback(WTFMove(result));
}

void WorkerFileSystemStorageConnection::move(FileSystemHandleIdentifier identifier, FileSystemHandleIdentifier destinationIdentifier, const String& newName, VoidCallback&& callback)
{
    if (!m_scope)
        return callback(Exception { InvalidStateError });

    auto callbackIdentifier = CallbackIdentifier::generateThreadSafe();
    m_voidCallbacks.add(callbackIdentifier, WTFMove(callback));

    callOnMainThread([callbackIdentifier, workerThread = Ref { m_scope->thread() }, mainThreadConnection = m_mainThreadConnection, identifier, destinationIdentifier, name = crossThreadCopy(newName)]() mutable {
        auto mainThreadCallback = [callbackIdentifier, workerThread = WTFMove(workerThread)](auto result) mutable {
            workerThread->runLoop().postTaskForMode([callbackIdentifier, result = crossThreadCopy(result)] (auto& scope) mutable {
                if (auto connection = downcast<WorkerGlobalScope>(scope).fileSystemStorageConnection())
                    connection->completeVoidCallback(callbackIdentifier, WTFMove(result));
            }, WorkerRunLoop::defaultMode());
        };

        mainThreadConnection->move(identifier, destinationIdentifier, name, WTFMove(mainThreadCallback));
    });
}

} // namespace WebCore
