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

#if ENABLE(PREVIEW_CONVERTER)

#include "PreviewConverterClient.h"
#include "PreviewConverterProvider.h"
#include <wtf/RunLoop.h>
#include <wtf/SetForScope.h>

namespace WebCore {

PreviewConverter::~PreviewConverter() = default;

bool PreviewConverter::supportsMIMEType(const String& mimeType)
{
    if (mimeType.isNull())
        return false;

    if (equalLettersIgnoringASCIICase(mimeType, "text/html"_s) || equalLettersIgnoringASCIICase(mimeType, "text/plain"_s))
        return false;

    static NeverDestroyed<HashSet<String, ASCIICaseInsensitiveHash>> supportedMIMETypes = platformSupportedMIMETypes();
    return supportedMIMETypes->contains(mimeType);
}

ResourceResponse PreviewConverter::previewResponse() const
{
    auto response = platformPreviewResponse();
    ASSERT(response.mimeType().length());
    response.setIsQuickLook(true);
    return response;
}

const ResourceError& PreviewConverter::previewError() const
{
    return m_previewError;
}

const FragmentedSharedBuffer& PreviewConverter::previewData() const
{
    return *m_previewData.get();
}

void PreviewConverter::updateMainResource()
{
    if (m_isInClientCallback)
        return;

    if (m_state != State::Updating)
        return;

    auto provider = m_provider.get();
    if (!provider) {
        didFailUpdating();
        return;
    }

    provider->provideMainResourceForPreviewConverter(*this, [this, protectedThis = Ref { *this }](auto&& buffer) {
        appendFromBuffer(WTFMove(buffer));
    });
}

void PreviewConverter::appendFromBuffer(const FragmentedSharedBuffer& buffer)
{
    while (buffer.size() > m_lengthAppended) {
        auto newData = buffer.getSomeData(m_lengthAppended);
        platformAppend(newData);
        m_lengthAppended += newData.size();
    }
}

void PreviewConverter::finishUpdating()
{
    if (m_isInClientCallback)
        return;

    if (m_state != State::Updating)
        return;

    platformFinishedAppending();

    iterateClients([&](auto& client) {
        client.previewConverterDidFinishUpdating(*this);
    });
}

void PreviewConverter::failedUpdating()
{
    if (m_isInClientCallback)
        return;

    if (m_state != State::Updating)
        return;

    m_state = State::FailedUpdating;
    platformFailedAppending();
}

bool PreviewConverter::hasClient(PreviewConverterClient& client) const
{
    return m_clients.contains(&client);
}

void PreviewConverter::addClient(PreviewConverterClient& client)
{
    ASSERT(!hasClient(client));
    m_clients.append(client);
    didAddClient(client);
}

void PreviewConverter::removeClient(PreviewConverterClient& client)
{
    m_clients.removeFirst(&client);
    ASSERT(!hasClient(client));
}

static String& sharedPasswordForTesting()
{
    static NeverDestroyed<String> passwordForTesting;
    return passwordForTesting.get();
}

const String& PreviewConverter::passwordForTesting()
{
    return sharedPasswordForTesting();
}

void PreviewConverter::setPasswordForTesting(const String& password)
{
    sharedPasswordForTesting() = password;
}

template<typename T>
void PreviewConverter::iterateClients(T&& callback)
{
    SetForScope isInClientCallback { m_isInClientCallback, true };
    auto clientsCopy { m_clients };
    auto protectedThis { Ref { *this } };

    for (auto& client : clientsCopy) {
        if (client && hasClient(*client))
            callback(*client);
    }
}

void PreviewConverter::didAddClient(PreviewConverterClient& client)
{
    RunLoop::current().dispatch([this, protectedThis = Ref { *this }, weakClient = WeakPtr { client }]() {
        if (auto client = weakClient.get())
            replayToClient(*client);
    });
}

void PreviewConverter::didFailConvertingWithError(const ResourceError& error)
{
    m_previewError = error;
    m_state = State::FailedConverting;

    iterateClients([&](auto& client) {
        client.previewConverterDidFailConverting(*this);
    });
}

void PreviewConverter::didFailUpdating()
{
    failedUpdating();

    iterateClients([&](auto& client) {
        client.previewConverterDidFailUpdating(*this);
    });
}

void PreviewConverter::replayToClient(PreviewConverterClient& client)
{
    if (!hasClient(client))
        return;

    SetForScope isInClientCallback { m_isInClientCallback, true };
    auto protectedThis { Ref { *this } };

    client.previewConverterDidStartUpdating(*this);

    if (m_state == State::Updating || !hasClient(client))
        return;

    if (m_state == State::FailedUpdating) {
        client.previewConverterDidFailUpdating(*this);
        return;
    }

    ASSERT(m_state >= State::Converting);
    client.previewConverterDidStartConverting(*this);

    if (!m_previewData.isEmpty() && hasClient(client))
        client.previewConverterDidReceiveData(*this, *m_previewData.get());

    if (m_state == State::Converting || !hasClient(client))
        return;

    if (m_state == State::FailedConverting) {
        ASSERT(!m_previewError.isNull());
        client.previewConverterDidFailConverting(*this);
        return;
    }

    ASSERT(m_state == State::FinishedConverting);
    ASSERT(!m_previewData.isEmpty());
    ASSERT(m_previewError.isNull());
    client.previewConverterDidFinishConverting(*this);
}

void PreviewConverter::delegateDidReceiveData(const FragmentedSharedBuffer& data)
{
    auto protectedThis { Ref { *this } };

    if (m_state == State::Updating) {
        m_provider = nullptr;
        m_state = State::Converting;

        iterateClients([&](auto& client) {
            client.previewConverterDidStartConverting(*this);
        });
    }

    ASSERT(m_state == State::Converting);
    if (data.isEmpty())
        return;

    m_previewData.append(data);

    iterateClients([&](auto& client) {
        client.previewConverterDidReceiveData(*this, data);
    });
}

void PreviewConverter::delegateDidFinishLoading()
{
    ASSERT(m_state == State::Converting);
    m_state = State::FinishedConverting;

    iterateClients([&](auto& client) {
        client.previewConverterDidFinishConverting(*this);
    });
}

void PreviewConverter::delegateDidFailWithError(const ResourceError& error)
{
    if (!isPlatformPasswordError(error)) {
        didFailConvertingWithError(error);
        return;
    }

    ASSERT(m_state == State::Updating);
    auto provider = m_provider.get();
    if (!provider) {
        didFailConvertingWithError(error);
        return;
    }

    provider->providePasswordForPreviewConverter(*this, [this, protectedThis = Ref { *this }](auto& password) mutable {
        if (m_state != State::Updating)
            return;

        platformUnlockWithPassword(password);
        m_lengthAppended = 0;
        updateMainResource();
        finishUpdating();
    });
}

} // namespace WebCore

#endif // ENABLE(PREVIEW_CONVERTER)
