/// <summary>
            /// Having made a call to MLTokenAgentGetClientCredentialsAsync(), the user can call MLTokenAgentGetClientCredentialsWait()
            /// to detect whether the asynchronous call completed and if so, to retrieve the credentials in out_credentials.
            /// </summary>
            /// <param name="clientCredentials">Reference to the clientCredentials object.</param>
            /// <param name="credentials">Reference to the credentials struct of the clientCredentials object.</param>
            /// <param name="tokens">Reference to the tokens struct of the clientCredentials object.</param>
            /// <returns>
            /// MLResult.Result will be <c>MLResult.Code.Ok</c> if the operation completed successfully before the timeout elapsed.
            /// MLResult.Result will be <c>MLResult.Code.Pending</c> if the timeout elapsed before the asynchronous call completed.
            /// MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if the operation failed with an unspecified error.
            /// MLResult.Result will be <c>MLResult.Code.InvalidParam</c> if the future or out_credentials were 0 (null).
            /// MLResult.Result will be <c>MLResult.Code.AllocFailed</c> if the operation failed to allocate memory.
            /// MLResult.Result will be <c>MLResult.Code.PrivilegeDenied</c> if the caller does not have the ClientCredentialsRead privilege.
            /// MLResult.Result will be <c>MLResult.Code.TokenAgent*</c> if a token specific failure occurred during the operation.
            /// </returns>
            public static MLResult.Code ListenClientCredentialsResponse(MLTokenAgent.ClientCredentials clientCredentials, ref MLTokenAgent.Credentials credentials, ref MLTokenAgent.Tokens tokens)
            {
                try
                {
                    IntPtr clientCredentialsPtr       = clientCredentialsPtrMap.ContainsKey(clientCredentials) ? clientCredentialsPtrMap[clientCredentials] : IntPtr.Zero;
                    IntPtr clientCredentialsFuturePtr = clientCredentialsFuturePtrMap.ContainsKey(clientCredentials) ? clientCredentialsFuturePtrMap[clientCredentials] : IntPtr.Zero;

                    if (clientCredentialsFuturePtr == IntPtr.Zero)
                    {
                        MLPluginLog.Warning("MLTokenAgent.NativeBindings.ListenClientCredentialsResponse failed because a valid future pointer could not be found with the passed request.");
                        return(MLResult.Code.UnspecifiedFailure);
                    }

                    //// Attempt to get data if available, 0 is passed as a timeout to immediately return and never wait for results.
                    MLResult.Code resultCode = MLTokenAgent.NativeBindings.MLTokenAgentGetClientCredentialsWait(clientCredentialsFuturePtr, 0, ref clientCredentialsPtr);

                    // If it succeeded, copy any modifications made to the profile in unmanaged memory by the Identity API to managed memory.
                    if (MLResult.IsOK(resultCode))
                    {
                        clientCredentialsFuturePtrMap.Remove(clientCredentials);

                        clientCredentialsPtrMap.Remove(clientCredentials);
                        clientCredentialsPtrMap.Add(clientCredentials, clientCredentialsPtr);

                        MLTokenAgent.NativeBindings.ClientCredentialsNative clientCredentialsNative = (MLTokenAgent.NativeBindings.ClientCredentialsNative)Marshal.PtrToStructure(clientCredentialsPtr, typeof(MLTokenAgent.NativeBindings.ClientCredentialsNative));
                        credentials = clientCredentialsNative.Credentials;
                        tokens      = clientCredentials.Tokens;
                    }
                    else
                    {
                        credentials = new Credentials();
                        tokens      = new Tokens();
                    }

                    return(resultCode);
                }
                catch (EntryPointNotFoundException)
                {
                    MLPluginLog.Error("MLTokenAgent.NativeBindings.ListenClientCredentialsResponse failed. Reason: API symbols not found.");
                    return(MLResult.Code.UnspecifiedFailure);
                }
            }
            /// <summary>
            /// GetClientCredentials is a blocking function that accesses the cloud and
            /// returns a MLTokenAgentClientCredentials structure containing the users credentials and
            /// tokens for a particular service (Audience).
            /// The library deduces the Audience being requested from the name of the calling service.
            /// </summary>
            /// <param name="clientCredentials">Reference to the clientCredentials object.</param>
            /// <param name="credentials">Reference to the credentials struct of the clientCredentials object.</param>
            /// <param name="tokens">Reference to the tokens struct of the clientCredentials object.</param>
            /// <returns>
            /// MLResult.Result will be <c>MLResult.Code.Ok</c> if successful.
            /// MLResult.Result will be <c>MLResult.Code.InvalidParam</c> if failed due to internal invalid input parameter.
            /// MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if failed due to internal error.
            /// MLResult.Result will be <c>MLResult.Code.AllocFailed</c> if failed to allocate memory.
            /// MLResult.Result will be <c>MLResult.Code.PrivilegeDenied</c> if necessary privilege is missing.
            /// MLResult.Result will be <c>MLResult.Code.TokenAgent*</c> if a token specific failure occurred during the operation.
            /// </returns>
            public static MLResult.Code GetClientCredentials(MLTokenAgent.ClientCredentials clientCredentials, ref MLTokenAgent.Credentials credentials, ref MLTokenAgent.Tokens tokens)
            {
                try
                {
                    IntPtr        clientCredentialsPtr = clientCredentialsPtrMap.ContainsKey(clientCredentials) ? clientCredentialsPtrMap[clientCredentials] : IntPtr.Zero;
                    MLResult.Code resultCode           = MLTokenAgent.NativeBindings.MLTokenAgentGetClientCredentials(ref clientCredentialsPtr);
                    if (MLResult.IsOK(resultCode))
                    {
                        clientCredentialsPtrMap.Remove(clientCredentials);
                        clientCredentialsPtrMap.Add(clientCredentials, clientCredentialsPtr);

                        MLTokenAgent.NativeBindings.ClientCredentialsNative clientCredentialsNative = (MLTokenAgent.NativeBindings.ClientCredentialsNative)Marshal.PtrToStructure(clientCredentialsPtr, typeof(MLTokenAgent.NativeBindings.ClientCredentialsNative));
                        credentials = clientCredentialsNative.Credentials;
                        tokens      = clientCredentials.Tokens;
                    }
                    else
                    {
                        credentials = new Credentials();
                        tokens      = new Tokens();
                    }

                    return(resultCode);
                }
                catch (EntryPointNotFoundException)
                {
                    MLPluginLog.Error("MLTokenAgent.NativeBindings.GetClientCredentials failed. Reason: API symbols not found.");
                    return(MLResult.Code.UnspecifiedFailure);
                }
            }