/*
 * Copyright (C) 2010, 2011, 2012 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 "WebKitAccessibleInterfaceHypertext.h"

#if ENABLE(ACCESSIBILITY)

#include "AccessibilityObject.h"
#include "WebKitAccessible.h"
#include "WebKitAccessibleUtil.h"

using namespace WebCore;

static AccessibilityObject* core(AtkHypertext* hypertext)
{
    if (!WEBKIT_IS_ACCESSIBLE(hypertext))
        return 0;

    return &webkitAccessibleGetAccessibilityObject(WEBKIT_ACCESSIBLE(hypertext));
}

static AtkHyperlink* webkitAccessibleHypertextGetLink(AtkHypertext* hypertext, gint index)
{
    g_return_val_if_fail(ATK_HYPERTEXT(hypertext), 0);
    returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(hypertext), 0);

    const AccessibilityObject::AccessibilityChildrenVector& children = core(hypertext)->children();
    if (index < 0 || static_cast<unsigned>(index) >= children.size())
        return 0;

    gint currentLink = -1;
    for (const auto& child : children) {
        AccessibilityObject* coreChild = child.get();
        if (!coreChild->accessibilityIsIgnored()) {
            auto* axObject = coreChild->wrapper();
            if (!axObject || !ATK_IS_HYPERLINK_IMPL(axObject))
                continue;

            currentLink++;
            if (index != currentLink)
                continue;

            return atk_hyperlink_impl_get_hyperlink(ATK_HYPERLINK_IMPL(axObject));
        }
    }

    return 0;
}

static gint webkitAccessibleHypertextGetNLinks(AtkHypertext* hypertext)
{
    g_return_val_if_fail(ATK_HYPERTEXT(hypertext), 0);
    returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(hypertext), 0);

    const AccessibilityObject::AccessibilityChildrenVector& children = core(hypertext)->children();
    gint linksFound = 0;
    for (const auto& child : children) {
        AccessibilityObject* coreChild = child.get();
        if (!coreChild->accessibilityIsIgnored()) {
            auto* axObject = coreChild->wrapper();
            if (axObject && ATK_IS_HYPERLINK_IMPL(axObject))
                linksFound++;
        }
    }

    return linksFound;
}

static gint webkitAccessibleHypertextGetLinkIndex(AtkHypertext* hypertext, gint charIndex)
{
    g_return_val_if_fail(ATK_HYPERTEXT(hypertext), -1);
    returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(hypertext), -1);

    size_t linksCount = webkitAccessibleHypertextGetNLinks(hypertext);
    if (!linksCount)
        return -1;

    for (size_t i = 0; i < linksCount; i++) {
        AtkHyperlink* hyperlink = ATK_HYPERLINK(webkitAccessibleHypertextGetLink(hypertext, i));
        gint startIndex = atk_hyperlink_get_start_index(hyperlink);
        gint endIndex = atk_hyperlink_get_end_index(hyperlink);

        // Check if the char index in the link's offset range
        if (startIndex <= charIndex && charIndex < endIndex)
            return i;
    }

    // Not found if reached
    return -1;
}

void webkitAccessibleHypertextInterfaceInit(AtkHypertextIface* iface)
{
    iface->get_link = webkitAccessibleHypertextGetLink;
    iface->get_n_links = webkitAccessibleHypertextGetNLinks;
    iface->get_link_index = webkitAccessibleHypertextGetLinkIndex;
}

#endif
