/*
 * 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.
 */

#pragma once

#include "CacheStorageConnection.h"
#include "DOMCache.h"
#include "FetchRequest.h"
#include <wtf/Forward.h>

namespace WebCore {

class SuspendableTaskQueue;

class DOMCacheStorage : public RefCounted<DOMCacheStorage>, public ActiveDOMObject {
public:
    static Ref<DOMCacheStorage> create(ScriptExecutionContext& context, Ref<CacheStorageConnection>&& connection) { return adoptRef(*new DOMCacheStorage(context, WTFMove(connection))); }
    ~DOMCacheStorage();

    using KeysPromise = DOMPromiseDeferred<IDLSequence<IDLDOMString>>;

    void match(DOMCache::RequestInfo&&, CacheQueryOptions&&, Ref<DeferredPromise>&&);
    void has(const String&, DOMPromiseDeferred<IDLBoolean>&&);
    void open(const String&, DOMPromiseDeferred<IDLInterface<DOMCache>>&&);
    void remove(const String&, DOMPromiseDeferred<IDLBoolean>&&);
    void keys(KeysPromise&&);

    // ActiveDOMObject
    bool hasPendingActivity() const final;

private:
    DOMCacheStorage(ScriptExecutionContext&, Ref<CacheStorageConnection>&&);

    // ActiveDOMObject
    void stop() final;
    const char* activeDOMObjectName() const final;

    void doOpen(const String& name, DOMPromiseDeferred<IDLInterface<DOMCache>>&&);
    void doRemove(const String&, DOMPromiseDeferred<IDLBoolean>&&);
    void doSequentialMatch(DOMCache::RequestInfo&&, CacheQueryOptions&&, Ref<DeferredPromise>&&);
    void retrieveCaches(WTF::Function<void(Optional<Exception>&&)>&&);
    Ref<DOMCache> findCacheOrCreate(DOMCacheEngine::CacheInfo&&);
    Optional<ClientOrigin> origin() const;

    Vector<Ref<DOMCache>> m_caches;
    uint64_t m_updateCounter { 0 };
    Ref<CacheStorageConnection> m_connection;
    UniqueRef<SuspendableTaskQueue> m_taskQueue;
    bool m_isStopped { false };
};

} // namespace WebCore
