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

#include "ApplicationCacheGroup.h"
#include "ApplicationCacheResource.h"
#include "ApplicationCacheStorage.h"
#include "ResourceRequest.h"
#include <algorithm>
#include <stdio.h>
#include <wtf/text/CString.h>

namespace WebCore {
 
static inline bool fallbackURLLongerThan(const std::pair<URL, URL>& lhs, const std::pair<URL, URL>& rhs)
{
    return lhs.first.string().length() > rhs.first.string().length();
}

ApplicationCache::ApplicationCache()
{
}

ApplicationCache::~ApplicationCache()
{
    if (m_group)
        m_group->cacheDestroyed(*this);
}
    
void ApplicationCache::setGroup(ApplicationCacheGroup* group)
{
    ASSERT(!m_group || group == m_group);
    m_group = makeWeakPtr(group);
}

bool ApplicationCache::isComplete()
{
    return m_group && m_group->cacheIsComplete(*this);
}

ApplicationCacheResource* ApplicationCache::manifestResource() const
{
    return m_manifest.get();
}

ApplicationCacheGroup* ApplicationCache::group() const
{
    return m_group.get();
}

void ApplicationCache::setManifestResource(Ref<ApplicationCacheResource>&& manifest)
{
    ASSERT(!m_manifest);
    ASSERT(manifest->type() & ApplicationCacheResource::Manifest);

    m_manifest = makeWeakPtr(manifest.get());

    addResource(WTFMove(manifest));
}
    
void ApplicationCache::addResource(Ref<ApplicationCacheResource>&& resource)
{
    auto& url = resource->url();

    ASSERT(!url.hasFragmentIdentifier());
    ASSERT(!m_resources.contains(url.string()));

    if (m_storageID) {
        ASSERT(!resource->storageID());
        ASSERT(resource->type() & ApplicationCacheResource::Master);

        // Add the resource to the storage.
        m_group->storage().store(resource.ptr(), this);
    }

    m_estimatedSizeInStorage += resource->estimatedSizeInStorage();

    m_resources.set(url.string(), WTFMove(resource));
}

ApplicationCacheResource* ApplicationCache::resourceForURL(const String& url)
{
    ASSERT(!URL({ }, url).hasFragmentIdentifier());
    return m_resources.get(url);
}    

bool ApplicationCache::requestIsHTTPOrHTTPSGet(const ResourceRequest& request)
{
    return request.url().protocolIsInHTTPFamily() && equalLettersIgnoringASCIICase(request.httpMethod(), "get");
}

ApplicationCacheResource* ApplicationCache::resourceForRequest(const ResourceRequest& request)
{
    // We only care about HTTP/HTTPS GET requests.
    if (!requestIsHTTPOrHTTPSGet(request))
        return nullptr;

    URL url(request.url());
    url.removeFragmentIdentifier();
    return resourceForURL(url.string());
}

void ApplicationCache::setOnlineAllowlist(const Vector<URL>& onlineAllowlist)
{
    ASSERT(m_onlineAllowlist.isEmpty());
    m_onlineAllowlist = onlineAllowlist;
}

bool ApplicationCache::isURLInOnlineAllowlist(const URL& url)
{
    for (auto& allowlistURL : m_onlineAllowlist) {
        if (protocolHostAndPortAreEqual(url, allowlistURL) && url.string().startsWith(allowlistURL.string()))
            return true;
    }
    return false;
}

void ApplicationCache::setFallbackURLs(const FallbackURLVector& fallbackURLs)
{
    ASSERT(m_fallbackURLs.isEmpty());
    m_fallbackURLs = fallbackURLs;
    // FIXME: What's the right behavior if we have 2 or more identical namespace URLs?
    std::stable_sort(m_fallbackURLs.begin(), m_fallbackURLs.end(), fallbackURLLongerThan);
}

bool ApplicationCache::urlMatchesFallbackNamespace(const URL& url, URL* fallbackURL)
{
    for (auto& fallback : m_fallbackURLs) {
        if (protocolHostAndPortAreEqual(url, fallback.first) && url.string().startsWith(fallback.first.string())) {
            if (fallbackURL)
                *fallbackURL = fallback.second;
            return true;
        }
    }
    return false;
}

void ApplicationCache::clearStorageID()
{
    m_storageID = 0;
    
    for (const auto& resource : m_resources.values())
        resource->clearStorageID();
}
    
#ifndef NDEBUG
void ApplicationCache::dump()
{
    for (const auto& urlAndResource : m_resources) {
        printf("%s ", urlAndResource.key.utf8().data());
        ApplicationCacheResource::dumpType(urlAndResource.value->type());
    }
}
#endif

}
