/*
 * Copyright (C) 2006-2019 Apple 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,
 * 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 "ImageDocument.h"

#include "CachedImage.h"
#include "Chrome.h"
#include "ChromeClient.h"
#include "DOMWindow.h"
#include "DocumentLoader.h"
#include "EventListener.h"
#include "EventNames.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "FrameLoaderClient.h"
#include "FrameView.h"
#include "HTMLBodyElement.h"
#include "HTMLHeadElement.h"
#include "HTMLHtmlElement.h"
#include "HTMLImageElement.h"
#include "HTMLNames.h"
#include "LocalizedStrings.h"
#include "MIMETypeRegistry.h"
#include "MouseEvent.h"
#include "Page.h"
#include "RawDataDocumentParser.h"
#include "RenderElement.h"
#include "Settings.h"
#include <wtf/IsoMallocInlines.h>
#include <wtf/text/StringConcatenateNumbers.h>

namespace WebCore {

WTF_MAKE_ISO_ALLOCATED_IMPL(ImageDocument);

using namespace HTMLNames;

#if !PLATFORM(IOS_FAMILY)
class ImageEventListener final : public EventListener {
public:
    static Ref<ImageEventListener> create(ImageDocument& document) { return adoptRef(*new ImageEventListener(document)); }

private:
    ImageEventListener(ImageDocument& document)
        : EventListener(ImageEventListenerType)
        , m_document(document)
    {
    }

    bool operator==(const EventListener&) const override;
    void handleEvent(ScriptExecutionContext&, Event&) override;

    ImageDocument& m_document;
};
#endif

class ImageDocumentParser final : public RawDataDocumentParser {
public:
    static Ref<ImageDocumentParser> create(ImageDocument& document)
    {
        return adoptRef(*new ImageDocumentParser(document));
    }

private:
    ImageDocumentParser(ImageDocument& document)
        : RawDataDocumentParser(document)
    {
    }

    ImageDocument& document() const;

    void appendBytes(DocumentWriter&, const char*, size_t) override;
    void finish() override;
};

class ImageDocumentElement final : public HTMLImageElement {
    WTF_MAKE_ISO_ALLOCATED_INLINE(ImageDocumentElement);
public:
    static Ref<ImageDocumentElement> create(ImageDocument&);

private:
    ImageDocumentElement(ImageDocument& document)
        : HTMLImageElement(imgTag, document)
        , m_imageDocument(&document)
    {
    }

    virtual ~ImageDocumentElement();
    void didMoveToNewDocument(Document& oldDocument, Document& newDocument) override;

    ImageDocument* m_imageDocument;
};

inline Ref<ImageDocumentElement> ImageDocumentElement::create(ImageDocument& document)
{
    return adoptRef(*new ImageDocumentElement(document));
}

// --------

HTMLImageElement* ImageDocument::imageElement() const
{
    return m_imageElement;
}

LayoutSize ImageDocument::imageSize()
{
    ASSERT(m_imageElement);
    updateStyleIfNeeded();
    return m_imageElement->cachedImage()->imageSizeForRenderer(m_imageElement->renderer(), frame() ? frame()->pageZoomFactor() : 1);
}

void ImageDocument::updateDuringParsing()
{
    if (!settings().areImagesEnabled())
        return;

    if (!m_imageElement)
        createDocumentStructure();

    if (RefPtr<SharedBuffer> buffer = loader()->mainResourceData())
        m_imageElement->cachedImage()->updateBuffer(*buffer);

    imageUpdated();
}

void ImageDocument::finishedParsing()
{
    if (!parser()->isStopped() && m_imageElement) {
        CachedImage& cachedImage = *m_imageElement->cachedImage();
        RefPtr<SharedBuffer> data = loader()->mainResourceData();

        // If this is a multipart image, make a copy of the current part, since the resource data
        // will be overwritten by the next part.
        if (data && loader()->isLoadingMultipartContent())
            data = data->copy();

        cachedImage.finishLoading(data.get(), { });
        cachedImage.finish();

        // Report the natural image size in the page title, regardless of zoom level.
        // At a zoom level of 1 the image is guaranteed to have an integer size.
        updateStyleIfNeeded();
        IntSize size = flooredIntSize(cachedImage.imageSizeForRenderer(m_imageElement->renderer(), 1));
        if (size.width()) {
            // Compute the title. We use the decoded filename of the resource, falling
            // back on the hostname if there is no path.
            String name = decodeURLEscapeSequences(url().lastPathComponent());
            if (name.isEmpty())
                name = url().host().toString();
            setTitle(imageTitle(name, size));
        }

        imageUpdated();
    }

    HTMLDocument::finishedParsing();
}
    
inline ImageDocument& ImageDocumentParser::document() const
{
    // Only used during parsing, so document is guaranteed to be non-null.
    ASSERT(RawDataDocumentParser::document());
    return downcast<ImageDocument>(*RawDataDocumentParser::document());
}

void ImageDocumentParser::appendBytes(DocumentWriter&, const char*, size_t)
{
    document().updateDuringParsing();
}

void ImageDocumentParser::finish()
{
    document().finishedParsing();
}

ImageDocument::ImageDocument(Frame& frame, const URL& url)
    : HTMLDocument(&frame, url, ImageDocumentClass)
    , m_imageElement(nullptr)
    , m_imageSizeIsKnown(false)
#if !PLATFORM(IOS_FAMILY)
    , m_didShrinkImage(false)
#endif
    , m_shouldShrinkImage(frame.settings().shrinksStandaloneImagesToFit() && frame.isMainFrame())
{
    setCompatibilityMode(DocumentCompatibilityMode::QuirksMode);
    lockCompatibilityMode();
}
    
Ref<DocumentParser> ImageDocument::createParser()
{
    return ImageDocumentParser::create(*this);
}

void ImageDocument::createDocumentStructure()
{
    auto rootElement = HTMLHtmlElement::create(*this);
    appendChild(rootElement);
    rootElement->insertedByParser();

    frame()->injectUserScripts(UserScriptInjectionTime::DocumentStart);

    // We need a <head> so that the call to setTitle() later on actually has an <head> to append to <title> to.
    auto head = HTMLHeadElement::create(*this);
    rootElement->appendChild(head);

    auto body = HTMLBodyElement::create(*this);
    body->setAttribute(styleAttr, "margin: 0px");
    if (MIMETypeRegistry::isPDFMIMEType(document().loader()->responseMIMEType()))
        body->setInlineStyleProperty(CSSPropertyBackgroundColor, "white");
    rootElement->appendChild(body);
    
    auto imageElement = ImageDocumentElement::create(*this);
    if (m_shouldShrinkImage)
        imageElement->setAttribute(styleAttr, "-webkit-user-select:none; display:block; margin:auto; padding:env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);");
    else
        imageElement->setAttribute(styleAttr, "-webkit-user-select:none; padding:env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);");
    imageElement->setLoadManually(true);
    imageElement->setSrc(url().string());
    imageElement->cachedImage()->setResponse(loader()->response());
    body->appendChild(imageElement);
    
    if (m_shouldShrinkImage) {
#if PLATFORM(IOS_FAMILY)
        // Set the viewport to be in device pixels (rather than the default of 980).
        processViewport("width=device-width,viewport-fit=cover"_s, ViewportArguments::ImageDocument);
#else
        auto listener = ImageEventListener::create(*this);
        if (RefPtr<DOMWindow> window = this->domWindow())
            window->addEventListener("resize", listener.copyRef(), false);
        imageElement->addEventListener("click", WTFMove(listener), false);
#endif
    }

    m_imageElement = imageElement.ptr();
}

void ImageDocument::imageUpdated()
{
    ASSERT(m_imageElement);

    if (m_imageSizeIsKnown)
        return;

    LayoutSize imageSize = this->imageSize();
    if (imageSize.isEmpty())
        return;

    m_imageSizeIsKnown = true;

    if (m_shouldShrinkImage) {
#if PLATFORM(IOS_FAMILY)
        FloatSize screenSize = page()->chrome().screenSize();
        if (imageSize.width() > screenSize.width())
            processViewport(makeString("width=", imageSize.width().toInt(), ",viewport-fit=cover"), ViewportArguments::ImageDocument);

        if (page())
            page()->chrome().client().imageOrMediaDocumentSizeChanged(IntSize(imageSize.width(), imageSize.height()));
#else
        // Call windowSizeChanged for its side effect of sizing the image.
        windowSizeChanged();
#endif
    }
}

#if !PLATFORM(IOS_FAMILY)
float ImageDocument::scale()
{
    if (!m_imageElement)
        return 1;

    RefPtr<FrameView> view = this->view();
    if (!view)
        return 1;

    LayoutSize imageSize = this->imageSize();

    IntSize viewportSize = view->visibleSize();
    float widthScale = viewportSize.width() / imageSize.width().toFloat();
    float heightScale = viewportSize.height() / imageSize.height().toFloat();

    return std::min(widthScale, heightScale);
}

void ImageDocument::resizeImageToFit()
{
    if (!m_imageElement)
        return;

    LayoutSize imageSize = this->imageSize();

    float scale = this->scale();
    m_imageElement->setWidth(static_cast<int>(imageSize.width() * scale));
    m_imageElement->setHeight(static_cast<int>(imageSize.height() * scale));

    m_imageElement->setInlineStyleProperty(CSSPropertyCursor, CSSValueZoomIn);
}

void ImageDocument::restoreImageSize()
{
    if (!m_imageElement || !m_imageSizeIsKnown)
        return;

    LayoutSize imageSize = this->imageSize();
    m_imageElement->setWidth(imageSize.width().toUnsigned());
    m_imageElement->setHeight(imageSize.height().toUnsigned());

    if (imageFitsInWindow())
        m_imageElement->removeInlineStyleProperty(CSSPropertyCursor);
    else
        m_imageElement->setInlineStyleProperty(CSSPropertyCursor, CSSValueZoomOut);

    m_didShrinkImage = false;
}

bool ImageDocument::imageFitsInWindow()
{
    if (!m_imageElement)
        return true;

    RefPtr<FrameView> view = this->view();
    if (!view)
        return true;

    LayoutSize imageSize = this->imageSize();
    IntSize viewportSize = view->visibleSize();
    return imageSize.width() <= viewportSize.width() && imageSize.height() <= viewportSize.height();
}


void ImageDocument::windowSizeChanged()
{
    if (!m_imageElement || !m_imageSizeIsKnown)
        return;

    bool fitsInWindow = imageFitsInWindow();

    // If the image has been explicitly zoomed in, restore the cursor if the image fits
    // and set it to a zoom out cursor if the image doesn't fit
    if (!m_shouldShrinkImage) {
        if (fitsInWindow)
            m_imageElement->removeInlineStyleProperty(CSSPropertyCursor);
        else
            m_imageElement->setInlineStyleProperty(CSSPropertyCursor, CSSValueZoomOut);
        return;
    }

    if (m_didShrinkImage) {
        // If the window has been resized so that the image fits, restore the image size,
        // otherwise update the restored image size.
        if (fitsInWindow)
            restoreImageSize();
        else
            resizeImageToFit();
    } else {
        // If the image isn't resized but needs to be, then resize it.
        if (!fitsInWindow) {
            resizeImageToFit();
            m_didShrinkImage = true;
        }
    }
}

void ImageDocument::imageClicked(int x, int y)
{
    if (!m_imageSizeIsKnown || imageFitsInWindow())
        return;

    m_shouldShrinkImage = !m_shouldShrinkImage;

    if (m_shouldShrinkImage) {
        // Call windowSizeChanged for its side effect of sizing the image.
        windowSizeChanged();
    } else {
        restoreImageSize();

        updateLayout();

        if (!view())
            return;

        float scale = this->scale();

        IntSize viewportSize = view()->visibleSize();
        int scrollX = static_cast<int>(x / scale - viewportSize.width() / 2.0f);
        int scrollY = static_cast<int>(y / scale - viewportSize.height() / 2.0f);

        view()->setScrollPosition(IntPoint(scrollX, scrollY));
    }
}

void ImageEventListener::handleEvent(ScriptExecutionContext&, Event& event)
{
    if (event.type() == eventNames().resizeEvent)
        m_document.windowSizeChanged();
    else if (event.type() == eventNames().clickEvent && is<MouseEvent>(event)) {
        MouseEvent& mouseEvent = downcast<MouseEvent>(event);
        m_document.imageClicked(mouseEvent.offsetX(), mouseEvent.offsetY());
    }
}

bool ImageEventListener::operator==(const EventListener& other) const
{
    // All ImageEventListener objects compare as equal; OK since there is only one per document.
    return other.type() == ImageEventListenerType;
}
#endif

// --------

ImageDocumentElement::~ImageDocumentElement()
{
    if (m_imageDocument)
        m_imageDocument->disconnectImageElement();
}

void ImageDocumentElement::didMoveToNewDocument(Document& oldDocument, Document& newDocument)
{
    if (m_imageDocument) {
        m_imageDocument->disconnectImageElement();
        m_imageDocument = nullptr;
    }
    HTMLImageElement::didMoveToNewDocument(oldDocument, newDocument);
}

}
