void AppStage_ComputeTrackerPoses::handle_tracker_list_response(
    const ClientPSMoveAPI::ResponseMessage *response_message,
    void *userdata)
{
    AppStage_ComputeTrackerPoses *thisPtr = static_cast<AppStage_ComputeTrackerPoses *>(userdata);

    switch (response_message->result_code)
    {
    case ClientPSMoveAPI::_clientPSMoveResultCode_ok:
        {
            assert(response_message->payload_type == ClientPSMoveAPI::_responsePayloadType_TrackerList);
            const ClientPSMoveAPI::ResponsePayload_TrackerList &tracker_list = response_message->payload.tracker_list;

            for (int tracker_index = 0; tracker_index < tracker_list.count; ++tracker_index)
            {
                const ClientTrackerInfo *TrackerInfo = &tracker_list.trackers[tracker_index];

                thisPtr->request_tracker_start_stream(TrackerInfo, tracker_index);
            }
        } break;

    case ClientPSMoveAPI::_clientPSMoveResultCode_error:
    case ClientPSMoveAPI::_clientPSMoveResultCode_canceled:
        {
            thisPtr->setState(eMenuState::failedTrackerListRequest);
        } break;
    }
}
void AppStage_ComputeTrackerPoses::handle_start_controller_response(
    const ClientPSMoveAPI::ResponseMessage *response_message,
    void *userdata)
{
    AppStage_ComputeTrackerPoses *thisPtr = static_cast<AppStage_ComputeTrackerPoses *>(userdata);

    const ClientPSMoveAPI::eClientPSMoveResultCode ResultCode = response_message->result_code;

    switch (ResultCode)
    {
    case ClientPSMoveAPI::_clientPSMoveResultCode_ok:
        {
			// See if this was the last controller we were waiting to get a response from
			--thisPtr->m_pendingControllerStartCount;
			if (thisPtr->m_pendingControllerStartCount <= 0)
			{
				// Move on to the controllers
				thisPtr->request_tracker_list();
			}
        } break;

    case ClientPSMoveAPI::_clientPSMoveResultCode_error:
    case ClientPSMoveAPI::_clientPSMoveResultCode_canceled:
        {
            thisPtr->setState(AppStage_ComputeTrackerPoses::failedControllerStartRequest);
        } break;
    }
}
void AppStage_ComputeTrackerPoses::handle_tracker_start_stream_response(
    const ClientPSMoveAPI::ResponseMessage *response_message,
    void *userdata)
{
    AppStage_ComputeTrackerPoses *thisPtr = static_cast<AppStage_ComputeTrackerPoses *>(userdata);

    switch (response_message->result_code)
    {
    case ClientPSMoveAPI::_clientPSMoveResultCode_ok:
        {
            // Get the tracker ID this request was for
            const PSMoveProtocol::Request *request = GET_PSMOVEPROTOCOL_REQUEST(response_message->opaque_request_handle);
            const int tracker_id= request->request_start_tracker_data_stream().tracker_id();

            // Get the tracker state associated with the tracker id
            t_tracker_state_map_iterator trackerStateEntry = thisPtr->m_trackerViews.find(tracker_id);
            assert(trackerStateEntry != thisPtr->m_trackerViews.end());

            // The context holds everything a handler needs to evaluate a response
            TrackerState &trackerState = trackerStateEntry->second;

            // Open the shared memory that the video stream is being written to
            if (trackerState.trackerView->openVideoStream())
            {
                // Create a texture to render the video frame to
                trackerState.textureAsset = new TextureAsset();
                trackerState.textureAsset->init(
                    trackerState.trackerView->getVideoFrameWidth(),
                    trackerState.trackerView->getVideoFrameHeight(),
                    GL_RGB, // texture format
                    GL_BGR, // buffer format
                    nullptr);
            }

            // See if this was the last tracker we were waiting to get a response from
            --thisPtr->m_pendingTrackerStartCount;
            if (thisPtr->m_pendingTrackerStartCount <= 0)
            {
                thisPtr->handle_all_devices_ready();
            }
        } break;

    case ClientPSMoveAPI::_clientPSMoveResultCode_error:
    case ClientPSMoveAPI::_clientPSMoveResultCode_canceled:
        {
            thisPtr->setState(eMenuState::failedTrackerStartRequest);
        } break;
    }
}
void AppStage_ComputeTrackerPoses::handle_controller_list_response(
    const ClientPSMoveAPI::ResponseMessage *response_message,
    void *userdata)
{
    AppStage_ComputeTrackerPoses *thisPtr = static_cast<AppStage_ComputeTrackerPoses *>(userdata);

    const ClientPSMoveAPI::eClientPSMoveResultCode ResultCode = response_message->result_code;
//    const ClientPSMoveAPI::t_request_id request_id = response_message->request_id;

    switch (ResultCode)
    {
    case ClientPSMoveAPI::_clientPSMoveResultCode_ok:
        {
            assert(response_message->payload_type == ClientPSMoveAPI::_responsePayloadType_ControllerList);
            const ClientPSMoveAPI::ResponsePayload_ControllerList *controller_list = 
                &response_message->payload.controller_list;

            int PSMoveControllerId = -1;
            for (int list_index = 0; list_index < controller_list->count; ++list_index)
            {
                if (controller_list->controller_type[list_index] == ClientControllerView::PSMove)
                {
                    PSMoveControllerId = controller_list->controller_id[list_index];
                    break;
                }
            }

            if (PSMoveControllerId != -1)
            {
                thisPtr->request_start_controller_stream(PSMoveControllerId);
            }
            else
            {
                thisPtr->setState(AppStage_ComputeTrackerPoses::failedControllerListRequest);
            }
        } break;

    case ClientPSMoveAPI::_clientPSMoveResultCode_error:
    case ClientPSMoveAPI::_clientPSMoveResultCode_canceled:
        {
            thisPtr->setState(AppStage_ComputeTrackerPoses::failedControllerListRequest);
        } break;
    }
}
void AppStage_ComputeTrackerPoses::handle_start_controller_response(
    const ClientPSMoveAPI::ResponseMessage *response_message,
    void *userdata)
{
    AppStage_ComputeTrackerPoses *thisPtr = static_cast<AppStage_ComputeTrackerPoses *>(userdata);

    const ClientPSMoveAPI::eClientPSMoveResultCode ResultCode = response_message->result_code;
//    const ClientPSMoveAPI::t_request_id request_id = response_message->request_id;

    switch (ResultCode)
    {
    case ClientPSMoveAPI::_clientPSMoveResultCode_ok:
        {
            thisPtr->request_tracker_list();
        } break;

    case ClientPSMoveAPI::_clientPSMoveResultCode_error:
    case ClientPSMoveAPI::_clientPSMoveResultCode_canceled:
        {
            thisPtr->setState(AppStage_ComputeTrackerPoses::failedControllerStartRequest);
        } break;
    }
}
void AppStage_ComputeTrackerPoses::handle_controller_list_response(
    const ClientPSMoveAPI::ResponseMessage *response_message,
    void *userdata)
{
	const PSMoveProtocol::Response *response = GET_PSMOVEPROTOCOL_RESPONSE(response_message->opaque_response_handle);
	const PSMoveProtocol::Request *request = GET_PSMOVEPROTOCOL_REQUEST(response_message->opaque_request_handle);
	
    AppStage_ComputeTrackerPoses *thisPtr = static_cast<AppStage_ComputeTrackerPoses *>(userdata);

    const ClientPSMoveAPI::eClientPSMoveResultCode ResultCode = response_message->result_code;

    switch (ResultCode)
    {
    case ClientPSMoveAPI::_clientPSMoveResultCode_ok:
        {
            assert(response_message->payload_type == ClientPSMoveAPI::_responsePayloadType_ControllerList);
            const ClientPSMoveAPI::ResponsePayload_ControllerList *controller_list = 
                &response_message->payload.controller_list;			

			if (thisPtr->m_bSkipCalibration)
			{
				bool bStartedAnyControllers = false;

				for (int list_index = 0; list_index < controller_list->count; ++list_index)
				{
					if (controller_list->controller_type[list_index] == ClientControllerView::PSMove ||
						controller_list->controller_type[list_index] == ClientControllerView::PSDualShock4)
					{
						int trackedControllerId = controller_list->controller_id[list_index];
						const auto &protocolControllerResponse = response->result_controller_list().controllers(list_index);
						const PSMoveTrackingColorType trackingColorType=
							static_cast<PSMoveTrackingColorType>(protocolControllerResponse.tracking_color_type());

						thisPtr->request_start_controller_stream(trackedControllerId, list_index, trackingColorType);
						bStartedAnyControllers = true;
					}
				}

				if (!bStartedAnyControllers)
				{
					thisPtr->setState(AppStage_ComputeTrackerPoses::failedControllerListRequest);
				}
			}
			else
			{
				int trackedControllerId = thisPtr->m_overrideControllerId;
				int trackedControllerListIndex = -1;
				PSMoveTrackingColorType trackingColorType;

				if (trackedControllerId == -1)
				{
					for (int list_index = 0; list_index < controller_list->count; ++list_index)
					{
						if (controller_list->controller_type[list_index] == ClientControllerView::PSMove ||
							controller_list->controller_type[list_index] == ClientControllerView::PSDualShock4)
						{
							const auto &protocolControllerResponse = response->result_controller_list().controllers(list_index);

							trackingColorType = static_cast<PSMoveTrackingColorType>(protocolControllerResponse.tracking_color_type());
							trackedControllerId = controller_list->controller_id[list_index];
							trackedControllerListIndex = list_index;
							break;
						}
					}
				}

				if (trackedControllerId != -1)
				{
					thisPtr->request_start_controller_stream(trackedControllerId, trackedControllerListIndex, trackingColorType);
				}
				else
				{
					thisPtr->setState(AppStage_ComputeTrackerPoses::failedControllerListRequest);
				}
			}
        } break;

    case ClientPSMoveAPI::_clientPSMoveResultCode_error:
    case ClientPSMoveAPI::_clientPSMoveResultCode_canceled:
        {
            thisPtr->setState(AppStage_ComputeTrackerPoses::failedControllerListRequest);
        } break;
    }
}