/*
 * Copyright (C) 2010, 2011, 2012 Igalia S.L.
 * Copyright (C) 2013 Samsung Electronics
 *
 * 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 "Editing.h"
#include "NotImplemented.h"
#include "Position.h"
#include "Range.h"
#include "RenderListMarker.h"
#include "RenderObject.h"
#include "TextIterator.h"
#include "WebKitAccessibleUtil.h"
#include "WebKitAccessibleWrapperAtk.h"
#include <wtf/text/CString.h>

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

using namespace WebCore;

struct _WebKitAccessibleHyperlinkPrivate {
    WebKitAccessible* hyperlinkImpl;

    // We cache these values so we can return them as const values.
    CString actionName;
    CString actionKeyBinding;
};

#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;

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

    return webkitAccessibleGetAccessibilityObject(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);
    returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE_HYPERLINK(action)->priv->hyperlinkImpl, 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);
    returnValIfWebKitAccessibleIsInvalid(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);
    returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE_HYPERLINK(action)->priv->hyperlinkImpl, 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);

    WebKitAccessibleHyperlinkPrivate* priv = WEBKIT_ACCESSIBLE_HYPERLINK(action)->priv;
    returnValIfWebKitAccessibleIsInvalid(priv->hyperlinkImpl, 0);

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

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

    priv->actionKeyBinding = coreObject->accessKey().string().utf8();
    return priv->actionKeyBinding.data();
}

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);

    WebKitAccessibleHyperlinkPrivate* priv = WEBKIT_ACCESSIBLE_HYPERLINK(action)->priv;
    returnValIfWebKitAccessibleIsInvalid(priv->hyperlinkImpl, 0);

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

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

    priv->actionName = coreObject->actionVerb().utf8();
    return priv->actionName.data();
}

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);
    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);

    returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE_HYPERLINK(link)->priv->hyperlinkImpl, 0);

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

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

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);

    returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE_HYPERLINK(link)->priv->hyperlinkImpl, 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, true);

    // 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 = markerObj->renderer();
    if (!is<RenderListMarker>(renderer))
        return baseLength;

    auto& marker = downcast<RenderListMarker>(*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);
    g_return_val_if_fail(WEBKIT_ACCESSIBLE_HYPERLINK(link)->priv->hyperlinkImpl, 0);
    returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE_HYPERLINK(link)->priv->hyperlinkImpl, 0);

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

    AccessibilityObject* parentUnignored = coreObject->parentObjectUnignored();
    if (!parentUnignored)
        return 0;

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

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

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

static gint webkitAccessibleHyperlinkGetEndIndex(AtkHyperlink* link)
{
    g_return_val_if_fail(WEBKIT_IS_ACCESSIBLE_HYPERLINK(link), 0);
    g_return_val_if_fail(WEBKIT_ACCESSIBLE_HYPERLINK(link)->priv->hyperlinkImpl, 0);
    returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE_HYPERLINK(link)->priv->hyperlinkImpl, 0);

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

    AccessibilityObject* parentUnignored = coreObject->parentObjectUnignored();
    if (!parentUnignored)
        return 0;

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

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

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

static gboolean webkitAccessibleHyperlinkIsValid(AtkHyperlink* link)
{
    g_return_val_if_fail(WEBKIT_IS_ACCESSIBLE_HYPERLINK(link), FALSE);
    g_return_val_if_fail(WEBKIT_ACCESSIBLE_HYPERLINK(link)->priv->hyperlinkImpl, FALSE);
    returnValIfWebKitAccessibleIsInvalid(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);
    returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE_HYPERLINK(link)->priv->hyperlinkImpl, 0);

    return 1;
}

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

    // 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 = nullptr;
}

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)
