/*
 * THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT EDIT.
 *
 * 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 -%>
<%- if @pref.visibleCondition -%>
#if <%= @pref.visibleCondition %>
<%- end -%>
        API::ExperimentalFeature::create(<%= @pref.humanReadableName %>, "<%= @pref.name %>", <%= @pref.humanReadableDescription %>, <%= @pref.defaultValue %>),
<%- if @pref.visibleCondition -%>
#endif
<%- end -%>
<%- if @pref.condition -%>
#endif
<%- end -%>
<%- end -%>
    });

    return features;
}

bool WebPreferences::isEnabledForFeature(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::setEnabledForFeature(bool value, const API::ExperimentalFeature& feature)
{
    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 -%>
    };

    const String& key = feature.key();
    
    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 -%>
}

}
