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

#if ENABLE(GAMEPAD)

#include "GamepadData.h"
#include "UIGamepad.h"
#include "WebPageProxy.h"
#include "WebProcessPool.h"
#include <WebCore/MockGamepadProvider.h>
#include <WebCore/PlatformGamepad.h>
#include <wtf/NeverDestroyed.h>

namespace WebKit {
using namespace WebCore;

static const Seconds maximumGamepadUpdateInterval { 1_s / 120. };

UIGamepadProvider& UIGamepadProvider::singleton()
{
    static NeverDestroyed<UIGamepadProvider> sharedProvider;
    return sharedProvider;
}

UIGamepadProvider::UIGamepadProvider()
    : m_gamepadSyncTimer(RunLoop::main(), this, &UIGamepadProvider::gamepadSyncTimerFired)
{
    platformSetDefaultGamepadProvider();
}

UIGamepadProvider::~UIGamepadProvider()
{
    if (!m_processPoolsUsingGamepads.isEmpty())
        GamepadProvider::singleton().stopMonitoringGamepads(*this);
}

void UIGamepadProvider::gamepadSyncTimerFired()
{
    auto webPageProxy = platformWebPageProxyForGamepadInput();
    if (!webPageProxy || !m_processPoolsUsingGamepads.contains(&webPageProxy->process().processPool()))
        return;

    webPageProxy->gamepadActivity(snapshotGamepads(), m_shouldMakeGamepadsVisibleOnSync);
    m_shouldMakeGamepadsVisibleOnSync = false;
}

void UIGamepadProvider::scheduleGamepadStateSync()
{
    if (!m_isMonitoringGamepads || m_gamepadSyncTimer.isActive())
        return;

    if (m_gamepads.isEmpty() || m_processPoolsUsingGamepads.isEmpty()) {
        m_gamepadSyncTimer.stop();
        return;
    }

    m_gamepadSyncTimer.startOneShot(maximumGamepadUpdateInterval);
}

void UIGamepadProvider::setInitialConnectedGamepads(const Vector<PlatformGamepad*>& initialGamepads)
{
    ASSERT(!m_hasInitialGamepads);

    m_gamepads.resize(initialGamepads.size());

    for (auto* gamepad : initialGamepads) {
        if (!gamepad)
            continue;
        m_gamepads[gamepad->index()] = makeUnique<UIGamepad>(*gamepad);
    }

    for (auto& pool : m_processPoolsUsingGamepads)
        pool->setInitialConnectedGamepads(m_gamepads);

    m_hasInitialGamepads = true;
}

void UIGamepadProvider::platformGamepadConnected(PlatformGamepad& gamepad)
{
    if (m_gamepads.size() <= gamepad.index())
        m_gamepads.grow(gamepad.index() + 1);

    ASSERT(!m_gamepads[gamepad.index()]);
    m_gamepads[gamepad.index()] = makeUnique<UIGamepad>(gamepad);

    scheduleGamepadStateSync();

    for (auto& pool : m_processPoolsUsingGamepads)
        pool->gamepadConnected(*m_gamepads[gamepad.index()]);
}

void UIGamepadProvider::platformGamepadDisconnected(PlatformGamepad& gamepad)
{
    ASSERT(gamepad.index() < m_gamepads.size());
    ASSERT(m_gamepads[gamepad.index()]);

    std::unique_ptr<UIGamepad> disconnectedGamepad = WTFMove(m_gamepads[gamepad.index()]);

    scheduleGamepadStateSync();

    for (auto& pool : m_processPoolsUsingGamepads)
        pool->gamepadDisconnected(*disconnectedGamepad);
}

void UIGamepadProvider::platformGamepadInputActivity(bool shouldMakeGamepadsVisible)
{
    auto platformGamepads = GamepadProvider::singleton().platformGamepads();
    ASSERT(platformGamepads.size() == m_gamepads.size());

    for (size_t i = 0; i < platformGamepads.size(); ++i) {
        if (!platformGamepads[i]) {
            ASSERT(!m_gamepads[i]);
            continue;
        }

        ASSERT(m_gamepads[i]);
        m_gamepads[i]->updateFromPlatformGamepad(*platformGamepads[i]);
    }

    if (shouldMakeGamepadsVisible)
        m_shouldMakeGamepadsVisibleOnSync = true;

    scheduleGamepadStateSync();
}

void UIGamepadProvider::processPoolStartedUsingGamepads(WebProcessPool& pool)
{
    ASSERT(!m_processPoolsUsingGamepads.contains(&pool));
    m_processPoolsUsingGamepads.add(&pool);

    if (!m_isMonitoringGamepads && platformWebPageProxyForGamepadInput())
        startMonitoringGamepads();
}

void UIGamepadProvider::processPoolStoppedUsingGamepads(WebProcessPool& pool)
{
    ASSERT(m_processPoolsUsingGamepads.contains(&pool));
    m_processPoolsUsingGamepads.remove(&pool);

    if (m_isMonitoringGamepads && !platformWebPageProxyForGamepadInput())
        platformStopMonitoringInput();
}

void UIGamepadProvider::viewBecameActive(WebPageProxy& page)
{
    if (!m_processPoolsUsingGamepads.contains(&page.process().processPool()))
        return;

    if (!m_isMonitoringGamepads)
        startMonitoringGamepads();

    if (platformWebPageProxyForGamepadInput())
        platformStartMonitoringInput();
}

void UIGamepadProvider::viewBecameInactive(WebPageProxy& page)
{
    auto pageForGamepadInput = platformWebPageProxyForGamepadInput();
    if (pageForGamepadInput == &page)
        platformStopMonitoringInput();
}

void UIGamepadProvider::startMonitoringGamepads()
{
    if (m_isMonitoringGamepads)
        return;

    m_isMonitoringGamepads = true;
    ASSERT(!m_processPoolsUsingGamepads.isEmpty());
    GamepadProvider::singleton().startMonitoringGamepads(*this);
}

void UIGamepadProvider::stopMonitoringGamepads()
{
    if (!m_isMonitoringGamepads)
        return;

    m_isMonitoringGamepads = false;

    ASSERT(m_processPoolsUsingGamepads.isEmpty());
    GamepadProvider::singleton().stopMonitoringGamepads(*this);

    m_gamepads.clear();
}

Vector<GamepadData> UIGamepadProvider::snapshotGamepads()
{
    Vector<GamepadData> gamepadDatas;
    gamepadDatas.reserveInitialCapacity(m_gamepads.size());

    for (auto& gamepad : m_gamepads) {
        if (gamepad)
            gamepadDatas.uncheckedAppend(gamepad->condensedGamepadData());
        else
            gamepadDatas.uncheckedAppend({ });
    }

    return gamepadDatas;
}

#if !PLATFORM(COCOA)

void UIGamepadProvider::platformSetDefaultGamepadProvider()
{
    // FIXME: Implement for other platforms
}

WebPageProxy* UIGamepadProvider::platformWebPageProxyForGamepadInput()
{
    // FIXME: Implement for other platforms
    return nullptr;
}

void UIGamepadProvider::platformStopMonitoringInput()
{
}

void UIGamepadProvider::platformStartMonitoringInput()
{
}

#endif // !PLATFORM(MAC)

}

#endif // ENABLE(GAMEPAD)
