/*
 * 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 "HTMLTableCaptionElement.h"
#include "HTMLTableElement.h"
#include "RenderElement.h"
#include <gio/gio.h>
#include <wtf/text/StringBuilder.h>

namespace WebCore {

GDBusInterfaceVTable AccessibilityObjectAtspi::s_tableFunctions = {
    // method_call
    [](GDBusConnection*, const gchar*, const gchar*, const gchar*, const gchar* methodName, GVariant* parameters, GDBusMethodInvocation* invocation, gpointer userData) {
        auto atspiObject = Ref { *static_cast<AccessibilityObjectAtspi*>(userData) };
        atspiObject->updateBackingStore();

        if (!g_strcmp0(methodName, "GetAccessibleAt")) {
            int row, column;
            g_variant_get(parameters, "(ii)", &row, &column);
            auto* cell = row >= 0 && column >= 0 ? atspiObject->cell(row, column) : nullptr;
            g_dbus_method_invocation_return_value(invocation, g_variant_new("(@(so))", cell ? cell->reference() : AccessibilityAtspi::singleton().nullReference()));
        } else if (!g_strcmp0(methodName, "GetIndexAt")) {
            int row, column;
            g_variant_get(parameters, "(ii)", &row, &column);
            g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", row >= 0 && column >= 0 ? atspiObject->cellIndex(row, column).value_or(-1) : -1));
        } else if (!g_strcmp0(methodName, "GetRowAtIndex")) {
            int index;
            g_variant_get(parameters, "(i)", &index);
            g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", index >= 0 ? atspiObject->rowAtIndex(index).value_or(-1) : -1));
        } else if (!g_strcmp0(methodName, "GetColumnAtIndex")) {
            int index;
            g_variant_get(parameters, "(i)", &index);
            g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", index >= 0 ? atspiObject->columnAtIndex(index).value_or(-1) : -1));
        } else if (!g_strcmp0(methodName, "GetRowDescription")) {
            int index;
            g_variant_get(parameters, "(i)", &index);
            g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", index >= 0 ? atspiObject->rowDescription(index).utf8().data() : ""));
        } else if (!g_strcmp0(methodName, "GetColumnDescription")) {
            int index;
            g_variant_get(parameters, "(i)", &index);
            g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", index >= 0 ? atspiObject->columnDescription(index).utf8().data() : ""));
        } else if (!g_strcmp0(methodName, "GetRowExtentAt")) {
            int row, column;
            g_variant_get(parameters, "(ii)", &row, &column);
            g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", row >= 0 && column >= 0 ? atspiObject->rowExtent(row, column) : -1));
        } else if (!g_strcmp0(methodName, "GetColumnExtentAt")) {
            int row, column;
            g_variant_get(parameters, "(ii)", &row, &column);
            g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", row >= 0 && column >= 0 ? atspiObject->columnExtent(row, column) : -1));
        } else if (!g_strcmp0(methodName, "GetRowHeader")) {
            int row;
            g_variant_get(parameters, "(i)", &row);
            auto* header = row >= 0 ? atspiObject->rowHeader(row) : nullptr;
            g_dbus_method_invocation_return_value(invocation, g_variant_new("(@(so))", header ? header->reference() : AccessibilityAtspi::singleton().nullReference()));
        } else if (!g_strcmp0(methodName, "GetColumnHeader")) {
            int column;
            g_variant_get(parameters, "(i)", &column);
            auto* header = column >= 0 ? atspiObject->columnHeader(column) : nullptr;
            g_dbus_method_invocation_return_value(invocation, g_variant_new("(@(so))", header ? header->reference() : AccessibilityAtspi::singleton().nullReference()));
        } else if (!g_strcmp0(methodName, "GetRowColumnExtentsAtIndex")) {
            int index;
            g_variant_get(parameters, "(i)", &index);
            if (index < 0) {
                g_dbus_method_invocation_return_value(invocation, g_variant_new("(biiiib)", FALSE, -1, -1, -1, -1, FALSE));
                return;
            }

            auto row = atspiObject->rowAtIndex(index);
            auto column = atspiObject->columnAtIndex(index);
            auto* cell = atspiObject->m_coreObject ? atspiObject->m_coreObject->cellForColumnAndRow(*column, *row) : nullptr;
            g_dbus_method_invocation_return_value(invocation, g_variant_new("(biiiib)", cell && cell->isTableCell() ? TRUE : FALSE,
                row.value_or(-1), column.value_or(-1), row && column ? atspiObject->rowExtent(*row, *column) : -1,
                row && column ? atspiObject->columnExtent(*row, *column) : -1, FALSE));
        } else if (!g_strcmp0(methodName, "GetSelectedRows")
            || !g_strcmp0(methodName, "GetSelectedColumns")
            || !g_strcmp0(methodName, "IsRowSelected")
            || !g_strcmp0(methodName, "IsColumnSelected")
            || !g_strcmp0(methodName, "IsSelected")
            || !g_strcmp0(methodName, "AddRowSelection")
            || !g_strcmp0(methodName, "AddColumnSelection")
            || !g_strcmp0(methodName, "RemoveRowSelection")
            || !g_strcmp0(methodName, "RemoveColumnSelection"))
            g_dbus_method_invocation_return_error_literal(invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "");
    },
    // get_property
    [](GDBusConnection*, const gchar*, const gchar*, const gchar*, const gchar* propertyName, GError** error, gpointer userData) -> GVariant* {
        auto atspiObject = Ref { *static_cast<AccessibilityObjectAtspi*>(userData) };
        atspiObject->updateBackingStore();

        if (!g_strcmp0(propertyName, "NRows"))
            return g_variant_new_int32(atspiObject->rowCount());
        if (!g_strcmp0(propertyName, "NColumns"))
            return g_variant_new_int32(atspiObject->columnCount());
        if (!g_strcmp0(propertyName, "Caption")) {
            auto* caption = atspiObject->tableCaption();
            return caption ? caption->reference() : AccessibilityAtspi::singleton().nullReference();
        }
        if (!g_strcmp0(propertyName, "Summary"))
            return AccessibilityAtspi::singleton().nullReference();
        if (!g_strcmp0(propertyName, "NSelectedRows"))
            return g_variant_new_int32(0);
        if (!g_strcmp0(propertyName, "NSelectedColumns"))
            return g_variant_new_int32(0);

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

unsigned AccessibilityObjectAtspi::rowCount() const
{
    return m_coreObject ? m_coreObject->rowCount() : 0;
}

unsigned AccessibilityObjectAtspi::columnCount() const
{
    return m_coreObject ? m_coreObject->columnCount() : 0;
}

AccessibilityObjectAtspi* AccessibilityObjectAtspi::cell(unsigned row, unsigned column) const
{
    if (!m_coreObject)
        return nullptr;

    if (auto* tableCell = m_coreObject->cellForColumnAndRow(column, row))
        return tableCell->wrapper();

    return nullptr;
}

AccessibilityObjectAtspi* AccessibilityObjectAtspi::tableCaption() const
{
    if (!m_coreObject)
        return nullptr;

    if (auto* node = m_coreObject->node()) {
        if (!is<HTMLTableElement>(node))
            return nullptr;

        if (auto caption = downcast<HTMLTableElement>(*node).caption()) {
            if (auto* renderer = caption->renderer()) {
                if (auto* element = AccessibilityObject::firstAccessibleObjectFromNode(renderer->element()))
                    return element->wrapper();
            }
        }
    }

    return nullptr;
}

std::optional<unsigned> AccessibilityObjectAtspi::cellIndex(unsigned row, unsigned column) const
{
    if (!m_coreObject)
        return std::nullopt;

    auto* cell = m_coreObject->cellForColumnAndRow(column, row);
    if (!cell)
        return std::nullopt;

    auto cells = m_coreObject->cells();
    AXCoreObject::AccessibilityChildrenVector::iterator position;
    position = std::find(cells.begin(), cells.end(), cell);
    if (position == cells.end())
        return std::nullopt;
    return position - cells.begin();
}

std::optional<unsigned> AccessibilityObjectAtspi::rowAtIndex(unsigned index) const
{
    if (!m_coreObject)
        return std::nullopt;

    auto cells = m_coreObject->cells();
    if (index >= cells.size())
        return std::nullopt;

    return cells[index]->rowIndexRange().first;
}

std::optional<unsigned> AccessibilityObjectAtspi::columnAtIndex(unsigned index) const
{
    if (!m_coreObject)
        return std::nullopt;

    auto cells = m_coreObject->cells();
    if (index >= cells.size())
        return std::nullopt;

    return cells[index]->columnIndexRange().first;
}

AccessibilityObjectAtspi* AccessibilityObjectAtspi::rowHeader(unsigned row) const
{
    if (!m_coreObject)
        return nullptr;

    auto headers = m_coreObject->rowHeaders();
    for (const auto& header : headers) {
        auto range = header->rowIndexRange();
        if (range.first <= row && row < range.first + range.second) {
            if (auto* wrapper = header->wrapper())
                return wrapper;
        }
    }

    return nullptr;
}

AccessibilityObjectAtspi* AccessibilityObjectAtspi::columnHeader(unsigned column) const
{
    if (!m_coreObject)
        return nullptr;

    auto headers = m_coreObject->columnHeaders();
    for (const auto& header : headers) {
        auto range = header->columnIndexRange();
        if (range.first <= column && column < range.first + range.second) {
            if (auto* wrapper = header->wrapper())
                return wrapper;
        }
    }

    return nullptr;
}

String AccessibilityObjectAtspi::rowDescription(unsigned row) const
{
    if (!m_coreObject)
        return { };

    StringBuilder builder;
    bool isFirst = true;
    auto headers = m_coreObject->rowHeaders();
    for (const auto& header : headers) {
        auto* wrapper = header->wrapper();
        if (!wrapper)
            continue;

        auto range = header->rowIndexRange();
        if (range.first <= row && row < range.first + range.second) {
            wrapper->updateBackingStore();
            auto text = wrapper->text();
            if (text.isEmpty())
                continue;

            if (!isFirst)
                builder.append(' ');
            else
                isFirst = false;
            builder.append(text);
        }
    }
    return builder.toString();
}

String AccessibilityObjectAtspi::columnDescription(unsigned column) const
{
    if (!m_coreObject)
        return { };

    StringBuilder builder;
    bool isFirst = true;
    auto headers = m_coreObject->columnHeaders();
    for (const auto& header : headers) {
        auto* wrapper = header->wrapper();
        if (!wrapper)
            continue;

        auto range = header->columnIndexRange();
        if (range.first <= column && column < range.first + range.second) {
            wrapper->updateBackingStore();
            auto text = wrapper->text();
            if (text.isEmpty())
                continue;

            if (!isFirst)
                builder.append(' ');
            else
                isFirst = false;
            builder.append(text);
        }
    }
    return builder.toString();
}

unsigned AccessibilityObjectAtspi::rowExtent(unsigned row, unsigned column) const
{
    if (!m_coreObject)
        return 0;

    auto* cell = m_coreObject->cellForColumnAndRow(column, row);
    return cell ? cell->rowIndexRange().second : 0;
}

unsigned AccessibilityObjectAtspi::columnExtent(unsigned row, unsigned column) const
{
    if (!m_coreObject)
        return 0;

    auto* cell = m_coreObject->cellForColumnAndRow(column, row);
    return cell ? cell->columnIndexRange().second : 0;
}

Vector<RefPtr<AccessibilityObjectAtspi>> AccessibilityObjectAtspi::cells() const
{
    if (!m_coreObject)
        return { };

    return wrapperVector(m_coreObject->cells());
}

Vector<RefPtr<AccessibilityObjectAtspi>> AccessibilityObjectAtspi::rows() const
{
    if (!m_coreObject)
        return { };

    return wrapperVector(m_coreObject->rows());
}

Vector<RefPtr<AccessibilityObjectAtspi>> AccessibilityObjectAtspi::rowHeaders() const
{
    if (!m_coreObject)
        return { };

    return wrapperVector(m_coreObject->rowHeaders());
}

Vector<RefPtr<AccessibilityObjectAtspi>> AccessibilityObjectAtspi::columnHeaders() const
{
    if (!m_coreObject)
        return { };

    return wrapperVector(m_coreObject->columnHeaders());
}

} // namespace WebCore

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