/*
 * Copyright (C) 2010 Google 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * OWNER 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 "DOMFormData.h"

#include "Document.h"
#include "HTMLFormControlElement.h"
#include "HTMLFormElement.h"

namespace WebCore {

DOMFormData::DOMFormData(const PAL::TextEncoding& encoding)
    : m_encoding(encoding)
{
}

ExceptionOr<Ref<DOMFormData>> DOMFormData::create(HTMLFormElement* form)
{
    auto formData = adoptRef(*new DOMFormData);
    if (!form)
        return formData;
    
    auto result = form->constructEntryList(nullptr, WTFMove(formData), nullptr);
    
    if (!result)
        return Exception { InvalidStateError, "Already constructing Form entry list."_s };
    
    return result.releaseNonNull();
}

Ref<DOMFormData> DOMFormData::create(const PAL::TextEncoding& encoding)
{
    return adoptRef(*new DOMFormData(encoding));
}

Ref<DOMFormData> DOMFormData::clone() const
{
    auto newFormData = adoptRef(*new DOMFormData(this->encoding()));
    newFormData->m_items = m_items;
    
    return newFormData;
}

// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#create-an-entry
static auto createStringEntry(const String& name, const String& value) -> DOMFormData::Item
{
    return {
        replaceUnpairedSurrogatesWithReplacementCharacter(String(name)),
        replaceUnpairedSurrogatesWithReplacementCharacter(String(value)),
    };
}

// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#create-an-entry
static auto createFileEntry(const String& name, Blob& blob, const String& filename) -> DOMFormData::Item
{
    auto usvName = replaceUnpairedSurrogatesWithReplacementCharacter(String(name));

    if (!blob.isFile())
        return { usvName, File::create(blob.scriptExecutionContext(), blob, filename.isNull() ? "blob"_s : filename) };

    if (!filename.isNull())
        return { usvName, File::create(blob.scriptExecutionContext(), downcast<File>(blob), filename) };

    return { usvName, RefPtr<File> { &downcast<File>(blob) } };
}

void DOMFormData::append(const String& name, const String& value)
{
    m_items.append(createStringEntry(name, value));
}

void DOMFormData::append(const String& name, Blob& blob, const String& filename)
{
    m_items.append(createFileEntry(name, blob, filename));
}

void DOMFormData::remove(const String& name)
{
    m_items.removeAllMatching([&name] (const auto& item) {
        return item.name == name;
    });
}

auto DOMFormData::get(const String& name) -> std::optional<FormDataEntryValue>
{
    for (auto& item : m_items) {
        if (item.name == name)
            return item.data;
    }

    return std::nullopt;
}

auto DOMFormData::getAll(const String& name) -> Vector<FormDataEntryValue>
{
    Vector<FormDataEntryValue> result;

    for (auto& item : m_items) {
        if (item.name == name)
            result.append(item.data);
    }

    return result;
}

bool DOMFormData::has(const String& name)
{
    for (auto& item : m_items) {
        if (item.name == name)
            return true;
    }
    
    return false;
}

void DOMFormData::set(const String& name, const String& value)
{
    set(name, { name, value });
}

void DOMFormData::set(const String& name, Blob& blob, const String& filename)
{
    set(name, createFileEntry(name, blob, filename));
}

void DOMFormData::set(const String& name, Item&& item)
{
    std::optional<size_t> initialMatchLocation;

    // Find location of the first item with a matching name.
    for (size_t i = 0; i < m_items.size(); ++i) {
        if (name == m_items[i].name) {
            initialMatchLocation = i;
            break;
        }
    }

    if (initialMatchLocation) {
        m_items[*initialMatchLocation] = WTFMove(item);

        m_items.removeAllMatching([&name] (const auto& item) {
            return item.name == name;
        }, *initialMatchLocation + 1);
        return;
    }

    m_items.append(WTFMove(item));
}

DOMFormData::Iterator::Iterator(DOMFormData& target)
    : m_target(target)
{
}

std::optional<KeyValuePair<String, DOMFormData::FormDataEntryValue>> DOMFormData::Iterator::next()
{
    auto& items = m_target->items();
    if (m_index >= items.size())
        return std::nullopt;

    auto& item = items[m_index++];
    return makeKeyValuePair(item.name, item.data);
}

} // namespace WebCore
