/*
 * 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 HAVE(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
