/*
 * Copyright (C) 2008 Nuanti Ltd.
 * Copyright (C) 2009 Jan Alonzo
 * Copyright (C) 2011, 2012 Igalia S.L.
 *
 * Portions from Mozilla a11y, copyright as follows:
 *
 * The Original Code is mozilla.org code.
 *
 * The Initial Developer of the Original Code is
 * Sun Microsystems, Inc.
 * Portions created by the Initial Developer are Copyright (C) 2002
 * the Initial Developer. All Rights Reserved.
 *
 * 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 "WebKitAccessibleInterfaceEditableText.h"

#if HAVE(ACCESSIBILITY)

#include "AccessibilityObject.h"
#include "Document.h"
#include "Editor.h"
#include "Frame.h"
#include "NotImplemented.h"
#include "WebKitAccessibleUtil.h"
#include "WebKitAccessibleWrapperAtk.h"

using namespace WebCore;

static AccessibilityObject* core(AtkEditableText* text)
{
    if (!WEBKIT_IS_ACCESSIBLE(text))
        return 0;

    return webkitAccessibleGetAccessibilityObject(WEBKIT_ACCESSIBLE(text));
}

static gboolean webkitAccessibleEditableTextSetRunAttributes(AtkEditableText* text, AtkAttributeSet*, gint, gint)
{
    g_return_val_if_fail(ATK_IS_EDITABLE_TEXT(text), FALSE);
    returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(text), FALSE);

    notImplemented();
    return FALSE;
}

static void webkitAccessibleEditableTextSetTextContents(AtkEditableText* text, const gchar* string)
{
    g_return_if_fail(ATK_IS_EDITABLE_TEXT(text));
    returnIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(text));

    // FIXME: string nullcheck?
    core(text)->setValue(String::fromUTF8(string));
}

static void webkitAccessibleEditableTextInsertText(AtkEditableText* text, const gchar* string, gint length, gint* position)
{
    g_return_if_fail(ATK_IS_EDITABLE_TEXT(text));
    returnIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(text));

    if (!string)
        return;

    AccessibilityObject* coreObject = core(text);
    // FIXME: Not implemented in WebCore
    // coreObject->setSelectedTextRange(PlainTextRange(*position, 0));
    // coreObject->setSelectedText(String::fromUTF8(string));

    Document* document = coreObject->document();
    if (!document || !document->frame())
        return;

    coreObject->setSelectedVisiblePositionRange(coreObject->visiblePositionRangeForRange(PlainTextRange(*position, 0)));
    coreObject->setFocused(true);
    // FIXME: We should set position to the actual inserted text length, which may be less than that requested.
    if (document->frame()->editor().insertTextWithoutSendingTextEvent(String::fromUTF8(string).substring(0, length), false, 0))
        *position += length;
}

static void webkitAccessibleEditableTextCopyText(AtkEditableText* text, gint, gint)
{
    g_return_if_fail(ATK_IS_EDITABLE_TEXT(text));
    returnIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(text));

    notImplemented();
}

static void webkitAccessibleEditableTextCutText(AtkEditableText* text, gint, gint)
{
    g_return_if_fail(ATK_IS_EDITABLE_TEXT(text));
    returnIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(text));

    notImplemented();
}

static void webkitAccessibleEditableTextDeleteText(AtkEditableText* text, gint startPos, gint endPos)
{
    g_return_if_fail(ATK_IS_EDITABLE_TEXT(text));
    returnIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(text));

    AccessibilityObject* coreObject = core(text);
    // FIXME: Not implemented in WebCore
    // coreObject->setSelectedTextRange(PlainTextRange(startPos, endPos - startPos));
    // coreObject->setSelectedText(String());

    Document* document = coreObject->document();
    if (!document || !document->frame())
        return;

    coreObject->setSelectedVisiblePositionRange(coreObject->visiblePositionRangeForRange(PlainTextRange(startPos, endPos - startPos)));
    coreObject->setFocused(true);
    document->frame()->editor().performDelete();
}

static void webkitAccessibleEditableTextPasteText(AtkEditableText* text, gint)
{
    g_return_if_fail(ATK_IS_EDITABLE_TEXT(text));
    returnIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(text));

    notImplemented();
}

void webkitAccessibleEditableTextInterfaceInit(AtkEditableTextIface* iface)
{
    iface->set_run_attributes = webkitAccessibleEditableTextSetRunAttributes;
    iface->set_text_contents = webkitAccessibleEditableTextSetTextContents;
    iface->insert_text = webkitAccessibleEditableTextInsertText;
    iface->copy_text = webkitAccessibleEditableTextCopyText;
    iface->cut_text = webkitAccessibleEditableTextCutText;
    iface->delete_text = webkitAccessibleEditableTextDeleteText;
    iface->paste_text = webkitAccessibleEditableTextPasteText;
}

#endif
