/*
 * Copyright (C) 2012 Google 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. AND ITS CONTRIBUTORS ``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 ITS 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 "PointerLockController.h"

#if ENABLE(POINTER_LOCK)

#include "Chrome.h"
#include "ChromeClient.h"
#include "Element.h"
#include "Event.h"
#include "Page.h"
#include "PlatformMouseEvent.h"
#include "VoidCallback.h"


namespace WebCore {

PointerLockController::PointerLockController(Page& page)
    : m_page(page)
    , m_lockPending(false)
{
}

void PointerLockController::requestPointerLock(Element* target)
{
    if (!target || !target->inDocument() || m_documentOfRemovedElementWhileWaitingForUnlock) {
        enqueueEvent(eventNames().pointerlockerrorEvent, target);
        return;
    }

    if (target->document().isSandboxed(SandboxPointerLock)) {
        // FIXME: This message should be moved off the console once a solution to https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
        target->document().addConsoleMessage(MessageSource::Security, MessageLevel::Error, ASCIILiteral("Blocked pointer lock on an element because the element's frame is sandboxed and the 'allow-pointer-lock' permission is not set."));
        enqueueEvent(eventNames().pointerlockerrorEvent, target);
        return;
    }

    if (m_element) {
        if (&m_element->document() != &target->document()) {
            enqueueEvent(eventNames().pointerlockerrorEvent, target);
            return;
        }
        enqueueEvent(eventNames().pointerlockchangeEvent, target);
        m_element = target;
    } else if (m_page.chrome().client().requestPointerLock()) {
        m_lockPending = true;
        m_element = target;
    } else
        enqueueEvent(eventNames().pointerlockerrorEvent, target);
}

void PointerLockController::requestPointerUnlock()
{
    return m_page.chrome().client().requestPointerUnlock();
}

void PointerLockController::elementRemoved(Element* element)
{
    if (m_element == element) {
        m_documentOfRemovedElementWhileWaitingForUnlock = &m_element->document();
        // Set element null immediately to block any future interaction with it
        // including mouse events received before the unlock completes.
        clearElement();
        requestPointerUnlock();
    }
}

void PointerLockController::documentDetached(Document* document)
{
    if (m_element && &m_element->document() == document) {
        clearElement();
        requestPointerUnlock();
    }
}

bool PointerLockController::lockPending() const
{
    return m_lockPending;
}

Element* PointerLockController::element() const
{
    return m_element.get();
}

void PointerLockController::didAcquirePointerLock()
{
    enqueueEvent(eventNames().pointerlockchangeEvent, m_element.get());
    m_lockPending = false;
}

void PointerLockController::didNotAcquirePointerLock()
{
    enqueueEvent(eventNames().pointerlockerrorEvent, m_element.get());
    clearElement();
}

void PointerLockController::didLosePointerLock()
{
    enqueueEvent(eventNames().pointerlockchangeEvent, m_element ? &m_element->document() : m_documentOfRemovedElementWhileWaitingForUnlock.get());
    clearElement();
    m_documentOfRemovedElementWhileWaitingForUnlock = nullptr;
}

void PointerLockController::dispatchLockedMouseEvent(const PlatformMouseEvent& event, const AtomicString& eventType)
{
    if (!m_element || !m_element->document().frame())
        return;

    m_element->dispatchMouseEvent(event, eventType, event.clickCount());

    // Create click events
    if (eventType == eventNames().mouseupEvent)
        m_element->dispatchMouseEvent(event, eventNames().clickEvent, event.clickCount());
}

void PointerLockController::clearElement()
{
    m_lockPending = false;
    m_element = nullptr;
}

void PointerLockController::enqueueEvent(const AtomicString& type, Element* element)
{
    if (element)
        enqueueEvent(type, &element->document());
}

void PointerLockController::enqueueEvent(const AtomicString& type, Document* document)
{
    if (document)
        document->enqueueDocumentEvent(Event::create(type, true, false));
}

} // namespace WebCore

#endif // ENABLE(POINTER_LOCK)
