/*
 * Copyright (C) 2004-2018 Apple Inc. All rights reserved.
 * Copyright (C) 2010 Google Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include "config.h"
#include "FileInputType.h"

#include "Chrome.h"
#include "DOMFormData.h"
#include "DragData.h"
#include "ElementChildIterator.h"
#include "Event.h"
#include "File.h"
#include "FileList.h"
#include "FileListCreator.h"
#include "FormController.h"
#include "Frame.h"
#include "HTMLInputElement.h"
#include "HTMLNames.h"
#include "Icon.h"
#include "InputTypeNames.h"
#include "LocalizedStrings.h"
#include "RenderFileUploadControl.h"
#include "RuntimeEnabledFeatures.h"
#include "Settings.h"
#include "ShadowRoot.h"
#include "UserGestureIndicator.h"
#include <wtf/FileSystem.h>
#include <wtf/IsoMallocInlines.h>
#include <wtf/TypeCasts.h>
#include <wtf/text/StringBuilder.h>

namespace WebCore {
class UploadButtonElement;
}

SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::UploadButtonElement)
    static bool isType(const WebCore::Element& element) { return element.isUploadButton(); }
    static bool isType(const WebCore::Node& node) { return is<WebCore::Element>(node) && isType(downcast<WebCore::Element>(node)); }
SPECIALIZE_TYPE_TRAITS_END()

namespace WebCore {

using namespace HTMLNames;

class UploadButtonElement final : public HTMLInputElement {
    WTF_MAKE_ISO_ALLOCATED_INLINE(UploadButtonElement);
public:
    static Ref<UploadButtonElement> create(Document&);
    static Ref<UploadButtonElement> createForMultiple(Document&);

private:
    bool isUploadButton() const override { return true; }
    
    UploadButtonElement(Document&);
};

Ref<UploadButtonElement> UploadButtonElement::create(Document& document)
{
    auto button = adoptRef(*new UploadButtonElement(document));
    button->setValue(fileButtonChooseFileLabel());
    return button;
}

Ref<UploadButtonElement> UploadButtonElement::createForMultiple(Document& document)
{
    auto button = adoptRef(*new UploadButtonElement(document));
    button->setValue(fileButtonChooseMultipleFilesLabel());
    return button;
}

UploadButtonElement::UploadButtonElement(Document& document)
    : HTMLInputElement(inputTag, document, 0, false)
{
    setType(AtomicString("button", AtomicString::ConstructFromLiteral));
    setPseudo(AtomicString("-webkit-file-upload-button", AtomicString::ConstructFromLiteral));
}

FileInputType::FileInputType(HTMLInputElement& element)
    : BaseClickableWithKeyInputType(element)
    , m_fileList(FileList::create())
{
}

FileInputType::~FileInputType()
{
    if (m_fileListCreator)
        m_fileListCreator->cancel();

    if (m_fileChooser)
        m_fileChooser->invalidate();

    if (m_fileIconLoader)
        m_fileIconLoader->invalidate();
}

Vector<FileChooserFileInfo> FileInputType::filesFromFormControlState(const FormControlState& state)
{
    Vector<FileChooserFileInfo> files;
    size_t size = state.size();
    files.reserveInitialCapacity(size / 2);
    for (size_t i = 0; i < size; i += 2) {
        if (!state[i + 1].isEmpty())
            files.uncheckedAppend({ state[i], state[i + 1] });
        else
            files.uncheckedAppend({ state[i] });
    }
    return files;
}

const AtomicString& FileInputType::formControlType() const
{
    return InputTypeNames::file();
}

FormControlState FileInputType::saveFormControlState() const
{
    if (m_fileList->isEmpty())
        return { };

    auto length = Checked<size_t>(m_fileList->files().size()) * Checked<size_t>(2);

    Vector<String> stateVector;
    stateVector.reserveInitialCapacity(length.unsafeGet());
    for (auto& file : m_fileList->files()) {
        stateVector.uncheckedAppend(file->path());
        stateVector.uncheckedAppend(file->name());
    }
    return FormControlState { WTFMove(stateVector) };
}

void FileInputType::restoreFormControlState(const FormControlState& state)
{
    filesChosen(filesFromFormControlState(state));
}

bool FileInputType::appendFormData(DOMFormData& formData, bool multipart) const
{
    ASSERT(element());
    auto fileList = makeRefPtr(element()->files());
    ASSERT(fileList);

    auto name = element()->name();

    if (!multipart) {
        // Send only the basenames.
        // 4.10.16.4 and 4.10.16.6 sections in HTML5.

        // Unlike the multipart case, we have no special handling for the empty
        // fileList because Netscape doesn't support for non-multipart
        // submission of file inputs, and Firefox doesn't add "name=" query
        // parameter.
        for (auto& file : fileList->files())
            formData.append(name, file->name());
        return true;
    }

    // If no filename at all is entered, return successful but empty.
    // Null would be more logical, but Netscape posts an empty file. Argh.
    if (fileList->isEmpty()) {
        formData.append(name, File::create(emptyString()));
        return true;
    }


    for (auto& file : fileList->files())
        formData.append(name, file.get());
    return true;
}

bool FileInputType::valueMissing(const String& value) const
{
    ASSERT(element());
    return element()->isRequired() && value.isEmpty();
}

String FileInputType::valueMissingText() const
{
    ASSERT(element());
    return element()->multiple() ? validationMessageValueMissingForMultipleFileText() : validationMessageValueMissingForFileText();
}

void FileInputType::handleDOMActivateEvent(Event& event)
{
    ASSERT(element());
    auto& input = *element();

    if (input.isDisabledFormControl())
        return;

    if (!UserGestureIndicator::processingUserGesture())
        return;

    if (auto* chrome = this->chrome()) {
        FileChooserSettings settings;
        settings.allowsDirectories = allowsDirectories();
        settings.allowsMultipleFiles = input.hasAttributeWithoutSynchronization(multipleAttr);
        settings.acceptMIMETypes = input.acceptMIMETypes();
        settings.acceptFileExtensions = input.acceptFileExtensions();
        settings.selectedFiles = m_fileList->paths();
#if ENABLE(MEDIA_CAPTURE)
        settings.mediaCaptureType = input.mediaCaptureType();
#endif
        applyFileChooserSettings(settings);
        chrome->runOpenPanel(*input.document().frame(), *m_fileChooser);
    }

    event.setDefaultHandled();
}

RenderPtr<RenderElement> FileInputType::createInputRenderer(RenderStyle&& style)
{
    ASSERT(element());
    return createRenderer<RenderFileUploadControl>(*element(), WTFMove(style));
}

bool FileInputType::canSetStringValue() const
{
    return false;
}

FileList* FileInputType::files()
{
    return m_fileList.ptr();
}

bool FileInputType::canSetValue(const String& value)
{
    // For security reasons, we don't allow setting the filename, but we do allow clearing it.
    // The HTML5 spec (as of the 10/24/08 working draft) says that the value attribute isn't
    // applicable to the file upload control at all, but for now we are keeping this behavior
    // to avoid breaking existing websites that may be relying on this.
    return value.isEmpty();
}

bool FileInputType::getTypeSpecificValue(String& value)
{
    if (m_fileList->isEmpty()) {
        value = { };
        return true;
    }

    // HTML5 tells us that we're supposed to use this goofy value for
    // file input controls. Historically, browsers revealed the real
    // file path, but that's a privacy problem. Code on the web
    // decided to try to parse the value by looking for backslashes
    // (because that's what Windows file paths use). To be compatible
    // with that code, we make up a fake path for the file.
    value = makeString("C:\\fakepath\\", m_fileList->file(0).name());
    return true;
}

void FileInputType::setValue(const String&, bool, TextFieldEventBehavior)
{
    // FIXME: Should we clear the file list, or replace it with a new empty one here? This is observable from JavaScript through custom properties.
    m_fileList->clear();
    m_icon = nullptr;
    ASSERT(element());
    element()->invalidateStyleForSubtree();
}

bool FileInputType::isFileUpload() const
{
    return true;
}

void FileInputType::createShadowSubtree()
{
    ASSERT(element());
    ASSERT(element()->shadowRoot());
    element()->userAgentShadowRoot()->appendChild(element()->multiple() ? UploadButtonElement::createForMultiple(element()->document()): UploadButtonElement::create(element()->document()));
}

void FileInputType::disabledStateChanged()
{
    ASSERT(element());
    ASSERT(element()->shadowRoot());

    auto root = element()->userAgentShadowRoot();
    if (!root)
        return;
    
    if (auto button = makeRefPtr(childrenOfType<UploadButtonElement>(*root).first()))
        button->setBooleanAttribute(disabledAttr, element()->isDisabledFormControl());
}

void FileInputType::attributeChanged(const QualifiedName& name)
{
    if (name == multipleAttr) {
        if (auto* element = this->element()) {
            ASSERT(element->shadowRoot());
            if (auto root = element->userAgentShadowRoot()) {
                if (auto button = makeRefPtr(childrenOfType<UploadButtonElement>(*root).first()))
                    button->setValue(element->multiple() ? fileButtonChooseMultipleFilesLabel() : fileButtonChooseFileLabel());
            }
        }
    }
    BaseClickableWithKeyInputType::attributeChanged(name);
}

void FileInputType::requestIcon(const Vector<String>& paths)
{
    if (!paths.size()) {
        iconLoaded(nullptr);
        return;
    }

    auto* chrome = this->chrome();
    if (!chrome) {
        iconLoaded(nullptr);
        return;
    }

    if (m_fileIconLoader)
        m_fileIconLoader->invalidate();

    FileIconLoaderClient& client = *this;
    m_fileIconLoader = std::make_unique<FileIconLoader>(client);

    chrome->loadIconForFiles(paths, *m_fileIconLoader);
}

void FileInputType::applyFileChooserSettings(const FileChooserSettings& settings)
{
    if (m_fileChooser)
        m_fileChooser->invalidate();

    m_fileChooser = FileChooser::create(this, settings);
}

bool FileInputType::allowsDirectories() const
{
    if (!RuntimeEnabledFeatures::sharedFeatures().directoryUploadEnabled())
        return false;
    ASSERT(element());
    return element()->hasAttributeWithoutSynchronization(webkitdirectoryAttr);
}

void FileInputType::setFiles(RefPtr<FileList>&& files)
{
    setFiles(WTFMove(files), RequestIcon::Yes);
}

void FileInputType::setFiles(RefPtr<FileList>&& files, RequestIcon shouldRequestIcon)
{
    if (!files)
        return;

    ASSERT(element());
    Ref<HTMLInputElement> protectedInputElement(*element());

    unsigned length = files->length();

    bool pathsChanged = false;
    if (length != m_fileList->length())
        pathsChanged = true;
    else {
        for (unsigned i = 0; i < length; ++i) {
            if (files->file(i).path() != m_fileList->file(i).path()) {
                pathsChanged = true;
                break;
            }
        }
    }

    m_fileList = files.releaseNonNull();

    protectedInputElement->setFormControlValueMatchesRenderer(true);
    protectedInputElement->updateValidity();

    if (shouldRequestIcon == RequestIcon::Yes) {
        Vector<String> paths;
        paths.reserveInitialCapacity(length);
        for (auto& file : m_fileList->files())
            paths.uncheckedAppend(file->path());
        requestIcon(paths);
    }

    if (protectedInputElement->renderer())
        protectedInputElement->renderer()->repaint();

    if (pathsChanged) {
        // This call may cause destruction of this instance.
        // input instance is safe since it is ref-counted.
        protectedInputElement->dispatchChangeEvent();
    }
    protectedInputElement->setChangedSinceLastFormControlChangeEvent(false);
}

void FileInputType::filesChosen(const Vector<FileChooserFileInfo>& paths, const String& displayString, Icon* icon)
{
    if (!displayString.isEmpty())
        m_displayString = displayString;

    if (m_fileListCreator)
        m_fileListCreator->cancel();

    auto shouldResolveDirectories = allowsDirectories() ? FileListCreator::ShouldResolveDirectories::Yes : FileListCreator::ShouldResolveDirectories::No;
    auto shouldRequestIcon = icon ? RequestIcon::Yes : RequestIcon::No;
    m_fileListCreator = FileListCreator::create(paths, shouldResolveDirectories, [this, shouldRequestIcon](Ref<FileList>&& fileList) {
        setFiles(WTFMove(fileList), shouldRequestIcon);
        m_fileListCreator = nullptr;
    });

    if (icon && !m_fileList->isEmpty())
        iconLoaded(icon);
}

String FileInputType::displayString() const
{
    return m_displayString;
}

void FileInputType::iconLoaded(RefPtr<Icon>&& icon)
{
    if (m_icon == icon)
        return;

    m_icon = WTFMove(icon);
    ASSERT(element());
    if (auto* renderer = element()->renderer())
        renderer->repaint();
}

#if ENABLE(DRAG_SUPPORT)
bool FileInputType::receiveDroppedFiles(const DragData& dragData)
{
    auto paths = dragData.asFilenames();
    if (paths.isEmpty())
        return false;

    ASSERT(element());
    if (element()->hasAttributeWithoutSynchronization(multipleAttr)) {
        Vector<FileChooserFileInfo> files;
        files.reserveInitialCapacity(paths.size());
        for (auto& path : paths)
            files.uncheckedAppend({ path });

        filesChosen(files);
    } else
        filesChosen({ FileChooserFileInfo { paths[0] } });

    return true;
}
#endif // ENABLE(DRAG_SUPPORT)

Icon* FileInputType::icon() const
{
    return m_icon.get();
}

String FileInputType::defaultToolTip() const
{
    unsigned listSize = m_fileList->length();
    if (!listSize) {
        ASSERT(element());
        if (element()->multiple())
            return fileButtonNoFilesSelectedLabel();
        return fileButtonNoFileSelectedLabel();
    }

    StringBuilder names;
    for (unsigned i = 0; i < listSize; ++i) {
        names.append(m_fileList->file(i).name());
        if (i != listSize - 1)
            names.append('\n');
    }
    return names.toString();
}


} // namespace WebCore
