/*
 * Copyright (C) 2008, 2009, 2010, 2013 Apple Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#include "config.h"
#include "AccessibilityController.h"

#include "AccessibilityUIElement.h"
#include "DumpRenderTree.h"
#include "FrameLoadDelegate.h"
#include "TestRunner.h"
#include <JavaScriptCore/JSRetainPtr.h>
#include <JavaScriptCore/JSStringRef.h>
#include <JavaScriptCore/JSStringRefBSTR.h>
#include <WebCore/AccessibilityObjectWrapperWin.h>
#include <WebCore/COMPtr.h>
#include <WebKitLegacy/WebKit.h>
#include <comutil.h>
#include <oleacc.h>
#include <string>
#include <wtf/Assertions.h>
#include <wtf/text/AtomicString.h>

using namespace std;

AccessibilityController::AccessibilityController()
    : m_focusEventHook(0)
    , m_scrollingStartEventHook(0)
    , m_valueChangeEventHook(0)
    , m_allEventsHook(0)
    , m_notificationsEventHook(0)
{
}

AccessibilityController::~AccessibilityController()
{
    setLogFocusEvents(false);
    setLogAccessibilityEvents(false);
    setLogValueChangeEvents(false);

    if (m_notificationsEventHook)
        UnhookWinEvent(m_notificationsEventHook);

    for (auto& listener : m_notificationListeners.values())
        JSValueUnprotect(frame->globalContext(), listener);
}

AccessibilityUIElement AccessibilityController::elementAtPoint(int x, int y)
{
    // FIXME: implement
    return 0;
}

static COMPtr<IAccessibleComparable> comparableObject(const COMPtr<IServiceProvider>& serviceProvider)
{
    COMPtr<IAccessibleComparable> comparable;
    serviceProvider->QueryService(SID_AccessibleComparable, __uuidof(IAccessibleComparable), reinterpret_cast<void**>(&comparable));
    return comparable;
}

static COMPtr<IAccessible> findAccessibleObjectById(AccessibilityUIElement parentObject, BSTR idAttribute)
{
    COMPtr<IAccessible> parentIAccessible = parentObject.platformUIElement();

    COMPtr<IServiceProvider> serviceProvider(Query, parentIAccessible);
    if (!serviceProvider)
        return 0;

    COMPtr<IAccessibleComparable> comparable = comparableObject(serviceProvider);
    if (!comparable)
        return 0;

    _variant_t value;
    _bstr_t elementIdAttributeKey(L"AXDRTElementIdAttribute");
    if (SUCCEEDED(comparable->get_attribute(elementIdAttributeKey, &value.GetVARIANT()))) {
        ASSERT(V_VT(&value) == VT_BSTR);
        if (VARCMP_EQ == ::VarBstrCmp(value.bstrVal, idAttribute, LOCALE_USER_DEFAULT, 0))
            return parentIAccessible;
    }

    long childCount = parentObject.childrenCount();
    if (!childCount)
        return nullptr;

    COMPtr<IAccessible> result;
    for (long i = 0; i < childCount; ++i) {
        AccessibilityUIElement childAtIndex = parentObject.getChildAtIndex(i);

        result = findAccessibleObjectById(childAtIndex, idAttribute);
        if (result)
            return result;
    }

    return nullptr;
}

AccessibilityUIElement AccessibilityController::accessibleElementById(JSStringRef id)
{
    AccessibilityUIElement rootAccessibilityUIElement = rootElement();

    _bstr_t idAttribute(JSStringCopyBSTR(id), false);

    COMPtr<IAccessible> result = findAccessibleObjectById(rootAccessibilityUIElement, idAttribute);
    if (result)
        return AccessibilityUIElement(result);

    return 0;
}

AccessibilityUIElement AccessibilityController::focusedElement()
{
    COMPtr<IAccessible> rootAccessible = rootElement().platformUIElement();

    _variant_t vFocus;
    if (FAILED(rootAccessible->get_accFocus(&vFocus.GetVARIANT())))
        return nullptr;

    if (V_VT(&vFocus) == VT_I4) {
        ASSERT(V_I4(&vFocus) == CHILDID_SELF);
        // The root accessible object is the focused object.
        return rootAccessible;
    }

    ASSERT(V_VT(&vFocus) == VT_DISPATCH);
    // We have an IDispatch; query for IAccessible.
    return COMPtr<IAccessible>(Query, V_DISPATCH(&vFocus));
}

AccessibilityUIElement AccessibilityController::rootElement()
{
    COMPtr<IWebView> view;
    if (FAILED(frame->webView(&view)))
        return 0;

    COMPtr<IWebViewPrivate2> viewPrivate(Query, view);
    if (!viewPrivate)
        return 0;

    HWND webViewWindow;
    if (FAILED(viewPrivate->viewWindow(&webViewWindow)))
        return 0;

    // Make sure the layout is up to date, so we can find all accessible elements.
    COMPtr<IWebFramePrivate> framePrivate(Query, frame);
    if (framePrivate)
        framePrivate->layout();

    // Get the root accessible object by querying for the accessible object for the
    // WebView's window.
    COMPtr<IAccessible> rootAccessible;
    if (FAILED(AccessibleObjectFromWindow(webViewWindow, static_cast<DWORD>(OBJID_CLIENT), __uuidof(IAccessible), reinterpret_cast<void**>(&rootAccessible))))
        return 0;

    return rootAccessible;
}

static void CALLBACK logEventProc(HWINEVENTHOOK, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD, DWORD)
{
    // Get the accessible object for this event.
    COMPtr<IAccessible> parentObject;

    _variant_t vChild;

    HRESULT hr = AccessibleObjectFromEvent(hwnd, idObject, idChild, &parentObject, &vChild.GetVARIANT());
    ASSERT(SUCCEEDED(hr));

    // Get the name of the focused element, and log it to stdout.
    _bstr_t nameBSTR;
    hr = parentObject->get_accName(vChild, &nameBSTR.GetBSTR());
    ASSERT(SUCCEEDED(hr));
    wstring name(nameBSTR, nameBSTR.length());

    switch (event) {
        case EVENT_OBJECT_FOCUS:
            fprintf(testResult, "Received focus event for object '%S'.\n", name.c_str());
            break;

        case EVENT_OBJECT_SELECTION:
            fprintf(testResult, "Received selection event for object '%S'.\n", name.c_str());
            break;

        case EVENT_OBJECT_VALUECHANGE: {
            _bstr_t valueBSTR;
            hr = parentObject->get_accValue(vChild, &valueBSTR.GetBSTR());
            ASSERT(SUCCEEDED(hr));
            wstring value(valueBSTR, valueBSTR.length());

            fprintf(testResult, "Received value change event for object '%S', value '%S'.\n", name.c_str(), value.c_str());
            break;
        }

        case EVENT_SYSTEM_SCROLLINGSTART:
            fprintf(testResult, "Received scrolling start event for object '%S'.\n", name.c_str());
            break;

        default:
            fprintf(testResult, "Received unknown event for object '%S'.\n", name.c_str());
            break;
    }
}

void AccessibilityController::setLogFocusEvents(bool logFocusEvents)
{
    if (!!m_focusEventHook == logFocusEvents)
        return;

    if (!logFocusEvents) {
        UnhookWinEvent(m_focusEventHook);
        m_focusEventHook = 0;
        return;
    }

    // Ensure that accessibility is initialized for the WebView by querying for
    // the root accessible object.
    rootElement();

    m_focusEventHook = SetWinEventHook(EVENT_OBJECT_FOCUS, EVENT_OBJECT_FOCUS, GetModuleHandle(0), logEventProc, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT);

    ASSERT(m_focusEventHook);
}

void AccessibilityController::platformResetToConsistentState()
{
}

void AccessibilityController::setLogValueChangeEvents(bool logValueChangeEvents)
{
    if (!!m_valueChangeEventHook == logValueChangeEvents)
        return;

    if (!logValueChangeEvents) {
        UnhookWinEvent(m_valueChangeEventHook);
        m_valueChangeEventHook = 0;
        return;
    }

    // Ensure that accessibility is initialized for the WebView by querying for
    // the root accessible object.
    rootElement();

    m_valueChangeEventHook = SetWinEventHook(EVENT_OBJECT_VALUECHANGE, EVENT_OBJECT_VALUECHANGE, GetModuleHandle(0), logEventProc, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT);

    ASSERT(m_valueChangeEventHook);
}

void AccessibilityController::setLogScrollingStartEvents(bool logScrollingStartEvents)
{
    if (!!m_scrollingStartEventHook == logScrollingStartEvents)
        return;

    if (!logScrollingStartEvents) {
        UnhookWinEvent(m_scrollingStartEventHook);
        m_scrollingStartEventHook = 0;
        return;
    }

    // Ensure that accessibility is initialized for the WebView by querying for
    // the root accessible object.
    rootElement();

    m_scrollingStartEventHook = SetWinEventHook(EVENT_SYSTEM_SCROLLINGSTART, EVENT_SYSTEM_SCROLLINGSTART, GetModuleHandle(0), logEventProc, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT);

    ASSERT(m_scrollingStartEventHook);
}

void AccessibilityController::setLogAccessibilityEvents(bool logAccessibilityEvents)
{
    if (!!m_allEventsHook == logAccessibilityEvents)
        return;

    if (!logAccessibilityEvents) {
        UnhookWinEvent(m_allEventsHook);
        m_allEventsHook = 0;
        return;
    }

    // Ensure that accessibility is initialized for the WebView by querying for
    // the root accessible object.
    rootElement();

    m_allEventsHook = SetWinEventHook(EVENT_MIN, EVENT_MAX, GetModuleHandle(0), logEventProc, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT);

    ASSERT(m_allEventsHook);
}

static string stringEvent(DWORD event)
{
    switch(event) {
        case EVENT_OBJECT_VALUECHANGE:
            return "value change event";
        default:
            return "unknown event";
    }
}

static void CALLBACK notificationListenerProc(HWINEVENTHOOK, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD, DWORD)
{
    // Get the accessible object for this event.
    COMPtr<IAccessible> parentObject;

    _variant_t vChild;
    HRESULT hr = AccessibleObjectFromEvent(hwnd, idObject, idChild, &parentObject, &vChild.GetVARIANT());
    if (FAILED(hr) || !parentObject)
        return;

    COMPtr<IDispatch> childDispatch;
    if (FAILED(parentObject->get_accChild(vChild, &childDispatch)))
        return;

    COMPtr<IAccessible> childAccessible(Query, childDispatch);
    sharedFrameLoadDelegate->accessibilityController()->winNotificationReceived(childAccessible, stringEvent(event));
}

bool AccessibilityController::addNotificationListener(JSObjectRef functionCallback)
{
    return false;
}

void AccessibilityController::removeNotificationListener()
{
}

void AccessibilityController::winNotificationReceived(PlatformUIElement element, const string& eventName)
{
    for (auto& slot : m_notificationListeners) {
        COMPtr<IServiceProvider> thisServiceProvider(Query, slot.key);
        if (!thisServiceProvider)
            continue;

        COMPtr<IAccessibleComparable> thisComparable = comparableObject(thisServiceProvider);
        if (!thisComparable)
            continue;

        COMPtr<IServiceProvider> elementServiceProvider(Query, element);
        if (!elementServiceProvider)
            continue;

        COMPtr<IAccessibleComparable> elementComparable = comparableObject(elementServiceProvider);
        if (!elementComparable)
            continue;

        BOOL isSame = FALSE;
        thisComparable->isSameObject(elementComparable.get(), &isSame);
        if (!isSame)
            continue;

        JSRetainPtr<JSStringRef> jsNotification(Adopt, JSStringCreateWithUTF8CString(eventName.c_str()));
        JSValueRef argument = JSValueMakeString(frame->globalContext(), jsNotification.get());
        JSObjectCallAsFunction(frame->globalContext(), slot.value, 0, 1, &argument, 0);
    }
}

void AccessibilityController::winAddNotificationListener(PlatformUIElement element, JSObjectRef functionCallback)
{
    if (!m_notificationsEventHook)
        m_notificationsEventHook = SetWinEventHook(EVENT_MIN, EVENT_MAX, GetModuleHandle(0), notificationListenerProc, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT);

    JSValueProtect(frame->globalContext(), functionCallback);
    m_notificationListeners.add(element, functionCallback);
}

void AccessibilityController::enableEnhancedAccessibility(bool)
{
    // FIXME: implement
}

bool AccessibilityController::enhancedAccessibilityEnabled()
{
    // FIXME: implement
    return false;
}

JSRetainPtr<JSStringRef> AccessibilityController::platformName() const
{
    JSRetainPtr<JSStringRef> platformName(Adopt, JSStringCreateWithUTF8CString("win"));
    return platformName;
}
