/*
 * Copyright (C) 2021 Igalia S.L.
 *
 * 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 "AccessibilityObjectAtspi.h"

#if ENABLE(ACCESSIBILITY) && USE(ATSPI)

#include "AccessibilityAtspi.h"
#include "AccessibilityObject.h"
#include <gio/gio.h>

namespace WebCore {

GDBusInterfaceVTable AccessibilityObjectAtspi::s_valueFunctions = {
    // method_call
    nullptr,
    // get_property
    [](GDBusConnection*, const gchar*, const gchar*, const gchar*, const gchar* propertyName, GError** error, gpointer userData) -> GVariant* {
        RELEASE_ASSERT(!isMainThread());
        auto atspiObject = Ref { *static_cast<AccessibilityObjectAtspi*>(userData) };
        atspiObject->updateBackingStore();

        if (!g_strcmp0(propertyName, "CurrentValue"))
            return g_variant_new_double(atspiObject->currentValue());
        if (!g_strcmp0(propertyName, "MinimumValue"))
            return g_variant_new_double(atspiObject->minimumValue());
        if (!g_strcmp0(propertyName, "MaximumValue"))
            return g_variant_new_double(atspiObject->maximumValue());
        if (!g_strcmp0(propertyName, "MinimumIncrement"))
            return g_variant_new_double(atspiObject->minimumIncrement());

        g_set_error(error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "Unknown property '%s'", propertyName);
        return nullptr;
    },
    // set_property,
    [](GDBusConnection*, const gchar*, const gchar*, const gchar*, const gchar* propertyName, GVariant* propertyValue, GError** error, gpointer userData) -> gboolean {
        RELEASE_ASSERT(!isMainThread());
        auto atspiObject = Ref { *static_cast<AccessibilityObjectAtspi*>(userData) };
        atspiObject->updateBackingStore();

        if (!g_strcmp0(propertyName, "CurrentValue"))
            return atspiObject->setCurrentValue(g_variant_get_double(propertyValue));

        g_set_error(error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "Unknown property '%s'", propertyName);
        return FALSE;
    },
    // padding
    nullptr
};

double AccessibilityObjectAtspi::currentValue() const
{
    RELEASE_ASSERT(!isMainThread());
    if (!m_axObject)
        return 0;

    return m_axObject->valueForRange();
}

bool AccessibilityObjectAtspi::setCurrentValue(double value)
{
    return Accessibility::retrieveValueFromMainThread<bool>([this, value]() -> bool {
        if (m_coreObject)
            m_coreObject->updateBackingStore();

        if (!m_coreObject)
            return false;

        if (!m_coreObject->canSetValueAttribute())
            return false;

        if (m_coreObject->canSetNumericValue())
            return m_coreObject->setValue(value);

        return m_coreObject->setValue(String::numberToStringFixedPrecision(value));
    });
}

double AccessibilityObjectAtspi::minimumValue() const
{
    RELEASE_ASSERT(!isMainThread());
    if (!m_axObject)
        return 0;

    return m_axObject->minValueForRange();
}

double AccessibilityObjectAtspi::maximumValue() const
{
    RELEASE_ASSERT(!isMainThread());
    if (!m_axObject)
        return 0;

    return m_axObject->maxValueForRange();
}

double AccessibilityObjectAtspi::minimumIncrement() const
{
    return Accessibility::retrieveValueFromMainThread<float>([this]() -> float {
        if (m_coreObject)
            m_coreObject->updateBackingStore();

        if (!m_coreObject)
            return 0;

        auto stepAttribute = static_cast<AccessibilityObject*>(m_coreObject)->getAttribute(HTMLNames::stepAttr);
        if (!stepAttribute.isEmpty())
            return stepAttribute.toFloat();

        // If 'step' attribute is not defined, WebCore assumes a 5% of the range between
        // minimum and maximum values. Implicit value of step should be one or larger.
        float step = (m_coreObject->maxValueForRange() - m_coreObject->minValueForRange()) * 0.05;
        return step < 1 ? 1 : step;
    });
}

void AccessibilityObjectAtspi::valueChanged(double value)
{
    RELEASE_ASSERT(isMainThread());
    AccessibilityAtspi::singleton().valueChanged(*this, value);
}

} // namespace WebCore

#endif // ENABLE(ACCESSIBILITY) && USE(ATSPI)
