/*
 * Copyright (C) 2016 Canon Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted, provided that the following conditions
 * are required to be 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.
 * 3.  Neither the name of Canon Inc. nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY CANON 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 CANON INC. AND 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 "FetchBodyOwner.h"

#include "Document.h"
#include "FetchLoader.h"
#include "HTTPParsers.h"
#include "JSBlob.h"
#include "ResourceError.h"
#include "ResourceResponse.h"
#include "WindowEventLoop.h"

namespace WebCore {

FetchBodyOwner::FetchBodyOwner(ScriptExecutionContext& context, Optional<FetchBody>&& body, Ref<FetchHeaders>&& headers)
    : ActiveDOMObject(&context)
    , m_body(WTFMove(body))
    , m_headers(WTFMove(headers))
{
    suspendIfNeeded();
}

FetchBodyOwner::~FetchBodyOwner()
{
    if (m_readableStreamSource)
        m_readableStreamSource->detach();
}

void FetchBodyOwner::stop()
{
    if (m_body)
        m_body->cleanConsumer();

    if (m_blobLoader) {
        bool isUniqueReference = hasOneRef();
        if (m_blobLoader->loader)
            m_blobLoader->loader->stop();
        // After that point, 'this' may be destroyed, since unsetPendingActivity should have been called.
        ASSERT_UNUSED(isUniqueReference, isUniqueReference || !m_blobLoader);
    }
}

bool FetchBodyOwner::isDisturbed() const
{
    if (isBodyNull())
        return false;

    if (m_isDisturbed)
        return true;

#if ENABLE(STREAMS_API)
    if (body().readableStream())
        return body().readableStream()->isDisturbed();
#endif

    return false;
}

bool FetchBodyOwner::isDisturbedOrLocked() const
{
    if (isBodyNull())
        return false;

    if (m_isDisturbed)
        return true;

#if ENABLE(STREAMS_API)
    if (body().readableStream())
        return body().readableStream()->isDisturbed() || body().readableStream()->isLocked();
#endif

    return false;
}

void FetchBodyOwner::arrayBuffer(Ref<DeferredPromise>&& promise)
{
    if (auto exception = loadingException()) {
        promise->reject(*exception);
        return;
    }

    if (isBodyNullOrOpaque()) {
        fulfillPromiseWithArrayBuffer(WTFMove(promise), nullptr, 0);
        return;
    }
    if (isDisturbedOrLocked()) {
        promise->reject(Exception { TypeError, "Body is disturbed or locked"_s });
        return;
    }
    m_isDisturbed = true;
    m_body->arrayBuffer(*this, WTFMove(promise));
}

void FetchBodyOwner::blob(Ref<DeferredPromise>&& promise)
{
    if (auto exception = loadingException()) {
        promise->reject(*exception);
        return;
    }

    if (isBodyNullOrOpaque()) {
        promise->resolveCallbackValueWithNewlyCreated<IDLInterface<Blob>>([this](auto&) {
            return Blob::create(Vector<uint8_t> { }, Blob::normalizedContentType(extractMIMETypeFromMediaType(m_contentType)));
        });
        return;
    }
    if (isDisturbedOrLocked()) {
        promise->reject(Exception { TypeError, "Body is disturbed or locked"_s });
        return;
    }
    m_isDisturbed = true;
    m_body->blob(*this, WTFMove(promise), m_contentType);
}

void FetchBodyOwner::cloneBody(FetchBodyOwner& owner)
{
    m_loadingError = owner.m_loadingError;

    m_contentType = owner.m_contentType;
    if (owner.isBodyNull())
        return;
    m_body = owner.m_body->clone();
}

ExceptionOr<void> FetchBodyOwner::extractBody(FetchBody::Init&& value)
{
    auto result = FetchBody::extract(WTFMove(value), m_contentType);
    if (result.hasException())
        return result.releaseException();
    m_body = result.releaseReturnValue();
    return { };
}

void FetchBodyOwner::updateContentType()
{
    String contentType = m_headers->fastGet(HTTPHeaderName::ContentType);
    if (!contentType.isNull()) {
        m_contentType = WTFMove(contentType);
        return;
    }
    if (!m_contentType.isNull())
        m_headers->fastSet(HTTPHeaderName::ContentType, m_contentType);
}

void FetchBodyOwner::consumeOnceLoadingFinished(FetchBodyConsumer::Type type, Ref<DeferredPromise>&& promise)
{
    if (isDisturbedOrLocked()) {
        promise->reject(Exception { TypeError, "Body is disturbed or locked"_s });
        return;
    }
    m_isDisturbed = true;
    m_body->consumeOnceLoadingFinished(type, WTFMove(promise), m_contentType);
}

void FetchBodyOwner::formData(Ref<DeferredPromise>&& promise)
{
    if (auto exception = loadingException()) {
        promise->reject(*exception);
        return;
    }

    if (isBodyNullOrOpaque()) {
        promise->reject();
        return;
    }
    if (isDisturbedOrLocked()) {
        promise->reject(Exception { TypeError, "Body is disturbed or locked"_s });
        return;
    }
    m_isDisturbed = true;
    m_body->formData(*this, WTFMove(promise));
}

void FetchBodyOwner::json(Ref<DeferredPromise>&& promise)
{
    if (auto exception = loadingException()) {
        promise->reject(*exception);
        return;
    }

    if (isBodyNullOrOpaque()) {
        promise->reject(SyntaxError);
        return;
    }
    if (isDisturbedOrLocked()) {
        promise->reject(Exception { TypeError, "Body is disturbed or locked"_s });
        return;
    }
    m_isDisturbed = true;
    m_body->json(*this, WTFMove(promise));
}

void FetchBodyOwner::text(Ref<DeferredPromise>&& promise)
{
    if (auto exception = loadingException()) {
        promise->reject(*exception);
        return;
    }

    if (isBodyNullOrOpaque()) {
        promise->resolve<IDLDOMString>({ });
        return;
    }
    if (isDisturbedOrLocked()) {
        promise->reject(Exception { TypeError, "Body is disturbed or locked"_s });
        return;
    }
    m_isDisturbed = true;
    m_body->text(*this, WTFMove(promise));
}

void FetchBodyOwner::loadBlob(const Blob& blob, FetchBodyConsumer* consumer)
{
    // Can only be called once for a body instance.
    ASSERT(!m_blobLoader);
    ASSERT(!isBodyNull());

    if (!scriptExecutionContext()) {
        m_body->loadingFailed(Exception { TypeError, "Blob loading failed"_s});
        return;
    }

    m_blobLoader.emplace(*this);
    m_blobLoader->loader = makeUnique<FetchLoader>(*m_blobLoader, consumer);

    m_blobLoader->loader->start(*scriptExecutionContext(), blob);
    if (!m_blobLoader->loader->isStarted()) {
        m_body->loadingFailed(Exception { TypeError, "Blob loading failed"_s});
        m_blobLoader = WTF::nullopt;
        return;
    }
    setPendingActivity(*this);
}

void FetchBodyOwner::finishBlobLoading()
{
    ASSERT(m_blobLoader);

    m_blobLoader = WTF::nullopt;
    unsetPendingActivity(*this);
}

void FetchBodyOwner::blobLoadingSucceeded()
{
    ASSERT(!isBodyNull());
#if ENABLE(STREAMS_API)
    if (m_readableStreamSource) {
        m_readableStreamSource->close();
        m_readableStreamSource = nullptr;
    }
#endif
    m_body->loadingSucceeded();
    finishBlobLoading();
}

void FetchBodyOwner::blobLoadingFailed()
{
    ASSERT(!isBodyNull());
#if ENABLE(STREAMS_API)
    if (m_readableStreamSource) {
        if (!m_readableStreamSource->isCancelling())
            m_readableStreamSource->error(Exception { TypeError, "Blob loading failed"_s});
        m_readableStreamSource = nullptr;
    } else
#endif
        m_body->loadingFailed(Exception { TypeError, "Blob loading failed"_s});
    finishBlobLoading();
}

void FetchBodyOwner::blobChunk(const char* data, size_t size)
{
    ASSERT(data);
#if ENABLE(STREAMS_API)
    ASSERT(m_readableStreamSource);
    if (!m_readableStreamSource->enqueue(ArrayBuffer::tryCreate(data, size)))
        stop();
#else
    UNUSED_PARAM(data);
    UNUSED_PARAM(size);
#endif
}

FetchBodyOwner::BlobLoader::BlobLoader(FetchBodyOwner& owner)
    : owner(owner)
{
}

void FetchBodyOwner::BlobLoader::didReceiveResponse(const ResourceResponse& response)
{
    if (response.httpStatusCode() != 200)
        didFail({ });
}

void FetchBodyOwner::BlobLoader::didFail(const ResourceError&)
{
    // didFail might be called within FetchLoader::start call.
    if (loader->isStarted())
        owner.blobLoadingFailed();
}

RefPtr<ReadableStream> FetchBodyOwner::readableStream(JSC::JSGlobalObject& state)
{
    if (isBodyNullOrOpaque())
        return nullptr;

    if (!m_body->hasReadableStream())
        createReadableStream(state);

    return m_body->readableStream();
}

void FetchBodyOwner::createReadableStream(JSC::JSGlobalObject& state)
{
    ASSERT(!m_readableStreamSource);
    if (isDisturbed()) {
        m_body->setReadableStream(ReadableStream::create(state, nullptr));
        m_body->readableStream()->lock();
    } else {
        m_readableStreamSource = adoptRef(*new FetchBodySource(*this));
        m_body->setReadableStream(ReadableStream::create(state, m_readableStreamSource));
    }
}

void FetchBodyOwner::consumeBodyAsStream()
{
    ASSERT(m_readableStreamSource);

    if (auto exception = loadingException()) {
        m_readableStreamSource->error(*exception);
        return;
    }

    body().consumeAsStream(*this, *m_readableStreamSource);
    if (!m_readableStreamSource->isPulling())
        m_readableStreamSource = nullptr;
}

ResourceError FetchBodyOwner::loadingError() const
{
    return WTF::switchOn(m_loadingError, [](const ResourceError& error) {
        return ResourceError { error };
    }, [](const Exception& exception) {
        return ResourceError { errorDomainWebKitInternal, 0, { }, exception.message() };
    }, [](auto&&) {
        return ResourceError { };
    });
}

Optional<Exception> FetchBodyOwner::loadingException() const
{
    return WTF::switchOn(m_loadingError, [](const ResourceError& error) {
        return Exception { TypeError, error.localizedDescription().isEmpty() ? "Loading failed"_s : error.localizedDescription() };
    }, [](const Exception& exception) {
        return Exception { exception };
    }, [](auto&&) -> Optional<Exception> {
        return WTF::nullopt;
    });
}

bool FetchBodyOwner::hasLoadingError() const
{
    return WTF::switchOn(m_loadingError, [](const ResourceError&) {
        return true;
    }, [](const Exception&) {
        return true;
    }, [](auto&&) {
        return false;
    });
}

void FetchBodyOwner::setLoadingError(Exception&& exception)
{
    if (hasLoadingError())
        return;

    m_loadingError = WTFMove(exception);
}

void FetchBodyOwner::setLoadingError(ResourceError&& error)
{
    if (hasLoadingError())
        return;

    m_loadingError = WTFMove(error);
}

} // namespace WebCore
