// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only

#include "qopenxrcontroller_p.h"
#include "qopenxrinputmanager_p.h"

#include "qopenxrview_p.h"

QT_BEGIN_NAMESPACE

QOpenXRController::QOpenXRController()
{
    m_inputManager = QOpenXRInputManager::instance();
}

QOpenXRController::Controller QOpenXRController::controller() const
{
    return m_controller;
}

void QOpenXRController::setController(QOpenXRController::Controller newController)
{
    if (m_controller == newController)
        return;
    m_controller = newController;
    emit controllerChanged();
    emit handInputChanged();

    disconnect(m_posePositionConnection);
    disconnect(m_poseRotationConnection);
    disconnect(m_isActiveConnection);
    disconnect(m_inputActionConnection);

    auto *input = handInput();
    if (input) {
        setPosition(input->posePosition());
        setRotation(input->poseRotation());
        setVisible(input->isActive());

        m_posePositionConnection = connect(input, &QOpenXRHandInput::posePositionChanged, this, [this, input]{
            setPosition(input->posePosition());
        });
        m_poseRotationConnection = connect(input, &QOpenXRHandInput::poseRotationChanged, this, [this, input]{
            setRotation(input->poseRotation());
        });
        m_isActiveConnection = connect(input, &QOpenXRHandInput::isActiveChanged, this, [this, input]{
            setVisible(input->isActive());
        });
        m_inputActionConnection = connect(input, &QOpenXRHandInput::inputValueChange,
                                          this, [this](int id, const char *shortName, float value) {
                                              if (m_actionMapper)
                                                  m_actionMapper->handleInput(QOpenXRActionMapper::InputAction(id), shortName, value);
                                          });
    } else {
        setVisible(false);
        //TODO handle gamepad connections
    }
}

QOpenXRHandInput *QOpenXRController::handInput() const
{
    if (m_controller == ControllerRight)
        return m_inputManager->rightHandInput();
    else if (m_controller == ControllerLeft)
        return m_inputManager->leftHandInput();
    return nullptr;
}

QOpenXRGamepadInput *QOpenXRController::gamepadInput() const
{
    return m_inputManager->gamepadInput();
}

QOpenXRActionMapper *QOpenXRController::actionMapper() const
{
    return m_actionMapper;
}

void QOpenXRController::setActionMapper(QOpenXRActionMapper *newActionMapper)
{
    if (m_actionMapper == newActionMapper)
        return;

    if (m_actionMapperConnection) {
        QObject::disconnect(m_actionMapperConnection);
        m_actionMapperConnection = {};
    }

    if (newActionMapper)
        m_actionMapperConnection = QObject::connect(newActionMapper, &QObject::destroyed, this, [this](QObject *destroyedMapper) {
            if (m_actionMapper == destroyedMapper) {
                m_actionMapper = nullptr;
                emit actionMapperChanged();
            }
        });

    m_actionMapper = newActionMapper;
    emit actionMapperChanged();
}

QT_END_NAMESPACE
