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

#include "CacheQueryOptions.h"
#include "ClientOrigin.h"
#include "JSDOMCache.h"
#include "JSFetchResponse.h"
#include "ScriptExecutionContext.h"
#include "SuspendableTaskQueue.h"

namespace WebCore {
using namespace WebCore::DOMCacheEngine;

DOMCacheStorage::DOMCacheStorage(ScriptExecutionContext& context, Ref<CacheStorageConnection>&& connection)
    : ActiveDOMObject(&context)
    , m_connection(WTFMove(connection))
    , m_taskQueue(SuspendableTaskQueue::create(&context))
{
    suspendIfNeeded();
}

DOMCacheStorage::~DOMCacheStorage() = default;

Optional<ClientOrigin> DOMCacheStorage::origin() const
{
    auto* origin = scriptExecutionContext() ? scriptExecutionContext()->securityOrigin() : nullptr;
    if (!origin)
        return WTF::nullopt;

    return ClientOrigin { scriptExecutionContext()->topOrigin().data(), origin->data() };
}

static void doSequentialMatch(size_t index, Vector<Ref<DOMCache>>&& caches, DOMCache::RequestInfo&& info, CacheQueryOptions&& options, DOMCache::MatchCallback&& completionHandler)
{
    if (index >= caches.size()) {
        completionHandler(nullptr);
        return;
    }

    auto& cache = caches[index].get();
    cache.doMatch(WTFMove(info), WTFMove(options), [caches = WTFMove(caches), info, options, completionHandler = WTFMove(completionHandler), index](auto&& result) mutable {
        if (result.hasException()) {
            completionHandler(result.releaseException());
            return;
        }
        if (result.returnValue()) {
            completionHandler(result.releaseReturnValue());
            return;
        }
        doSequentialMatch(++index, WTFMove(caches), WTFMove(info), WTFMove(options), WTFMove(completionHandler));
    });
}

static inline void startSequentialMatch(Vector<Ref<DOMCache>>&& caches, DOMCache::RequestInfo&& info, CacheQueryOptions&& options, DOMCache::MatchCallback&& completionHandler)
{
    doSequentialMatch(0, WTFMove(caches), WTFMove(info), WTFMove(options), WTFMove(completionHandler));
}

static inline Ref<DOMCache> copyCache(const Ref<DOMCache>& cache)
{
    return cache.copyRef();
}

void DOMCacheStorage::doSequentialMatch(DOMCache::RequestInfo&& info, CacheQueryOptions&& options, Ref<DeferredPromise>&& promise)
{
    startSequentialMatch(WTF::map(m_caches, copyCache), WTFMove(info), WTFMove(options), [this, pendingActivity = makePendingActivity(*this), promise = WTFMove(promise)](auto&& result) mutable {
        m_taskQueue->enqueueTask([promise = WTFMove(promise), result = WTFMove(result)]() mutable {
            if (result.hasException()) {
                promise->reject(result.releaseException());
                return;
            }
            if (!result.returnValue()) {
                promise->resolve();
                return;
            }
            promise->resolve<IDLInterface<FetchResponse>>(*result.returnValue());
        });
    });
}

void DOMCacheStorage::match(DOMCache::RequestInfo&& info, CacheQueryOptions&& options, Ref<DeferredPromise>&& promise)
{
    retrieveCaches([this, info = WTFMove(info), options = WTFMove(options), promise = WTFMove(promise)](Optional<Exception>&& exception) mutable {
        if (exception) {
            m_taskQueue->enqueueTask([promise = WTFMove(promise), exception = WTFMove(exception.value())]() mutable {
                promise->reject(WTFMove(exception));
            });
            return;
        }

        if (!options.cacheName.isNull()) {
            auto position = m_caches.findMatching([&](auto& item) { return item->name() == options.cacheName; });
            if (position != notFound) {
                m_caches[position]->match(WTFMove(info), WTFMove(options), WTFMove(promise));
                return;
            }
            m_taskQueue->enqueueTask([promise = WTFMove(promise)]() mutable {
                promise->resolve();
            });
            return;
        }

        this->doSequentialMatch(WTFMove(info), WTFMove(options), WTFMove(promise));
    });
}

void DOMCacheStorage::has(const String& name, DOMPromiseDeferred<IDLBoolean>&& promise)
{
    retrieveCaches([this, name, promise = WTFMove(promise)](Optional<Exception>&& exception) mutable {
        m_taskQueue->enqueueTask([this, name, promise = WTFMove(promise), exception = WTFMove(exception)]() mutable {
            if (exception) {
                promise.reject(WTFMove(exception.value()));
                return;
            }
            promise.resolve(m_caches.findMatching([&](auto& item) { return item->name() == name; }) != notFound);
        });
    });
}

Ref<DOMCache> DOMCacheStorage::findCacheOrCreate(CacheInfo&& info)
{
   auto position = m_caches.findMatching([&] (const auto& cache) { return info.identifier == cache->identifier(); });
   if (position != notFound)
       return m_caches[position].copyRef();
   return DOMCache::create(*scriptExecutionContext(), WTFMove(info.name), info.identifier, m_connection.copyRef());
}

void DOMCacheStorage::retrieveCaches(WTF::Function<void(Optional<Exception>&&)>&& callback)
{
    auto origin = this->origin();
    if (!origin)
        return;

    m_connection->retrieveCaches(*origin, m_updateCounter, [this, callback = WTFMove(callback), pendingActivity = makePendingActivity(*this)](CacheInfosOrError&& result) mutable {
        if (!m_isStopped) {
            if (!result.has_value()) {
                callback(DOMCacheEngine::convertToExceptionAndLog(scriptExecutionContext(), result.error()));
                return;
            }

            auto& cachesInfo = result.value();

            if (m_updateCounter != cachesInfo.updateCounter) {
                m_updateCounter = cachesInfo.updateCounter;

                m_caches = WTF::map(WTFMove(cachesInfo.infos), [this] (CacheInfo&& info) {
                    return findCacheOrCreate(WTFMove(info));
                });
            }
            callback(WTF::nullopt);
        }
    });
}

static void logConsolePersistencyError(ScriptExecutionContext* context, const String& cacheName)
{
    if (!context)
        return;

    context->addConsoleMessage(MessageSource::JS, MessageLevel::Error, makeString("There was an error making ", cacheName, " persistent on the filesystem"));
}

void DOMCacheStorage::open(const String& name, DOMPromiseDeferred<IDLInterface<DOMCache>>&& promise)
{
    retrieveCaches([this, name, promise = WTFMove(promise)](Optional<Exception>&& exception) mutable {
        if (exception) {
            m_taskQueue->enqueueTask([promise = WTFMove(promise), exception = WTFMove(exception.value())]() mutable {
                promise.reject(WTFMove(exception));
            });
            return;
        }
        doOpen(name, WTFMove(promise));
    });
}

void DOMCacheStorage::doOpen(const String& name, DOMPromiseDeferred<IDLInterface<DOMCache>>&& promise)
{
    auto position = m_caches.findMatching([&](auto& item) { return item->name() == name; });
    if (position != notFound) {
        m_taskQueue->enqueueTask([this, promise = WTFMove(promise), cache = m_caches[position].copyRef()]() mutable {
            promise.resolve(DOMCache::create(*scriptExecutionContext(), String { cache->name() }, cache->identifier(), m_connection.copyRef()));
        });
        return;
    }

    m_connection->open(*origin(), name, [this, name, promise = WTFMove(promise), pendingActivity = makePendingActivity(*this)](const CacheIdentifierOrError& result) mutable {
        if (!result.has_value()) {
            m_taskQueue->enqueueTask([this, promise = WTFMove(promise), error = result.error()]() mutable {
                promise.reject(DOMCacheEngine::convertToExceptionAndLog(scriptExecutionContext(), error));
            });
        } else {
            if (result.value().hadStorageError)
                logConsolePersistencyError(scriptExecutionContext(), name);

            m_taskQueue->enqueueTask([this, name, promise = WTFMove(promise), identifier = result.value().identifier]() mutable {
                auto cache = DOMCache::create(*scriptExecutionContext(), String { name }, identifier, m_connection.copyRef());
                promise.resolve(cache);
                m_caches.append(WTFMove(cache));
            });
        }
    });
}

void DOMCacheStorage::remove(const String& name, DOMPromiseDeferred<IDLBoolean>&& promise)
{
    retrieveCaches([this, name, promise = WTFMove(promise)](Optional<Exception>&& exception) mutable {
        if (exception) {
            m_taskQueue->enqueueTask([promise = WTFMove(promise), exception = WTFMove(exception.value())]() mutable {
                promise.reject(WTFMove(exception));
            });
            return;
        }
        doRemove(name, WTFMove(promise));
    });
}

void DOMCacheStorage::doRemove(const String& name, DOMPromiseDeferred<IDLBoolean>&& promise)
{
    auto position = m_caches.findMatching([&](auto& item) { return item->name() == name; });
    if (position == notFound) {
        m_taskQueue->enqueueTask([promise = WTFMove(promise)]() mutable {
            promise.resolve(false);
        });
        return;
    }

    m_connection->remove(m_caches[position]->identifier(), [this, name, promise = WTFMove(promise), pendingActivity = makePendingActivity(*this)](const CacheIdentifierOrError& result) mutable {
        m_taskQueue->enqueueTask([this, name, promise = WTFMove(promise), result]() mutable {
            if (!result.has_value())
                promise.reject(DOMCacheEngine::convertToExceptionAndLog(scriptExecutionContext(), result.error()));
            else {
                if (result.value().hadStorageError)
                    logConsolePersistencyError(scriptExecutionContext(), name);
                promise.resolve(!!result.value().identifier);
            }
        });
    });
}

void DOMCacheStorage::keys(KeysPromise&& promise)
{
    retrieveCaches([this, promise = WTFMove(promise)](Optional<Exception>&& exception) mutable {
        m_taskQueue->enqueueTask([this, promise = WTFMove(promise), exception = WTFMove(exception)]() mutable {
            if (exception) {
                promise.reject(WTFMove(exception.value()));
                return;
            }

            promise.resolve(WTF::map(m_caches, [] (const auto& cache) {
                return cache->name();
            }));
        });
    });
}

void DOMCacheStorage::stop()
{
    m_isStopped = true;
}

const char* DOMCacheStorage::activeDOMObjectName() const
{
    return "CacheStorage";
}

bool DOMCacheStorage::canSuspendForDocumentSuspension() const
{
    return true;
}

bool DOMCacheStorage::hasPendingActivity() const
{
    return m_taskQueue->hasPendingTasks() || ActiveDOMObject::hasPendingActivity();
}

} // namespace WebCore
