/*
 * 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") || equalLettersIgnoringASCIICase(mimeType, "text/plain"))
        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<bool> 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<bool> 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)
