/*
 * <%= @warning %>
 *
 * Copyright (C) 2017 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. AND ITS CONTRIBUTORS ``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 ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 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 "WebPreferences.h"

#include "WebPreferencesKeys.h"

namespace WebKit {

<%- for @pref in @experimentalFeatures do -%>
void WebPreferences::set<%= @pref.name %>(const bool& value)
{
    if (!m_store.setBoolValueForKey(WebPreferencesKey::<%= @pref.nameLower %>Key(), value))
        return;
    updateBoolValueForExperimentalFeatureKey(WebPreferencesKey::<%= @pref.nameLower %>Key(), value);
}

bool WebPreferences::<%= @pref.nameLower %>() const
{
    return m_store.getBoolValueForKey(WebPreferencesKey::<%= @pref.nameLower %>Key());
}

<%- end -%>
const Vector<RefPtr<API::Object>>& WebPreferences::experimentalFeatures()
{
    static NeverDestroyed<Vector<RefPtr<API::Object>>> features(std::initializer_list<RefPtr<API::Object>> {
<%- for @pref in @experimentalFeatures do -%>
<%- if @pref.condition -%>
#if <%= @pref.condition %>
<%- end -%>
        API::ExperimentalFeature::create(<%= @pref.humanReadableName %>, "<%= @pref.name %>", <%= @pref.humanReadableDescription %>, <%= @pref.defaultValue %>, <%= @pref.hidden %>),
<%- if @pref.condition -%>
#endif
<%- end -%>
<%- end -%>
    });

    return features;
}

bool WebPreferences::isFeatureEnabled(const API::ExperimentalFeature& feature) const
{
    struct FeatureGetterMapping {
        const char* name;
        bool (WebPreferences::*function) () const;
    };

    static FeatureGetterMapping getters[] = {
<%- for @pref in @experimentalFeatures do -%>
<%- if @pref.condition -%>
#if <%= @pref.condition %>
<%- end -%>
        { "<%= @pref.name %>", &WebPreferences::<%= @pref.nameLower %> },
<%- if @pref.condition -%>
#endif
<%- end -%>
<%- end -%>
    };

    const String& key = feature.key();

    for (auto& getter : getters) {
        if (key == getter.name)
            return (this->*getter.function)();
    }

    return false;
}

void WebPreferences::setFeatureEnabled(const API::ExperimentalFeature& feature, bool value)
{
    setExperimentalFeatureEnabledForKey(feature.key(), value);
}

void WebPreferences::setExperimentalFeatureEnabledForKey(const String& key, bool value)
{
    struct FeatureSetterMapping {
        const char* name;
        void (WebPreferences::*function) (const bool&);
    };

    static FeatureSetterMapping setters[] = {
<%- for @pref in @experimentalFeatures do -%>
<%- if @pref.condition -%>
#if <%= @pref.condition %>
<%- end -%>
        { "<%= @pref.name %>", &WebPreferences::set<%= @pref.name %> },
<%- if @pref.condition -%>
#endif
<%- end -%>
<%- end -%>
    };

    for (auto& setter : setters) {
        if (key == setter.name) {
            (this->*setter.function)(value);
            return;
        }
    }
}

void WebPreferences::enableAllExperimentalFeatures()
{
<%- for @pref in @experimentalFeatures do -%>
<%- if @pref.condition -%>
#if <%= @pref.condition %>
<%- end -%>
    set<%= @pref.name %>(true);
<%- if @pref.condition -%>
#endif
<%- end -%>
<%- end -%>
}

}
