/******************************************************************************
 * File: QXRCoreClient.hpp
 * Copyright (c) 2022 Qualcomm Technologies, Inc. and/or its subsidiaries. All rights reserved.
 *
 * Confidential and Proprietary - Qualcomm Technologies, Inc.
 *
 ******************************************************************************/

#pragma once

#include <cassert>
#include <memory>

#include "QXRCoreClient.h"

namespace wikitude::openxr {

    class QXRCoreClient {
    public:
        QXRCoreClient(const QXRCoreClient& other_) = delete;

        QXRCoreClient& operator=(const QXRCoreClient& other_) = delete;

        ~QXRCoreClient();

        static std::unique_ptr<QXRCoreClient> create(JavaVM* javaVM_, jobject context_);

        qvrservice_client_helper_t* getHandle() {
            return _qvrServiceClient;
        }

        int32_t getParameter(const char* parameterName_, std::string& result_) const;

        // RegisterForNotification(QVRSERVICE_CLIENT_NOTIFICATION notification, notification_callback_fn cb, void *pCtx)

        QVRSERVICE_VRMODE_STATE getVRMode() const;

        int32_t getTrackingMode(QVRSERVICE_TRACKING_MODE& currentMode_) const;
        int32_t getTrackingMode(QVRSERVICE_TRACKING_MODE& currentMode_, uint32_t& supportedModes_) const;

        int32_t getHistoricalHeadTrackingData(qvrservice_head_tracking_data_t*& data_, int64_t timeStampNs_) const;
        // GetHeadTrackingData(qvrservice_head_tracking_data_t **ppData)
        // GetFramePose(XrFramePoseQTI** ppData)

        // SetTransformationMatrix(QVRSERVICE_TRANSFORMATION_MATRIX_TYPE type, float mat4x4[16])
        // GetHwTransforms(uint32_t *pnTransforms, qvrservice_hw_transform_t transforms[])
        // GetHwTransform(qvrservice_hw_transform_t *transform)

    private:
        QXRCoreClient(qvrservice_client_helper_t* qvrServiceClient_);

        qvrservice_client_helper_t* _qvrServiceClient;
    };

    inline QXRCoreClient::~QXRCoreClient() {
        QVRServiceClient_Destroy(_qvrServiceClient);
    }

    inline std::unique_ptr<QXRCoreClient> QXRCoreClient::create(JavaVM* javaVM_, jobject context_) {
        auto qvrServiceClient = QXRCoreClient_Create(javaVM_, context_, "com.qualcomm.qti.spaces.services");

        return qvrServiceClient ? std::unique_ptr<QXRCoreClient>(new QXRCoreClient(qvrServiceClient)) : nullptr;
    }

    inline int32_t QXRCoreClient::getParameter(const char* parameterName_, std::string& result_) const {
        uint32_t length;
        int32_t resultCode = QVRServiceClient_GetParam(_qvrServiceClient, parameterName_, &length, NULL);

        if (resultCode == QVR_SUCCESS) {
            result_.resize(length);

            resultCode = QVRServiceClient_GetParam(_qvrServiceClient, parameterName_, &length, result_.data());

            if (resultCode == QVR_SUCCESS) {
                auto endPosition = result_.find('\0');

                if (endPosition != std::string::npos) {
                    result_.resize(endPosition);
                }
            }
        }

        return resultCode;
    }

    inline QVRSERVICE_VRMODE_STATE QXRCoreClient::getVRMode() const {
        return QVRServiceClient_GetVRMode(_qvrServiceClient);
    }

    inline int32_t QXRCoreClient::getTrackingMode(QVRSERVICE_TRACKING_MODE& currentMode_) const {
        return QVRServiceClient_GetTrackingMode(_qvrServiceClient, &currentMode_, NULL);
    }

    inline int32_t QXRCoreClient::getTrackingMode(QVRSERVICE_TRACKING_MODE& currentMode_, uint32_t& supportedModes_) const {
        return QVRServiceClient_GetTrackingMode(_qvrServiceClient, &currentMode_, &supportedModes_);
    }

    inline int32_t QXRCoreClient::getHistoricalHeadTrackingData(qvrservice_head_tracking_data_t*& data_, int64_t timeStampNs_) const {
        return QVRServiceClient_GetHistoricalHeadTrackingData(_qvrServiceClient, &data_, timeStampNs_);
    }

    inline QXRCoreClient::QXRCoreClient(qvrservice_client_helper_t* qvrServiceClient_)
        : _qvrServiceClient(qvrServiceClient_) {
        assert(qvrServiceClient_);
    }

}
