/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
 *           (C) 2006 Alexey Proskuryakov (ap@webkit.org)
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserved.
 * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
 * Copyright (C) 2012 Intel Corporation. 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 "ViewportArguments.h"

#include "Document.h"
#include "Frame.h"
#include "IntSize.h"
#include "ScriptableDocumentParser.h"
#include "Settings.h"
#include <wtf/text/TextStream.h>

namespace WebCore {

typedef Function<void(ViewportErrorCode, StringView, StringView)> InternalViewportErrorHandler;

#if PLATFORM(GTK)
const float ViewportArguments::deprecatedTargetDPI = 160;
#endif

static const float& compareIgnoringAuto(const float& value1, const float& value2, const float& (*compare) (const float&, const float&))
{
    ASSERT(value1 != ViewportArguments::ValueAuto || value2 != ViewportArguments::ValueAuto);

    if (value1 == ViewportArguments::ValueAuto)
        return value2;

    if (value2 == ViewportArguments::ValueAuto)
        return value1;

    return compare(value1, value2);
}

static inline float clampLengthValue(float value)
{
    ASSERT(value != ViewportArguments::ValueDeviceWidth);
    ASSERT(value != ViewportArguments::ValueDeviceHeight);

    // Limits as defined in the css-device-adapt spec.
    if (value != ViewportArguments::ValueAuto)
        return std::min<float>(10000, std::max<float>(value, 1));
    return value;
}

static inline float clampScaleValue(float value)
{
    ASSERT(value != ViewportArguments::ValueDeviceWidth);
    ASSERT(value != ViewportArguments::ValueDeviceHeight);

    // Limits as defined in the css-device-adapt spec.
    if (value != ViewportArguments::ValueAuto)
        return std::min<float>(10, std::max<float>(value, 0.1));
    return value;
}

ViewportAttributes ViewportArguments::resolve(const FloatSize& initialViewportSize, const FloatSize& deviceSize, int defaultWidth) const
{
    float resultWidth = width;
    float resultMaxWidth = maxWidth;
    float resultMinWidth = minWidth;
    float resultHeight = height;
    float resultMinHeight = minHeight;
    float resultMaxHeight = maxHeight;
    float resultZoom = zoom;
    float resultMinZoom = minZoom;
    float resultMaxZoom = maxZoom;

    switch (int(resultWidth)) {
    case ViewportArguments::ValueDeviceWidth:
        resultWidth = deviceSize.width();
        break;
    case ViewportArguments::ValueDeviceHeight:
        resultWidth = deviceSize.height();
        break;
    }

    switch (int(resultHeight)) {
    case ViewportArguments::ValueDeviceWidth:
        resultHeight = deviceSize.width();
        break;
    case ViewportArguments::ValueDeviceHeight:
        resultHeight = deviceSize.height();
        break;
    }

    if (type == ViewportArguments::CSSDeviceAdaptation) {
        switch (int(resultMinWidth)) {
        case ViewportArguments::ValueDeviceWidth:
            resultMinWidth = deviceSize.width();
            break;
        case ViewportArguments::ValueDeviceHeight:
            resultMinWidth = deviceSize.height();
            break;
        }

        switch (int(resultMaxWidth)) {
        case ViewportArguments::ValueDeviceWidth:
            resultMaxWidth = deviceSize.width();
            break;
        case ViewportArguments::ValueDeviceHeight:
            resultMaxWidth = deviceSize.height();
            break;
        }

        switch (int(resultMinHeight)) {
        case ViewportArguments::ValueDeviceWidth:
            resultMinHeight = deviceSize.width();
            break;
        case ViewportArguments::ValueDeviceHeight:
            resultMinHeight = deviceSize.height();
            break;
        }

        switch (int(resultMaxHeight)) {
        case ViewportArguments::ValueDeviceWidth:
            resultMaxHeight = deviceSize.width();
            break;
        case ViewportArguments::ValueDeviceHeight:
            resultMaxHeight = deviceSize.height();
            break;
        }

        if (resultMinWidth != ViewportArguments::ValueAuto || resultMaxWidth != ViewportArguments::ValueAuto)
            resultWidth = compareIgnoringAuto(resultMinWidth, compareIgnoringAuto(resultMaxWidth, deviceSize.width(), std::min), std::max);

        if (resultMinHeight != ViewportArguments::ValueAuto || resultMaxHeight != ViewportArguments::ValueAuto)
            resultHeight = compareIgnoringAuto(resultMinHeight, compareIgnoringAuto(resultMaxHeight, deviceSize.height(), std::min), std::max);

        if (resultMinZoom != ViewportArguments::ValueAuto && resultMaxZoom != ViewportArguments::ValueAuto)
            resultMaxZoom = std::max(resultMinZoom, resultMaxZoom);

        if (resultZoom != ViewportArguments::ValueAuto)
            resultZoom = compareIgnoringAuto(resultMinZoom, compareIgnoringAuto(resultMaxZoom, resultZoom, std::min), std::max);

        if (resultWidth == ViewportArguments::ValueAuto && resultZoom == ViewportArguments::ValueAuto)
            resultWidth = deviceSize.width();

        if (resultWidth == ViewportArguments::ValueAuto && resultHeight == ViewportArguments::ValueAuto)
            resultWidth = deviceSize.width() / resultZoom;

        if (resultWidth == ViewportArguments::ValueAuto)
            resultWidth = resultHeight * deviceSize.width() / deviceSize.height();

        if (resultHeight == ViewportArguments::ValueAuto)
            resultHeight = resultWidth * deviceSize.height() / deviceSize.width();

        if (resultZoom != ViewportArguments::ValueAuto || resultMaxZoom != ViewportArguments::ValueAuto) {
            resultWidth = compareIgnoringAuto(resultWidth, deviceSize.width() / compareIgnoringAuto(resultZoom, resultMaxZoom, std::min), std::max);
            resultHeight = compareIgnoringAuto(resultHeight, deviceSize.height() / compareIgnoringAuto(resultZoom, resultMaxZoom, std::min), std::max);
        }

        resultWidth = std::max<float>(1, resultWidth);
        resultHeight = std::max<float>(1, resultHeight);
    }

    if (type != ViewportArguments::CSSDeviceAdaptation && type != ViewportArguments::Implicit) {
        // Clamp values to a valid range, but not for @viewport since is
        // not mandated by the specification.
        resultWidth = clampLengthValue(resultWidth);
        resultHeight = clampLengthValue(resultHeight);
        resultZoom = clampScaleValue(resultZoom);
        resultMinZoom = clampScaleValue(resultMinZoom);
        resultMaxZoom = clampScaleValue(resultMaxZoom);
    }

    ViewportAttributes result;

    // Resolve minimum-scale and maximum-scale values according to spec.
    if (resultMinZoom == ViewportArguments::ValueAuto)
        result.minimumScale = float(0.25);
    else
        result.minimumScale = resultMinZoom;

    if (resultMaxZoom == ViewportArguments::ValueAuto) {
        result.maximumScale = 5;
        result.minimumScale = std::min<float>(5, result.minimumScale);
    } else
        result.maximumScale = resultMaxZoom;
    result.maximumScale = std::max(result.minimumScale, result.maximumScale);

    // Resolve initial-scale value.
    result.initialScale = resultZoom;
    if (resultZoom == ViewportArguments::ValueAuto) {
        result.initialScale = initialViewportSize.width() / defaultWidth;
        if (resultWidth != ViewportArguments::ValueAuto)
            result.initialScale = initialViewportSize.width() / resultWidth;
        if (resultHeight != ViewportArguments::ValueAuto) {
            // if 'auto', the initial-scale will be negative here and thus ignored.
            result.initialScale = std::max<float>(result.initialScale, initialViewportSize.height() / resultHeight);
        }
    }

    // Constrain initial-scale value to minimum-scale/maximum-scale range.
    result.initialScale = std::min(result.maximumScale, std::max(result.minimumScale, result.initialScale));

    // Resolve width value.
    if (resultWidth == ViewportArguments::ValueAuto) {
        if (resultZoom == ViewportArguments::ValueAuto)
            resultWidth = defaultWidth;
        else if (resultHeight != ViewportArguments::ValueAuto)
            resultWidth = resultHeight * (initialViewportSize.width() / initialViewportSize.height());
        else
            resultWidth = initialViewportSize.width() / result.initialScale;
    }

    // Resolve height value.
    if (resultHeight == ViewportArguments::ValueAuto)
        resultHeight = resultWidth * (initialViewportSize.height() / initialViewportSize.width());

    if (type == ViewportArguments::ViewportMeta) {
        // Extend width and height to fill the visual viewport for the resolved initial-scale.
        resultWidth = std::max<float>(resultWidth, initialViewportSize.width() / result.initialScale);
        resultHeight = std::max<float>(resultHeight, initialViewportSize.height() / result.initialScale);
    }

    result.layoutSize.setWidth(resultWidth);
    result.layoutSize.setHeight(resultHeight);

    // FIXME: This might affect some ports, but is the right thing to do.
    // Only set initialScale to a value if it was explicitly set.
    // if (resultZoom == ViewportArguments::ValueAuto)
    //    result.initialScale = ViewportArguments::ValueAuto;

    result.userScalable = userZoom;
    result.orientation = orientation;
    result.shrinkToFit = shrinkToFit;
    result.viewportFit = viewportFit;

    return result;
}

static FloatSize convertToUserSpace(const FloatSize& deviceSize, float devicePixelRatio)
{
    FloatSize result = deviceSize;
    if (devicePixelRatio != 1)
        result.scale(1 / devicePixelRatio);
    return result;
}

ViewportAttributes computeViewportAttributes(ViewportArguments args, int desktopWidth, int deviceWidth, int deviceHeight, float devicePixelRatio, IntSize visibleViewport)
{
    FloatSize initialViewportSize = convertToUserSpace(visibleViewport, devicePixelRatio);
    FloatSize deviceSize = convertToUserSpace(FloatSize(deviceWidth, deviceHeight), devicePixelRatio);

    return args.resolve(initialViewportSize, deviceSize, desktopWidth);
}

float computeMinimumScaleFactorForContentContained(const ViewportAttributes& result, const IntSize& visibleViewport, const IntSize& contentsSize)
{
    FloatSize viewportSize(visibleViewport);
    return std::max<float>(result.minimumScale, std::max(viewportSize.width() / contentsSize.width(), viewportSize.height() / contentsSize.height()));
}

void restrictMinimumScaleFactorToViewportSize(ViewportAttributes& result, IntSize visibleViewport, float devicePixelRatio)
{
    FloatSize viewportSize = convertToUserSpace(visibleViewport, devicePixelRatio);

    result.minimumScale = std::max<float>(result.minimumScale, std::max(viewportSize.width() / result.layoutSize.width(), viewportSize.height() / result.layoutSize.height()));
}

void restrictScaleFactorToInitialScaleIfNotUserScalable(ViewportAttributes& result)
{
    if (!result.userScalable)
        result.maximumScale = result.minimumScale = result.initialScale;
}

static float numericPrefix(StringView key, StringView value, const InternalViewportErrorHandler& errorHandler, bool* ok = nullptr)
{
    size_t parsedLength;
    float numericValue;
    if (value.is8Bit())
        numericValue = charactersToFloat(value.characters8(), value.length(), parsedLength);
    else
        numericValue = charactersToFloat(value.characters16(), value.length(), parsedLength);
    if (!parsedLength) {
        errorHandler(UnrecognizedViewportArgumentValueError, value, key);
        if (ok)
            *ok = false;
        return 0;
    }
    if (parsedLength < value.length())
        errorHandler(TruncatedViewportArgumentValueError, value, key);
    if (ok)
        *ok = true;
    return numericValue;
}

static float findSizeValue(StringView key, StringView value, const InternalViewportErrorHandler& errorHandler, bool* valueWasExplicit = nullptr)
{
    // 1) Non-negative number values are translated to px lengths.
    // 2) Negative number values are translated to auto.
    // 3) device-width and device-height are used as keywords.
    // 4) Other keywords and unknown values translate to 0.0.

    if (valueWasExplicit)
        *valueWasExplicit = true;

    if (equalLettersIgnoringASCIICase(value, "device-width"))
        return ViewportArguments::ValueDeviceWidth;

    if (equalLettersIgnoringASCIICase(value, "device-height"))
        return ViewportArguments::ValueDeviceHeight;

    float sizeValue = numericPrefix(key, value, errorHandler);

    if (sizeValue < 0) {
        if (valueWasExplicit)
            *valueWasExplicit = false;
        return ViewportArguments::ValueAuto;
    }

    return sizeValue;
}

static float findScaleValue(StringView key, StringView value, const InternalViewportErrorHandler& errorHandler)
{
    // 1) Non-negative number values are translated to <number> values.
    // 2) Negative number values are translated to auto.
    // 3) yes is translated to 1.0.
    // 4) device-width and device-height are translated to 10.0.
    // 5) no and unknown values are translated to 0.0

    if (equalLettersIgnoringASCIICase(value, "yes"))
        return 1;
    if (equalLettersIgnoringASCIICase(value, "no"))
        return 0;
    if (equalLettersIgnoringASCIICase(value, "device-width"))
        return 10;
    if (equalLettersIgnoringASCIICase(value, "device-height"))
        return 10;

    float numericValue = numericPrefix(key, value, errorHandler);

    if (numericValue < 0)
        return ViewportArguments::ValueAuto;

    if (numericValue > 10.0)
        errorHandler(MaximumScaleTooLargeError, { }, { });

    return numericValue;
}

static bool findBooleanValue(StringView key, StringView value, const InternalViewportErrorHandler& errorHandler)
{
    // yes and no are used as keywords.
    // Numbers >= 1, numbers <= -1, device-width and device-height are mapped to yes.
    // Numbers in the range <-1, 1>, and unknown values, are mapped to no.

    if (equalLettersIgnoringASCIICase(value, "yes"))
        return true;
    if (equalLettersIgnoringASCIICase(value, "no"))
        return false;
    if (equalLettersIgnoringASCIICase(value, "device-width"))
        return true;
    if (equalLettersIgnoringASCIICase(value, "device-height"))
        return true;
    return std::abs(numericPrefix(key, value, errorHandler)) >= 1;
}

static ViewportFit parseViewportFitValue(StringView key, StringView value, const InternalViewportErrorHandler& errorHandler)
{
    if (equalLettersIgnoringASCIICase(value, "auto"))
        return ViewportFit::Auto;
    if (equalLettersIgnoringASCIICase(value, "contain"))
        return ViewportFit::Contain;
    if (equalLettersIgnoringASCIICase(value, "cover"))
        return ViewportFit::Cover;

    errorHandler(UnrecognizedViewportArgumentValueError, value, key);

    return ViewportFit::Auto;
}

static const char* viewportErrorMessageTemplate(ViewportErrorCode errorCode)
{
    static const char* const errors[] = {
        "Viewport argument key \"%replacement1\" not recognized and ignored.",
        "Viewport argument value \"%replacement1\" for key \"%replacement2\" is invalid, and has been ignored.",
        "Viewport argument value \"%replacement1\" for key \"%replacement2\" was truncated to its numeric prefix.",
        "Viewport maximum-scale cannot be larger than 10.0. The maximum-scale will be set to 10.0."
    };

    return errors[errorCode];
}

static MessageLevel viewportErrorMessageLevel(ViewportErrorCode errorCode)
{
    switch (errorCode) {
    case TruncatedViewportArgumentValueError:
        return MessageLevel::Warning;
    case UnrecognizedViewportArgumentKeyError:
    case UnrecognizedViewportArgumentValueError:
    case MaximumScaleTooLargeError:
        return MessageLevel::Error;
    }

    ASSERT_NOT_REACHED();
    return MessageLevel::Error;
}

static String viewportErrorMessage(ViewportErrorCode errorCode, StringView replacement1, StringView replacement2)
{
    String message = viewportErrorMessageTemplate(errorCode);
    if (!replacement1.isNull())
        message.replace("%replacement1", replacement1.toStringWithoutCopying());
    // FIXME: This will do the wrong thing if replacement1 contains the substring "%replacement2".
    if (!replacement2.isNull())
        message.replace("%replacement2", replacement2.toStringWithoutCopying());

    if ((errorCode == UnrecognizedViewportArgumentValueError || errorCode == TruncatedViewportArgumentValueError) && replacement1.contains(';'))
        message.append(" Note that ';' is not a separator in viewport values. The list should be comma-separated.");

    return message;
}

static void reportViewportWarning(Document& document, ViewportErrorCode errorCode, const String& message)
{
    // FIXME: Why is this null check needed? Can't addConsoleMessage deal with this?
    if (!document.frame())
        return;

    // FIXME: This message should be moved off the console once a solution to https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
    document.addConsoleMessage(MessageSource::Rendering, viewportErrorMessageLevel(errorCode), message);
}

void setViewportFeature(ViewportArguments& arguments, StringView key, StringView value, bool viewportFitEnabled, const ViewportErrorHandler& errorHandler)
{
    InternalViewportErrorHandler internalErrorHandler = [&errorHandler] (ViewportErrorCode errorCode, StringView replacement1, StringView replacement2) {
        errorHandler(errorCode, viewportErrorMessage(errorCode, replacement1, replacement2));
    };

    if (equalLettersIgnoringASCIICase(key, "width"))
        arguments.width = findSizeValue(key, value, internalErrorHandler, &arguments.widthWasExplicit);
    else if (equalLettersIgnoringASCIICase(key, "height"))
        arguments.height = findSizeValue(key, value, internalErrorHandler);
    else if (equalLettersIgnoringASCIICase(key, "initial-scale"))
        arguments.zoom = findScaleValue(key, value, internalErrorHandler);
    else if (equalLettersIgnoringASCIICase(key, "minimum-scale"))
        arguments.minZoom = findScaleValue(key, value, internalErrorHandler);
    else if (equalLettersIgnoringASCIICase(key, "maximum-scale"))
        arguments.maxZoom = findScaleValue(key, value, internalErrorHandler);
    else if (equalLettersIgnoringASCIICase(key, "user-scalable"))
        arguments.userZoom = findBooleanValue(key, value, internalErrorHandler);
#if PLATFORM(IOS_FAMILY)
    else if (equalLettersIgnoringASCIICase(key, "minimal-ui")) {
        // FIXME: Ignore silently for now. This code should eventually be removed
        // so we start giving the warning in the web inspector as for other unimplemented keys.
    }
#endif
    else if (equalLettersIgnoringASCIICase(key, "shrink-to-fit"))
        arguments.shrinkToFit = findBooleanValue(key, value, internalErrorHandler);
    else if (equalLettersIgnoringASCIICase(key, "viewport-fit") && viewportFitEnabled)
        arguments.viewportFit = parseViewportFitValue(key, value, internalErrorHandler);
    else
        internalErrorHandler(UnrecognizedViewportArgumentKeyError, key, { });
}

void setViewportFeature(ViewportArguments& arguments, Document& document, StringView key, StringView value)
{
    setViewportFeature(arguments, key, value, document.settings().viewportFitEnabled(), [&](ViewportErrorCode errorCode, const String& message) {
        reportViewportWarning(document, errorCode, message);
    });
}

TextStream& operator<<(TextStream& ts, const ViewportArguments& viewportArguments)
{
    TextStream::IndentScope indentScope(ts);

    ts << "\n" << indent << "(width " << viewportArguments.width << ", minWidth " << viewportArguments.minWidth << ", maxWidth " << viewportArguments.maxWidth << ")";
    ts << "\n" << indent << "(height " << viewportArguments.height << ", minHeight " << viewportArguments.minHeight << ", maxHeight " << viewportArguments.maxHeight << ")";
    ts << "\n" << indent << "(zoom " << viewportArguments.zoom << ", minZoom " << viewportArguments.minZoom << ", maxZoom " << viewportArguments.maxZoom << ")";

    return ts;
}

} // namespace WebCore
