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

#include "BitmapImage.h"
#include "Blob.h"
#include "Clipboard.h"
#include "ClipboardItem.h"
#include "Document.h"
#include "ExceptionCode.h"
#include "FileReaderLoader.h"
#include "Frame.h"
#include "GraphicsContext.h"
#include "ImageBuffer.h"
#include "JSBlob.h"
#include "JSDOMPromise.h"
#include "JSDOMPromiseDeferred.h"
#include "PasteboardCustomData.h"
#include "SharedBuffer.h"
#include "markup.h"
#include <wtf/Function.h>

namespace WebCore {

static RefPtr<Document> documentFromClipboard(const Clipboard* clipboard)
{
    if (!clipboard)
        return nullptr;

    auto* frame = clipboard->frame();
    if (!frame)
        return nullptr;

    return frame->document();
}

static FileReaderLoader::ReadType readTypeForMIMEType(const String& type)
{
    if (type == "text/uri-list"_s || type == "text/plain"_s || type == "text/html"_s)
        return FileReaderLoader::ReadAsText;
    return FileReaderLoader::ReadAsArrayBuffer;
}

ClipboardItemBindingsDataSource::ClipboardItemBindingsDataSource(ClipboardItem& item, Vector<KeyValuePair<String, RefPtr<DOMPromise>>>&& itemPromises)
    : ClipboardItemDataSource(item)
    , m_itemPromises(WTFMove(itemPromises))
{
}

ClipboardItemBindingsDataSource::~ClipboardItemBindingsDataSource() = default;

Vector<String> ClipboardItemBindingsDataSource::types() const
{
    return m_itemPromises.map([&] (auto& typeAndItem) {
        return typeAndItem.key;
    });
}

void ClipboardItemBindingsDataSource::getType(const String& type, Ref<DeferredPromise>&& promise)
{
    auto matchIndex = m_itemPromises.findIf([&] (auto& item) {
        return type == item.key;
    });

    if (matchIndex == notFound) {
        promise->reject(NotFoundError);
        return;
    }

    auto itemPromise = m_itemPromises[matchIndex].value;
    itemPromise->whenSettled([itemPromise, promise = WTFMove(promise), type] () mutable {
        if (itemPromise->status() != DOMPromise::Status::Fulfilled) {
            promise->reject(AbortError);
            return;
        }

        auto result = itemPromise->result();
        if (!result) {
            promise->reject(TypeError);
            return;
        }

        String string;
        result.getString(itemPromise->globalObject(), string);
        if (!string.isNull()) {
            promise->resolve<IDLInterface<Blob>>(ClipboardItem::blobFromString(promise->scriptExecutionContext(), string, type));
            return;
        }

        if (!result.isObject()) {
            promise->reject(TypeError);
            return;
        }

        if (auto blob = JSBlob::toWrapped(result.getObject()->vm(), result.getObject()))
            promise->resolve<IDLInterface<Blob>>(*blob);
        else
            promise->reject(TypeError);
    });
}

void ClipboardItemBindingsDataSource::collectDataForWriting(Clipboard& destination, CompletionHandler<void(std::optional<PasteboardCustomData>)>&& completion)
{
    m_itemTypeLoaders.clear();
    ASSERT(!m_completionHandler);
    m_completionHandler = WTFMove(completion);
    m_writingDestination = destination;
    m_numberOfPendingClipboardTypes = m_itemPromises.size();
    m_itemTypeLoaders = m_itemPromises.map([&] (auto& typeAndItem) {
        auto type = typeAndItem.key;
        auto itemTypeLoader = ClipboardItemTypeLoader::create(type, [this, protectedItem = Ref { m_item }] {
            ASSERT(m_numberOfPendingClipboardTypes);
            if (!--m_numberOfPendingClipboardTypes)
                invokeCompletionHandler();
        });

        auto promise = typeAndItem.value;
        /* hack: gcc 8.4 will segfault if the WeakPtr is instantiated within the lambda captures */
        auto wl = WeakPtr { itemTypeLoader };
        promise->whenSettled([this, protectedItem = Ref { m_item }, destination = m_writingDestination, promise, type, weakItemTypeLoader = WTFMove(wl)] () mutable {
            if (!weakItemTypeLoader)
                return;

            Ref itemTypeLoader { *weakItemTypeLoader };
#if !COMPILER(MSVC)
            ASSERT_UNUSED(this, notFound != m_itemTypeLoaders.findIf([&] (auto& loader) { return loader.ptr() == itemTypeLoader.ptr(); }));
#endif

            auto result = promise->result();
            if (!result) {
                itemTypeLoader->didFailToResolve();
                return;
            }

            RefPtr clipboard = destination.get();
            if (!clipboard) {
                itemTypeLoader->didFailToResolve();
                return;
            }

            if (!clipboard->scriptExecutionContext()) {
                itemTypeLoader->didFailToResolve();
                return;
            }

            String text;
            result.getString(promise->globalObject(), text);
            if (!text.isNull()) {
                itemTypeLoader->didResolveToString(text);
                return;
            }

            if (!result.isObject()) {
                itemTypeLoader->didFailToResolve();
                return;
            }

            if (RefPtr blob = JSBlob::toWrapped(result.getObject()->vm(), result.getObject()))
                itemTypeLoader->didResolveToBlob(*clipboard->scriptExecutionContext(), blob.releaseNonNull());
            else
                itemTypeLoader->didFailToResolve();
        });

        return itemTypeLoader;
    });

    if (!m_numberOfPendingClipboardTypes)
        invokeCompletionHandler();
}

void ClipboardItemBindingsDataSource::invokeCompletionHandler()
{
    if (!m_completionHandler) {
        ASSERT_NOT_REACHED();
        return;
    }

    auto completionHandler = std::exchange(m_completionHandler, { });
    auto itemTypeLoaders = std::exchange(m_itemTypeLoaders, { });
    RefPtr clipboard = m_writingDestination.get();
    m_writingDestination = nullptr;

    auto document = documentFromClipboard(clipboard.get());
    if (!document) {
        completionHandler(std::nullopt);
        return;
    }

    PasteboardCustomData customData;
    for (auto& itemTypeLoader : itemTypeLoaders) {
        auto type = itemTypeLoader->type();
        auto& data = itemTypeLoader->data();
        if (std::holds_alternative<String>(data) && !!std::get<String>(data))
            customData.writeString(type, std::get<String>(data));
        else if (std::holds_alternative<Ref<SharedBuffer>>(data))
            customData.writeData(type, std::get<Ref<SharedBuffer>>(data).copyRef());
        else {
            completionHandler(std::nullopt);
            return;
        }
    }

    customData.setOrigin(document->originIdentifierForPasteboard());
    completionHandler(WTFMove(customData));
}

ClipboardItemBindingsDataSource::ClipboardItemTypeLoader::ClipboardItemTypeLoader(const String& type, CompletionHandler<void()>&& completionHandler)
    : m_type(type)
    , m_completionHandler(WTFMove(completionHandler))
{
}

ClipboardItemBindingsDataSource::ClipboardItemTypeLoader::~ClipboardItemTypeLoader()
{
    if (m_blobLoader)
        m_blobLoader->cancel();

    invokeCompletionHandler();
}

void ClipboardItemBindingsDataSource::ClipboardItemTypeLoader::didFinishLoading()
{
    ASSERT(m_blobLoader);
    auto stringResult = readTypeForMIMEType(m_type) == FileReaderLoader::ReadAsText ? m_blobLoader->stringResult() : nullString();
    if (!stringResult.isNull())
        m_data = { stringResult };
    else if (auto arrayBuffer = m_blobLoader->arrayBufferResult())
        m_data = { SharedBuffer::create(static_cast<const char*>(arrayBuffer->data()), arrayBuffer->byteLength()) };
    m_blobLoader = nullptr;
    invokeCompletionHandler();
}

void ClipboardItemBindingsDataSource::ClipboardItemTypeLoader::didFail(ExceptionCode)
{
    ASSERT(m_blobLoader);
    m_blobLoader = nullptr;
    invokeCompletionHandler();
}

void ClipboardItemBindingsDataSource::ClipboardItemTypeLoader::sanitizeDataIfNeeded()
{
    if (m_type == "text/html"_s) {
        String markupToSanitize;
        if (std::holds_alternative<Ref<SharedBuffer>>(m_data)) {
            auto& buffer = std::get<Ref<SharedBuffer>>(m_data);
            markupToSanitize = String::fromUTF8(buffer->data(), buffer->size());
        } else if (std::holds_alternative<String>(m_data))
            markupToSanitize = std::get<String>(m_data);

        if (markupToSanitize.isEmpty())
            return;

        m_data = { sanitizeMarkup(markupToSanitize) };
    }

    if (m_type == "image/png"_s) {
        RefPtr<SharedBuffer> bufferToSanitize;
        if (std::holds_alternative<Ref<SharedBuffer>>(m_data))
            bufferToSanitize = std::get<Ref<SharedBuffer>>(m_data).ptr();
        else if (std::holds_alternative<String>(m_data))
            bufferToSanitize = utf8Buffer(std::get<String>(m_data));

        if (!bufferToSanitize || bufferToSanitize->isEmpty())
            return;

        auto bitmapImage = BitmapImage::create();
        bitmapImage->setData(WTFMove(bufferToSanitize), true);
        auto imageBuffer = ImageBuffer::create(bitmapImage->size(), RenderingPurpose::Unspecified, 1, DestinationColorSpace::SRGB(), PixelFormat::BGRA8);
        if (!imageBuffer) {
            m_data = { nullString() };
            return;
        }

        imageBuffer->context().drawImage(bitmapImage.get(), FloatPoint::zero());
        m_data = { SharedBuffer::create(imageBuffer->toData("image/png"_s)) };
    }
}

void ClipboardItemBindingsDataSource::ClipboardItemTypeLoader::invokeCompletionHandler()
{
    if (auto completion = WTFMove(m_completionHandler)) {
        sanitizeDataIfNeeded();
        completion();
    }
}

void ClipboardItemBindingsDataSource::ClipboardItemTypeLoader::didResolveToBlob(ScriptExecutionContext& context, Ref<Blob>&& blob)
{
    ASSERT(!m_blobLoader);
    m_blobLoader = makeUnique<FileReaderLoader>(readTypeForMIMEType(m_type), this);
    m_blobLoader->start(&context, WTFMove(blob));
}

void ClipboardItemBindingsDataSource::ClipboardItemTypeLoader::didFailToResolve()
{
    ASSERT(!m_blobLoader);
    invokeCompletionHandler();
}

void ClipboardItemBindingsDataSource::ClipboardItemTypeLoader::didResolveToString(const String& text)
{
    ASSERT(!m_blobLoader);
    m_data = { text };
    invokeCompletionHandler();
}

} // namespace WebCore
