/*
 * Copyright (C) 2008 Apple Inc.  All rights reserved.
 * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
 * Copyright (C) 2007 Alp Toker <alp.toker@collabora.co.uk>
 * Copyright (C) 2007 Holger Hans Peter Freyther
 * Copyright (C) 2008 Collabora Ltd.
 * Copyright (C) 2018 Sony Interactive Entertainment 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. ``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
 * 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 "CurlFormDataStream.h"

#if USE(CURL)

#include "BlobRegistry.h"
#include "CurlContext.h"
#include "Logging.h"
#include <wtf/MainThread.h>

namespace WebCore {

CurlFormDataStream::CurlFormDataStream(const FormData* formData)
{
    ASSERT(isMainThread());

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

    m_formData = formData->isolatedCopy();

    // Resolve the blob elements so the formData can correctly report it's size.
    m_formData = m_formData->resolveBlobReferences(blobRegistry().blobRegistryImpl());
}

CurlFormDataStream::~CurlFormDataStream()
{

}

void CurlFormDataStream::clean()
{
    if (m_postData)
        m_postData = nullptr;

    if (m_fileHandle != FileSystem::invalidPlatformFileHandle) {
        FileSystem::closeFile(m_fileHandle);
        m_fileHandle = FileSystem::invalidPlatformFileHandle;
    }
}

const Vector<char>* CurlFormDataStream::getPostData()
{
    if (!m_formData)
        return nullptr;

    if (!m_postData)
        m_postData = makeUnique<Vector<char>>(m_formData->flatten());

    return m_postData.get();
}

bool CurlFormDataStream::shouldUseChunkTransfer()
{
    computeContentLength();

    return m_shouldUseChunkTransfer;
}

unsigned long long CurlFormDataStream::totalSize()
{
    computeContentLength();

    return m_totalSize;
}

void CurlFormDataStream::computeContentLength()
{
    if (!m_formData || m_isContentLengthUpdated)
        return;

    m_isContentLengthUpdated = true;

    for (const auto& element : m_formData->elements())
        m_totalSize += element.lengthInBytes();
}

Optional<size_t> CurlFormDataStream::read(char* buffer, size_t size)
{
    if (!m_formData)
        return WTF::nullopt;

    const auto totalElementSize = m_formData->elements().size();
    if (m_elementPosition >= totalElementSize)
        return 0;

    size_t totalReadBytes = 0;

    while ((m_elementPosition < totalElementSize) && (totalReadBytes < size)) {
        const auto& element = m_formData->elements().at(m_elementPosition);

        size_t bufferSize = size - totalReadBytes;
        char* bufferPosition = buffer + totalReadBytes;

        Optional<size_t> readBytes = switchOn(element.data,
            [&] (const Vector<char>& bytes) {
                return readFromData(bytes, bufferPosition, bufferSize);
            }, [&] (const FormDataElement::EncodedFileData& fileData) {
                return readFromFile(fileData, bufferPosition, bufferSize);
            }, [] (const FormDataElement::EncodedBlobData& blobData) {
                ASSERT_NOT_REACHED();
                return WTF::nullopt;
            }
        );

        if (!readBytes)
            return WTF::nullopt;

        totalReadBytes += *readBytes;
    }

    m_totalReadSize += totalReadBytes;

    return totalReadBytes;
}

Optional<size_t> CurlFormDataStream::readFromFile(const FormDataElement::EncodedFileData& fileData, char* buffer, size_t size)
{
    if (m_fileHandle == FileSystem::invalidPlatformFileHandle)
        m_fileHandle = FileSystem::openFile(fileData.filename, FileSystem::FileOpenMode::Read);

    if (!FileSystem::isHandleValid(m_fileHandle)) {
        LOG(Network, "Curl - Failed while trying to open %s for upload\n", fileData.filename.utf8().data());
        m_fileHandle = FileSystem::invalidPlatformFileHandle;
        return WTF::nullopt;
    }

    auto readBytes = FileSystem::readFromFile(m_fileHandle, buffer, size);
    if (readBytes < 0) {
        LOG(Network, "Curl - Failed while trying to read %s for upload\n", fileData.filename.utf8().data());
        FileSystem::closeFile(m_fileHandle);
        m_fileHandle = FileSystem::invalidPlatformFileHandle;
        return WTF::nullopt;
    }

    if (!readBytes) {
        FileSystem::closeFile(m_fileHandle);
        m_fileHandle = FileSystem::invalidPlatformFileHandle;
        m_elementPosition++;
    }

    return readBytes;
}

Optional<size_t> CurlFormDataStream::readFromData(const Vector<char>& data, char* buffer, size_t size)
{
    size_t elementSize = data.size() - m_dataOffset;
    const char* elementBuffer = data.data() + m_dataOffset;

    size_t readBytes = elementSize > size ? size : elementSize;
    memcpy(buffer, elementBuffer, readBytes);

    if (elementSize > readBytes)
        m_dataOffset += readBytes;
    else {
        m_dataOffset = 0;
        m_elementPosition++;
    }

    return readBytes;
}

} // namespace WebCore

#endif
