/*
 * 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.
 */

#pragma once

#include "DOMFormData.h"
#include "ExceptionOr.h"
#include "FetchBodyConsumer.h"
#include "FormData.h"
#include "ReadableStream.h"
#include "URLSearchParams.h"
#include <wtf/Variant.h>

namespace WebCore {

class DeferredPromise;
class FetchBodyOwner;
class FetchBodySource;
class ScriptExecutionContext;

class FetchBody {
public:
    void arrayBuffer(FetchBodyOwner&, Ref<DeferredPromise>&&);
    void blob(FetchBodyOwner&, Ref<DeferredPromise>&&, const String&);
    void json(FetchBodyOwner&, Ref<DeferredPromise>&&);
    void text(FetchBodyOwner&, Ref<DeferredPromise>&&);
    void formData(FetchBodyOwner&, Ref<DeferredPromise>&&);

#if ENABLE(STREAMS_API)
    void consumeAsStream(FetchBodyOwner&, FetchBodySource&);
#endif

    using Init = Variant<RefPtr<Blob>, RefPtr<ArrayBufferView>, RefPtr<ArrayBuffer>, RefPtr<DOMFormData>, RefPtr<URLSearchParams>, RefPtr<ReadableStream>, String>;
    static ExceptionOr<FetchBody> extract(Init&&, String&);
    FetchBody() = default;

    WEBCORE_EXPORT static Optional<FetchBody> fromFormData(FormData&);

    void loadingFailed(const Exception&);
    void loadingSucceeded();

    RefPtr<FormData> bodyAsFormData(ScriptExecutionContext&) const;

    using TakenData = Variant<std::nullptr_t, Ref<FormData>, Ref<SharedBuffer>>;
    TakenData take();

    void setAsFormData(Ref<FormData>&& data) { m_data = WTFMove(data); }
    FetchBodyConsumer& consumer() { return m_consumer; }

    void consumeOnceLoadingFinished(FetchBodyConsumer::Type, Ref<DeferredPromise>&&, const String&);
    void cleanConsumer() { m_consumer.clean(); }

    FetchBody clone();

    bool hasReadableStream() const { return !!m_readableStream; }
    const ReadableStream* readableStream() const { return m_readableStream.get(); }
    ReadableStream* readableStream() { return m_readableStream.get(); }
    void setReadableStream(Ref<ReadableStream>&& stream)
    {
        ASSERT(!m_readableStream);
        m_readableStream = WTFMove(stream);
    }

    bool isBlob() const { return WTF::holds_alternative<Ref<const Blob>>(m_data); }
    bool isFormData() const { return WTF::holds_alternative<Ref<FormData>>(m_data); }

private:
    explicit FetchBody(Ref<const Blob>&& data) : m_data(WTFMove(data)) { }
    explicit FetchBody(Ref<const ArrayBuffer>&& data) : m_data(WTFMove(data)) { }
    explicit FetchBody(Ref<const ArrayBufferView>&& data) : m_data(WTFMove(data)) { }
    explicit FetchBody(Ref<FormData>&& data) : m_data(WTFMove(data)) { }
    explicit FetchBody(String&& data) : m_data(WTFMove(data)) { }
    explicit FetchBody(Ref<const URLSearchParams>&& data) : m_data(WTFMove(data)) { }
    explicit FetchBody(const FetchBodyConsumer& consumer) : m_consumer(consumer) { }
    explicit FetchBody(Ref<ReadableStream>&& stream) : m_readableStream(WTFMove(stream)) { }

    void consume(FetchBodyOwner&, Ref<DeferredPromise>&&);

    void consumeArrayBuffer(Ref<DeferredPromise>&&);
    void consumeArrayBufferView(Ref<DeferredPromise>&&);
    void consumeText(Ref<DeferredPromise>&&, const String&);
    void consumeBlob(FetchBodyOwner&, Ref<DeferredPromise>&&);

    bool isArrayBuffer() const { return WTF::holds_alternative<Ref<const ArrayBuffer>>(m_data); }
    bool isArrayBufferView() const { return WTF::holds_alternative<Ref<const ArrayBufferView>>(m_data); }
    bool isURLSearchParams() const { return WTF::holds_alternative<Ref<const URLSearchParams>>(m_data); }
    bool isText() const { return WTF::holds_alternative<String>(m_data); }

    const Blob& blobBody() const { return WTF::get<Ref<const Blob>>(m_data).get(); }
    FormData& formDataBody() { return WTF::get<Ref<FormData>>(m_data).get(); }
    const FormData& formDataBody() const { return WTF::get<Ref<FormData>>(m_data).get(); }
    const ArrayBuffer& arrayBufferBody() const { return WTF::get<Ref<const ArrayBuffer>>(m_data).get(); }
    const ArrayBufferView& arrayBufferViewBody() const { return WTF::get<Ref<const ArrayBufferView>>(m_data).get(); }
    String& textBody() { return WTF::get<String>(m_data); }
    const String& textBody() const { return WTF::get<String>(m_data); }
    const URLSearchParams& urlSearchParamsBody() const { return WTF::get<Ref<const URLSearchParams>>(m_data).get(); }

    using Data = Variant<std::nullptr_t, Ref<const Blob>, Ref<FormData>, Ref<const ArrayBuffer>, Ref<const ArrayBufferView>, Ref<const URLSearchParams>, String>;
    Data m_data { nullptr };

    FetchBodyConsumer m_consumer { FetchBodyConsumer::Type::None };
    RefPtr<ReadableStream> m_readableStream;
};

} // namespace WebCore
