/*
 * Copyright (C) 2004-2018 Apple Inc. All rights reserved.
 * Copyright (C) 2010 Google Inc. All rights reserved.
 * Copyright (C) 2012 Samsung Electronics. 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 "ImageInputType.h"

#include "CachedImage.h"
#include "DOMFormData.h"
#include "ElementInlines.h"
#include "HTMLFormElement.h"
#include "HTMLImageLoader.h"
#include "HTMLInputElement.h"
#include "HTMLNames.h"
#include "HTMLParserIdioms.h"
#include "InputTypeNames.h"
#include "MouseEvent.h"
#include "RenderImage.h"
#include <wtf/NeverDestroyed.h>

namespace WebCore {

using namespace HTMLNames;

ImageInputType::ImageInputType(HTMLInputElement& element)
    : BaseButtonInputType(Type::Image, element)
{
}

const AtomString& ImageInputType::formControlType() const
{
    return InputTypeNames::image();
}

bool ImageInputType::isFormDataAppendable() const
{
    return true;
}

bool ImageInputType::appendFormData(DOMFormData& formData, bool) const
{
    ASSERT(element());
    if (!element()->isActivatedSubmit())
        return false;

    auto& name = element()->name();
    if (name.isEmpty()) {
        formData.append("x"_s, String::number(m_clickLocation.x()));
        formData.append("y"_s, String::number(m_clickLocation.y()));
        return true;
    }

    formData.append(makeString(name, ".x"), String::number(m_clickLocation.x()));
    formData.append(makeString(name, ".y"), String::number(m_clickLocation.y()));

    auto value = element()->value();
    if (!value.isEmpty())
        formData.append(name, value);

    return true;
}

void ImageInputType::handleDOMActivateEvent(Event& event)
{
    ASSERT(element());
    Ref<HTMLInputElement> protectedElement(*element());
    if (protectedElement->isDisabledFormControl() || !protectedElement->form())
        return;

    Ref<HTMLFormElement> protectedForm(*protectedElement->form());

    protectedElement->setActivatedSubmit(true);

    m_clickLocation = IntPoint();
    if (event.underlyingEvent()) {
        Event& underlyingEvent = *event.underlyingEvent();
        if (is<MouseEvent>(underlyingEvent)) {
            MouseEvent& mouseEvent = downcast<MouseEvent>(underlyingEvent);
            if (!mouseEvent.isSimulated())
                m_clickLocation = IntPoint(mouseEvent.offsetX(), mouseEvent.offsetY());
        }
    }

    // Update layout before processing form actions in case the style changes
    // the Form or button relationships.
    protectedElement->document().updateLayoutIgnorePendingStylesheets();

    if (auto currentForm = protectedElement->form())
        currentForm->submitIfPossible(&event); // Event handlers can run.

    protectedElement->setActivatedSubmit(false);
    event.setDefaultHandled();
}

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

void ImageInputType::attributeChanged(const QualifiedName& name)
{
    if (name == altAttr) {
        if (auto* element = this->element()) {
            auto* renderer = element->renderer();
            if (is<RenderImage>(renderer))
                downcast<RenderImage>(*renderer).updateAltText();
        }
    } else if (name == srcAttr) {
        if (auto* element = this->element()) {
            if (element->renderer())
                element->ensureImageLoader().updateFromElementIgnoringPreviousError();
        }
    }
    BaseButtonInputType::attributeChanged(name);
}

void ImageInputType::attach()
{
    BaseButtonInputType::attach();

    ASSERT(element());
    HTMLImageLoader& imageLoader = element()->ensureImageLoader();
    imageLoader.updateFromElement();

    auto* renderer = downcast<RenderImage>(element()->renderer());
    if (!renderer)
        return;

    if (imageLoader.hasPendingBeforeLoadEvent())
        return;

    auto& imageResource = renderer->imageResource();
    imageResource.setCachedImage(imageLoader.image());

    // If we have no image at all because we have no src attribute, set
    // image height and width for the alt text instead.
    if (!imageLoader.image() && !imageResource.cachedImage())
        renderer->setImageSizeForAltText();
}

bool ImageInputType::shouldRespectAlignAttribute()
{
    return true;
}

bool ImageInputType::canBeSuccessfulSubmitButton()
{
    return true;
}

bool ImageInputType::shouldRespectHeightAndWidthAttributes()
{
    return true;
}

unsigned ImageInputType::height() const
{
    ASSERT(element());
    Ref<HTMLInputElement> element(*this->element());

    element->document().updateLayout();

    if (auto* renderer = element->renderer())
        return adjustForAbsoluteZoom(downcast<RenderBox>(*renderer).contentHeight(), *renderer);

    // Check the attribute first for an explicit pixel value.
    if (auto optionalHeight = parseHTMLNonNegativeInteger(element->attributeWithoutSynchronization(heightAttr)))
        return optionalHeight.value();

    // If the image is available, use its height.
    auto* imageLoader = element->imageLoader();
    if (imageLoader && imageLoader->image())
        return imageLoader->image()->imageSizeForRenderer(element->renderer(), 1).height().toUnsigned();

    return 0;
}

unsigned ImageInputType::width() const
{
    ASSERT(element());
    Ref<HTMLInputElement> element(*this->element());

    element->document().updateLayout();

    if (auto* renderer = element->renderer())
        return adjustForAbsoluteZoom(downcast<RenderBox>(*renderer).contentWidth(), *renderer);

    // Check the attribute first for an explicit pixel value.
    if (auto optionalWidth = parseHTMLNonNegativeInteger(element->attributeWithoutSynchronization(widthAttr)))
        return optionalWidth.value();

    // If the image is available, use its width.
    auto* imageLoader = element->imageLoader();
    if (imageLoader && imageLoader->image())
        return imageLoader->image()->imageSizeForRenderer(element->renderer(), 1).width().toUnsigned();

    return 0;
}

String ImageInputType::resultForDialogSubmit() const
{
    return makeString(m_clickLocation.x(), ',', m_clickLocation.y());
}

} // namespace WebCore
