/*
 *  Copyright (C) 2000 Harri Porten (porten@kde.org)
 *  Copyright (C) 2006 Jon Shier (jshier@iastate.edu)
 *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2010 Apple Inc. All rights reseved.
 *  Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
 *  USA
 */

#include "config.h"
#include "WindowFeatures.h"

#include "FloatRect.h"
#include <wtf/ASCIICType.h>
#include <wtf/Assertions.h>
#include <wtf/HashMap.h>
#include <wtf/MathExtras.h>
#include <wtf/text/StringHash.h>

namespace WebCore {

typedef HashMap<String, String, ASCIICaseInsensitiveHash> DialogFeaturesMap;

static void setWindowFeature(WindowFeatures&, StringView key, StringView value);

static DialogFeaturesMap parseDialogFeaturesMap(const String&);
static Optional<bool> boolFeature(const DialogFeaturesMap&, const char* key);
static Optional<float> floatFeature(const DialogFeaturesMap&, const char* key, float min, float max);

// https://html.spec.whatwg.org/#feature-separator
static bool isSeparator(UChar character, FeatureMode mode)
{
    if (mode == FeatureMode::Viewport)
        return character == ' ' || character == '\t' || character == '\n' || character == '\r' || character == '=' || character == ',';

    return isASCIISpace(character) || character == '=' || character == ',';
}

WindowFeatures parseWindowFeatures(StringView featuresString)
{
    // The IE rule is: all features except for channelmode and fullscreen default to YES, but
    // if the user specifies a feature string, all features default to NO. (There is no public
    // standard that applies to this method.)
    //
    // <http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/open_0.asp>
    // We always allow a window to be resized, which is consistent with Firefox.

    WindowFeatures features;

    if (featuresString.isEmpty())
        return features;

    features.menuBarVisible = false;
    features.statusBarVisible = false;
    features.toolBarVisible = false;
    features.locationBarVisible = false;
    features.scrollbarsVisible = false;
    features.noopener = false;

    processFeaturesString(featuresString, FeatureMode::Window, [&features](StringView key, StringView value) {
        setWindowFeature(features, key, value);
    });

    return features;
}

// Window: https://html.spec.whatwg.org/#concept-window-open-features-tokenize
// Viewport: https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariHTMLRef/Articles/MetaTags.html#//apple_ref/doc/uid/TP40008193-SW6
// FIXME: We should considering aligning Viewport feature parsing with Window features parsing.
void processFeaturesString(StringView features, FeatureMode mode, const WTF::Function<void(StringView type, StringView value)>& callback)
{
    unsigned length = features.length();
    for (unsigned i = 0; i < length; ) {
        // Skip to first non-separator.
        while (i < length && isSeparator(features[i], mode))
            ++i;
        unsigned keyBegin = i;

        // Skip to first separator.
        while (i < length && !isSeparator(features[i], mode))
            i++;
        unsigned keyEnd = i;

        // Skip to first '=', but don't skip past a ',' or a non-separator.
        while (i < length && features[i] != '=' && features[i] != ',' && (mode == FeatureMode::Viewport || isSeparator(features[i], mode)))
            ++i;

        // Skip to first non-separator, but don't skip past a ','.
        if (mode == FeatureMode::Viewport || (i < length && isSeparator(features[i], mode))) {
            while (i < length && isSeparator(features[i], mode) && features[i] != ',')
                ++i;
            unsigned valueBegin = i;

            // Skip to first separator.
            while (i < length && !isSeparator(features[i], mode))
                ++i;
            unsigned valueEnd = i;
            callback(features.substring(keyBegin, keyEnd - keyBegin), features.substring(valueBegin, valueEnd - valueBegin));
        } else
            callback(features.substring(keyBegin, keyEnd - keyBegin), StringView());
    }
}

OptionSet<DisabledAdaptations> parseDisabledAdaptations(const String& disabledAdaptationsString)
{
    OptionSet<DisabledAdaptations> disabledAdaptations;
    for (auto& name : disabledAdaptationsString.split(',')) {
        auto normalizedName = name.stripWhiteSpace().convertToASCIILowercase();
        if (normalizedName == watchAdaptationName())
            disabledAdaptations.add(DisabledAdaptations::Watch);
    }
    return disabledAdaptations;
}

static void setWindowFeature(WindowFeatures& features, StringView key, StringView value)
{
    // Listing a key with no value is shorthand for key=yes
    int numericValue;
    if (value.isEmpty() || equalLettersIgnoringASCIICase(value, "yes"))
        numericValue = 1;
    else
        numericValue = value.toInt();

    // We treat key of "resizable" here as an additional feature rather than setting resizeable to true.
    // This is consistent with Firefox, but could also be handled at another level.

    if (equalLettersIgnoringASCIICase(key, "left") || equalLettersIgnoringASCIICase(key, "screenx"))
        features.x = numericValue;
    else if (equalLettersIgnoringASCIICase(key, "top") || equalLettersIgnoringASCIICase(key, "screeny"))
        features.y = numericValue;
    else if (equalLettersIgnoringASCIICase(key, "width") || equalLettersIgnoringASCIICase(key, "innerwidth"))
        features.width = numericValue;
    else if (equalLettersIgnoringASCIICase(key, "height") || equalLettersIgnoringASCIICase(key, "innerheight"))
        features.height = numericValue;
    else if (equalLettersIgnoringASCIICase(key, "menubar"))
        features.menuBarVisible = numericValue;
    else if (equalLettersIgnoringASCIICase(key, "toolbar"))
        features.toolBarVisible = numericValue;
    else if (equalLettersIgnoringASCIICase(key, "location"))
        features.locationBarVisible = numericValue;
    else if (equalLettersIgnoringASCIICase(key, "status"))
        features.statusBarVisible = numericValue;
    else if (equalLettersIgnoringASCIICase(key, "fullscreen"))
        features.fullscreen = numericValue;
    else if (equalLettersIgnoringASCIICase(key, "scrollbars"))
        features.scrollbarsVisible = numericValue;
    else if (equalLettersIgnoringASCIICase(key, "noopener"))
        features.noopener = numericValue;
    else if (equalLettersIgnoringASCIICase(key, "noreferrer"))
        features.noreferrer = numericValue;
    else if (numericValue == 1)
        features.additionalFeatures.append(key.toString());
}

WindowFeatures parseDialogFeatures(const String& dialogFeaturesString, const FloatRect& screenAvailableRect)
{
    auto featuresMap = parseDialogFeaturesMap(dialogFeaturesString);

    // The following features from Microsoft's documentation are not implemented:
    // - default font settings
    // - width, height, left, and top specified in units other than "px"
    // - edge (sunken or raised, default is raised)
    // - dialogHide: trusted && boolFeature(features, "dialoghide"), makes dialog hide when you print
    // - help: boolFeature(features, "help", true), makes help icon appear in dialog (what does it do on Windows?)
    // - unadorned: trusted && boolFeature(features, "unadorned");

    WindowFeatures features;

    features.menuBarVisible = false;
    features.toolBarVisible = false;
    features.locationBarVisible = false;
    features.dialog = true;

    float width = floatFeature(featuresMap, "dialogwidth", 100, screenAvailableRect.width()).valueOr(620); // default here came from frame size of dialog in MacIE
    float height = floatFeature(featuresMap, "dialogheight", 100, screenAvailableRect.height()).valueOr(450); // default here came from frame size of dialog in MacIE

    features.width = width;
    features.height = height;

    features.x = floatFeature(featuresMap, "dialogleft", screenAvailableRect.x(), screenAvailableRect.maxX() - width);
    features.y = floatFeature(featuresMap, "dialogtop", screenAvailableRect.y(), screenAvailableRect.maxY() - height);

    if (boolFeature(featuresMap, "center").valueOr(true)) {
        if (!features.x)
            features.x = screenAvailableRect.x() + (screenAvailableRect.width() - width) / 2;
        if (!features.y)
            features.y = screenAvailableRect.y() + (screenAvailableRect.height() - height) / 2;
    }

    features.resizable = boolFeature(featuresMap, "resizable").valueOr(false);
    features.scrollbarsVisible = boolFeature(featuresMap, "scroll").valueOr(true);
    features.statusBarVisible = boolFeature(featuresMap, "status").valueOr(false);

    return features;
}

static Optional<bool> boolFeature(const DialogFeaturesMap& features, const char* key)
{
    auto it = features.find(key);
    if (it == features.end())
        return WTF::nullopt;

    auto& value = it->value;
    return value.isNull()
        || value == "1"
        || equalLettersIgnoringASCIICase(value, "yes")
        || equalLettersIgnoringASCIICase(value, "on");
}

static Optional<float> floatFeature(const DialogFeaturesMap& features, const char* key, float min, float max)
{
    auto it = features.find(key);
    if (it == features.end())
        return WTF::nullopt;

    // FIXME: The toDouble function does not offer a way to tell "0q" from string with no digits in it: Both
    // return the number 0 and false for ok. But "0q" should yield the minimum rather than the default.
    bool ok;
    double parsedNumber = it->value.toDouble(&ok);
    if ((!parsedNumber && !ok) || std::isnan(parsedNumber))
        return WTF::nullopt;
    if (parsedNumber < min || max <= min)
        return min;
    if (parsedNumber > max)
        return max;

    // FIXME: Seems strange to cast a double to int and then convert back to a float. Why is this a good idea?
    return static_cast<int>(parsedNumber);
}

static DialogFeaturesMap parseDialogFeaturesMap(const String& string)
{
    // FIXME: Not clear why we take such a different approach to parsing dialog features
    // as opposed to window features (using a map, different parsing quirks).

    DialogFeaturesMap features;

    for (auto& featureString : string.split(';')) {
        size_t separatorPosition = featureString.find('=');
        size_t colonPosition = featureString.find(':');
        if (separatorPosition != notFound && colonPosition != notFound)
            continue; // ignore strings that have both = and :
        if (separatorPosition == notFound)
            separatorPosition = colonPosition;

        String key = featureString.left(separatorPosition).stripWhiteSpace();

        // Null string for value indicates key without value.
        String value;
        if (separatorPosition != notFound) {
            value = featureString.substring(separatorPosition + 1).stripWhiteSpace();
            value = value.left(value.find(' '));
        }

        features.set(key, value);
    }

    return features;
}

} // namespace WebCore
