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

#include "BlobLoader.h"
#include "FormData.h"
#include <wtf/WorkQueue.h>

namespace WebCore {

FormDataConsumer::FormDataConsumer(const FormData& formData, ScriptExecutionContext& context, Callback&& callback)
    : m_formData(formData.copy())
    , m_context(&context)
    , m_callback(WTFMove(callback))
    , m_fileQueue(WorkQueue::create("FormDataConsumer file queue"))
{
    read();
}

FormDataConsumer::~FormDataConsumer()
{
}

void FormDataConsumer::read()
{
    ASSERT(m_callback);
    ASSERT(m_context);
    ASSERT(!m_blobLoader);

    if (m_currentElementIndex >= m_formData->elements().size()) {
        m_callback(Span<const uint8_t> { });
        return;
    }

    switchOn(m_formData->elements()[m_currentElementIndex++].data, [this](const Vector<uint8_t>& content) {
        consumeData(content);
    }, [this](const FormDataElement::EncodedFileData& fileData) {
        consumeFile(fileData.filename);
    }, [this](const FormDataElement::EncodedBlobData& blobData) {
        consumeBlob(blobData.url);
    });
}

void FormDataConsumer::consumeData(const Vector<uint8_t>& content)
{
    consume(content.span());
}

void FormDataConsumer::consumeFile(const String& filename)
{
    m_fileQueue->dispatch([weakThis = WeakPtr { *this }, identifier = m_context->identifier(), path = filename.isolatedCopy()]() mutable {
        ScriptExecutionContext::postTaskTo(identifier, [weakThis = WTFMove(weakThis), content = FileSystem::readEntireFile(path)](auto&) {
            if (!weakThis)
                return;

            if (!content) {
                if (weakThis->m_callback)
                    weakThis->m_callback(Exception { InvalidStateError, "Unable to read form data file"_s });
                return;
            }

            weakThis->consume(*content);
        });
    });
}

void FormDataConsumer::consumeBlob(const URL& blobURL)
{
    m_blobLoader = makeUnique<BlobLoader>([weakThis = WeakPtr { *this }](BlobLoader&) mutable {
        if (!weakThis)
            return;

        auto loader = std::exchange(weakThis->m_blobLoader, { });
        if (auto optionalErrorCode = loader->errorCode()) {
            if (weakThis->m_callback)
                weakThis->m_callback(Exception { InvalidStateError, "Failed to read form data blob"_s });
            return;
        }

        if (auto data = loader->arrayBufferResult())
            weakThis->consume(Span<const uint8_t> { static_cast<const uint8_t*>(data->data()), data->byteLength() });
    });

    m_blobLoader->start(blobURL, m_context.get(), FileReaderLoader::ReadAsArrayBuffer);

    if (!m_blobLoader->isLoading()) {
        m_callback(Exception { InvalidStateError, "Unable to read form data blob"_s });
        m_blobLoader = nullptr;
    }
}

void FormDataConsumer::consume(Span<const uint8_t> content)
{
    if (!m_callback)
        return;

    m_callback(WTFMove(content));
    if (!m_callback)
        return;

    read();
}

void FormDataConsumer::cancel()
{
    m_callback = nullptr;
    if (m_blobLoader) {
        m_blobLoader->cancel();
        m_blobLoader = nullptr;
    }
    m_context = nullptr;
}

} // namespace WebCore
