/*
 * Copyright (C) 2010 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 "WebKitAccessibleHyperlink.h"

#if HAVE(ACCESSIBILITY)

#include "AXObjectCache.h"
#include "AccessibilityObject.h"
#include "AccessibilityObjectWrapperAtk.h"
#include "AccessibilityRenderObject.h"
#include "NotImplemented.h"
#include "Position.h"
#include "Range.h"
#include "RenderListMarker.h"
#include "RenderObject.h"
#include "TextIterator.h"

#include <atk/atk.h>
#include <glib.h>

using namespace WebCore;

struct _WebKitAccessibleHyperlinkPrivate {
    WebKitAccessible* hyperlinkImpl;
};

#define WEBKIT_ACCESSIBLE_HYPERLINK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), WEBKIT_TYPE_ACCESSIBLE_HYPERLINK, WebKitAccessibleHyperlinkPrivate))

enum {
    PROP_0,

    PROP_HYPERLINK_IMPL
};

static gpointer webkitAccessibleHyperlinkParentClass = 0;

// Used to provide const char* returns.
static const char* returnString(const String& str)
{
    static CString returnedString;
    returnedString = str.utf8();
    return returnedString.data();
}

static AccessibilityObject* core(WebKitAccessible* accessible)
{
    if (!accessible || !WEBKIT_IS_ACCESSIBLE(accessible))
        return 0;

    return webkit_accessible_get_accessibility_object(accessible);
}

static AccessibilityObject* core(WebKitAccessibleHyperlink* link)
{
    if (!link)
        return 0;

    return core(link->priv->hyperlinkImpl);
}

static AccessibilityObject* core(AtkHyperlink* link)
{
    if (!WEBKIT_IS_ACCESSIBLE_HYPERLINK(link))
        return 0;

    return core(WEBKIT_ACCESSIBLE_HYPERLINK(link));
}

static AccessibilityObject* core(AtkAction* action)
{
    return core(WEBKIT_ACCESSIBLE_HYPERLINK(action));
}


static gboolean webkitAccessibleHyperlinkActionDoAction(AtkAction* action, gint index)
{
    g_return_val_if_fail(WEBKIT_IS_ACCESSIBLE_HYPERLINK(action), FALSE);
    g_return_val_if_fail(WEBKIT_ACCESSIBLE_HYPERLINK(action)->priv->hyperlinkImpl, FALSE);
    g_return_val_if_fail(!index, FALSE);

    if (!ATK_IS_ACTION(WEBKIT_ACCESSIBLE_HYPERLINK(action)->priv->hyperlinkImpl))
        return FALSE;

    AccessibilityObject* coreObject = core(action);
    if (!coreObject)
        return FALSE;

    return coreObject->performDefaultAction();
}

static gint webkitAccessibleHyperlinkActionGetNActions(AtkAction* action)
{
    g_return_val_if_fail(WEBKIT_IS_ACCESSIBLE_HYPERLINK(action), 0);
    g_return_val_if_fail(WEBKIT_ACCESSIBLE_HYPERLINK(action)->priv->hyperlinkImpl, 0);

    if (!ATK_IS_ACTION(WEBKIT_ACCESSIBLE_HYPERLINK(action)->priv->hyperlinkImpl))
        return 0;

    return 1;
}

static const gchar* webkitAccessibleHyperlinkActionGetDescription(AtkAction* action, gint index)
{
    g_return_val_if_fail(WEBKIT_IS_ACCESSIBLE_HYPERLINK(action), 0);
    g_return_val_if_fail(WEBKIT_ACCESSIBLE_HYPERLINK(action)->priv->hyperlinkImpl, 0);
    g_return_val_if_fail(!index, 0);

    // TODO: Need a way to provide/localize action descriptions.
    notImplemented();
    return "";
}

static const gchar* webkitAccessibleHyperlinkActionGetKeybinding(AtkAction* action, gint index)
{
    g_return_val_if_fail(WEBKIT_IS_ACCESSIBLE_HYPERLINK(action), 0);
    g_return_val_if_fail(WEBKIT_ACCESSIBLE_HYPERLINK(action)->priv->hyperlinkImpl, 0);
    g_return_val_if_fail(!index, 0);

    if (!ATK_IS_ACTION(WEBKIT_ACCESSIBLE_HYPERLINK(action)->priv->hyperlinkImpl))
        return 0;

    AccessibilityObject* coreObject = core(action);
    if (!coreObject)
        return 0;

    return returnString(coreObject->accessKey().string());
}

static const gchar* webkitAccessibleHyperlinkActionGetName(AtkAction* action, gint index)
{
    g_return_val_if_fail(WEBKIT_IS_ACCESSIBLE_HYPERLINK(action), 0);
    g_return_val_if_fail(WEBKIT_ACCESSIBLE_HYPERLINK(action)->priv->hyperlinkImpl, 0);
    g_return_val_if_fail(!index, 0);

    if (!ATK_IS_ACTION(WEBKIT_ACCESSIBLE_HYPERLINK(action)->priv->hyperlinkImpl))
        return 0;

    AccessibilityObject* coreObject = core(action);
    if (!coreObject)
        return 0;

    return returnString(coreObject->actionVerb());
}

static void atkActionInterfaceInit(AtkActionIface* iface)
{
    iface->do_action = webkitAccessibleHyperlinkActionDoAction;
    iface->get_n_actions = webkitAccessibleHyperlinkActionGetNActions;
    iface->get_description = webkitAccessibleHyperlinkActionGetDescription;
    iface->get_keybinding = webkitAccessibleHyperlinkActionGetKeybinding;
    iface->get_name = webkitAccessibleHyperlinkActionGetName;
}

static gchar* webkitAccessibleHyperlinkGetURI(AtkHyperlink* link, gint index)
{
    g_return_val_if_fail(WEBKIT_IS_ACCESSIBLE_HYPERLINK(link), 0);
    // FIXME: Do NOT support more than one instance of an AtkObject
    // implementing AtkHyperlinkImpl in every instance of AtkHyperLink
    g_return_val_if_fail(!index, 0);

    AccessibilityObject* coreObject = core(link);
    if (!coreObject || coreObject->url().isNull())
        return 0;

    return g_strdup(returnString(coreObject->url().string()));
}

static AtkObject* webkitAccessibleHyperlinkGetObject(AtkHyperlink* link, gint index)
{
    g_return_val_if_fail(WEBKIT_IS_ACCESSIBLE_HYPERLINK(link), 0);
    g_return_val_if_fail(WEBKIT_ACCESSIBLE_HYPERLINK(link)->priv->hyperlinkImpl, 0);

    // FIXME: Do NOT support more than one instance of an AtkObject
    // implementing AtkHyperlinkImpl in every instance of AtkHyperLink
    g_return_val_if_fail(!index, 0);

    return ATK_OBJECT(WEBKIT_ACCESSIBLE_HYPERLINK(link)->priv->hyperlinkImpl);
}

static gint getRangeLengthForObject(AccessibilityObject* obj, Range* range)
{
    // This is going to be the actual length in most of the cases
    int baseLength = TextIterator::rangeLength(range);

    // Check whether the current hyperlink belongs to a list item.
    // If so, we need to consider the length of the item's marker
    AccessibilityObject* parent = obj->parentObjectUnignored();
    if (!parent || !parent->isAccessibilityRenderObject() || !parent->isListItem())
        return baseLength;

    // Even if we don't expose list markers to Assistive
    // Technologies, we need to have a way to measure their length
    // for those cases when it's needed to take it into account
    // separately (as in getAccessibilityObjectForOffset)
    AccessibilityObject* markerObj = parent->firstChild();
    if (!markerObj)
        return baseLength;

    RenderObject* renderer = static_cast<const AccessibilityRenderObject*>(markerObj)->renderer();
    if (!renderer || !renderer->isListMarker())
        return baseLength;

    RenderListMarker* marker = toRenderListMarker(renderer);
    return baseLength + marker->text().length() + marker->suffix().length();
}

static gint webkitAccessibleHyperlinkGetStartIndex(AtkHyperlink* link)
{
    g_return_val_if_fail(WEBKIT_IS_ACCESSIBLE_HYPERLINK(link), 0);

    AccessibilityObject* coreObject = core(link);
    if (!coreObject)
        return 0;

    Node* node = coreObject->node();
    if (!node)
        return 0;

    RefPtr<Range> range = Range::create(node->document(), firstPositionInNode(node->parentNode()), firstPositionInNode(node));
    return getRangeLengthForObject(coreObject, range.get());
}

static gint webkitAccessibleHyperlinkGetEndIndex(AtkHyperlink* link)
{
    g_return_val_if_fail(WEBKIT_IS_ACCESSIBLE_HYPERLINK(link), 0);

    AccessibilityObject* coreObject = core(link);
    if (!coreObject)
        return 0;

    Node* node = coreObject->node();
    if (!node)
        return 0;

    RefPtr<Range> range = Range::create(node->document(), firstPositionInNode(node->parentNode()), lastPositionInNode(node));
    return getRangeLengthForObject(coreObject, range.get());
}

static gboolean webkitAccessibleHyperlinkIsValid(AtkHyperlink* link)
{
    g_return_val_if_fail(WEBKIT_IS_ACCESSIBLE_HYPERLINK(link), 0);
    g_return_val_if_fail(WEBKIT_ACCESSIBLE_HYPERLINK(link)->priv->hyperlinkImpl, FALSE);

    // Link is valid for the whole object's lifetime
    return TRUE;
}

static gint webkitAccessibleHyperlinkGetNAnchors(AtkHyperlink* link)
{
    // FIXME Do NOT support more than one instance of an AtkObject
    // implementing AtkHyperlinkImpl in every instance of AtkHyperLink
    g_return_val_if_fail(WEBKIT_IS_ACCESSIBLE_HYPERLINK(link), 0);
    g_return_val_if_fail(WEBKIT_ACCESSIBLE_HYPERLINK(link)->priv->hyperlinkImpl, 0);
    return 1;
}

static gboolean webkitAccessibleHyperlinkIsSelectedLink(AtkHyperlink* link)
{
    // Not implemented: this function is deprecated in ATK now
    notImplemented();
    return FALSE;
}

static void webkitAccessibleHyperlinkGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* pspec)
{
    switch (propId) {
    case PROP_HYPERLINK_IMPL:
        g_value_set_object(value, WEBKIT_ACCESSIBLE_HYPERLINK(object)->priv->hyperlinkImpl);
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec);
    }
}

static void webkitAccessibleHyperlinkSetProperty(GObject* object, guint propId, const GValue* value, GParamSpec* pspec)
{
    WebKitAccessibleHyperlinkPrivate* priv = WEBKIT_ACCESSIBLE_HYPERLINK(object)->priv;

    switch (propId) {
    case PROP_HYPERLINK_IMPL:
        // No need to check and unref previous values of
        // priv->hyperlinkImpl as this is a CONSTRUCT ONLY property
        priv->hyperlinkImpl = WEBKIT_ACCESSIBLE(g_value_get_object(value));
        g_object_weak_ref(G_OBJECT(priv->hyperlinkImpl), (GWeakNotify)g_object_unref, object);
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec);
    }
}

static void webkitAccessibleHyperlinkFinalize(GObject* object)
{
    G_OBJECT_CLASS(webkitAccessibleHyperlinkParentClass)->finalize(object);
}

static void webkitAccessibleHyperlinkClassInit(AtkHyperlinkClass* klass)
{
    GObjectClass* gobjectClass = G_OBJECT_CLASS(klass);

    webkitAccessibleHyperlinkParentClass = g_type_class_peek_parent(klass);

    gobjectClass->finalize = webkitAccessibleHyperlinkFinalize;
    gobjectClass->set_property = webkitAccessibleHyperlinkSetProperty;
    gobjectClass->get_property = webkitAccessibleHyperlinkGetProperty;

    klass->get_uri = webkitAccessibleHyperlinkGetURI;
    klass->get_object = webkitAccessibleHyperlinkGetObject;
    klass->get_start_index = webkitAccessibleHyperlinkGetStartIndex;
    klass->get_end_index = webkitAccessibleHyperlinkGetEndIndex;
    klass->is_valid = webkitAccessibleHyperlinkIsValid;
    klass->get_n_anchors = webkitAccessibleHyperlinkGetNAnchors;
    klass->is_selected_link = webkitAccessibleHyperlinkIsSelectedLink;

    g_object_class_install_property(gobjectClass, PROP_HYPERLINK_IMPL,
                                    g_param_spec_object("hyperlink-impl",
                                                        "Hyperlink implementation",
                                                        "The associated WebKitAccessible instance.",
                                                        WEBKIT_TYPE_ACCESSIBLE,
                                                        (GParamFlags)(G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)));

    g_type_class_add_private(gobjectClass, sizeof(WebKitAccessibleHyperlinkPrivate));
}

static void webkitAccessibleHyperlinkInit(AtkHyperlink* link)
{
    WEBKIT_ACCESSIBLE_HYPERLINK(link)->priv = WEBKIT_ACCESSIBLE_HYPERLINK_GET_PRIVATE(link);
    WEBKIT_ACCESSIBLE_HYPERLINK(link)->priv->hyperlinkImpl = 0;
}

GType webkitAccessibleHyperlinkGetType()
{
    static volatile gsize typeVolatile = 0;

    if (g_once_init_enter(&typeVolatile)) {
        static const GTypeInfo tinfo = {
            sizeof(WebKitAccessibleHyperlinkClass),
            (GBaseInitFunc) 0,
            (GBaseFinalizeFunc) 0,
            (GClassInitFunc) webkitAccessibleHyperlinkClassInit,
            (GClassFinalizeFunc) 0,
            0, /* class data */
            sizeof(WebKitAccessibleHyperlink), /* instance size */
            0, /* nb preallocs */
            (GInstanceInitFunc) webkitAccessibleHyperlinkInit,
            0 /* value table */
        };

        static const GInterfaceInfo actionInfo = {
            (GInterfaceInitFunc)(GInterfaceInitFunc)atkActionInterfaceInit,
            (GInterfaceFinalizeFunc) 0, 0
        };

        GType type = g_type_register_static(ATK_TYPE_HYPERLINK, "WebKitAccessibleHyperlink", &tinfo, GTypeFlags(0));
        g_type_add_interface_static(type, ATK_TYPE_ACTION, &actionInfo);

        g_once_init_leave(&typeVolatile, type);
    }

    return typeVolatile;
}

WebKitAccessibleHyperlink* webkitAccessibleHyperlinkNew(AtkHyperlinkImpl* hyperlinkImpl)
{
    g_return_val_if_fail(ATK_IS_HYPERLINK_IMPL(hyperlinkImpl), 0);
    return WEBKIT_ACCESSIBLE_HYPERLINK(g_object_new(WEBKIT_TYPE_ACCESSIBLE_HYPERLINK, "hyperlink-impl", hyperlinkImpl, 0));
}

WebCore::AccessibilityObject* webkitAccessibleHyperlinkGetAccessibilityObject(WebKitAccessibleHyperlink* link)
{
    g_return_val_if_fail(WEBKIT_IS_ACCESSIBLE_HYPERLINK(link), 0);
    return core(link);
}

#endif // HAVE(ACCESSIBILITY)
