﻿/********************************************************
*                                                       *
* Copyright (C) Microsoft. All rights reserved.         *
*                                                       *
********************************************************/

// Sentient Client Stats API
//
// Include this to get access to all Stats-related Sentient features.

#pragma once

#include "SenClientTypes.h"


namespace Sentient
{
	/***********************
	 ***** Stats Types *****
	 ***********************/

	#define SenStatID_Custom 128

	// Stats
	#define SenStatFlag_Normal		1
	#define SenStatFlag_Time		2
	#define SenStatFlag_TimeEnd		4

	// Params
	#define SenStatValueFlag_Inc	1
	#define SenStatValueFlag_Accum	2
	#define SenStatValueFlag_Min	4
	#define SenStatValueFlag_Max	8

    // Enable Logging if we are in debug build
#ifdef _DEBUG 
    #define SEN_LOGTELEMETRY
#endif

	struct SenStat
	{
		DWORD	dwUserID;
		DWORD	dwStatID;
		DWORD	dwFlags;          // SenStatFlag_*
		DWORD	dwNumProperties;
		CHAR*	arrProperties;
		DWORD	dwNumValues;
		CHAR*	arrValues;
		DWORD*	arrValueFlags;    // SenStatValueFlag_*
	};


	/***************************
	 ***** Stats Functions *****
	 ***************************/
	
	/// @brief           Submit a stat entry to the sentient system
	///
    /// @param[in]       pStat
    ///                  The pointer to SenStat structure. The SentientStatsSend function is usually called from the autogenerated fuctions
    ///                  which use as [in] parameters the userIndex(0 through 3) and the set of the stat properties/values. The rest of the SenStat structure memebers are
    ///                  created automatically from the stat xml file generated code.   
	///
	/// @return          Check SUCCEEDED( hresult ) or FAILED( hresult ) to determine success.  Specific values include:
	///                  SENTIENT_E_NOT_INITIALIZED: You did not call SentientInitialize() first.
	///                  E_FAIL: Failed to spawn server call.
	///                  S_OK: Server call spawned successfully.
	///
	/// @details         Calls to this function should use generated Telemetry code, rather than
	///					 calling the function from title code
	HRESULT SentientStatsSend( SenStat *pStat );
	
	/// @brief			 Sets the send interval for Telemetry.  Only works in debug builds
	///
	/// @param[in]			 dwIntervalMs
	///					 The new send interval, in milliseconds.  This value is capped at a minimum of 250 ms.
	///
	/// @details		 The body of this function is conditionally compiled out of non-debug builds.  
	///
	void SentientSetStatSendInterval( DWORD dwIntervalMs );

	/// @brief			 Requests that Sentient immediately send any stats being buffered 
	///
	/// @return          Check SUCCEEDED( hresult ) or FAILED( hresult ) to determine success.  Specific values include:
	///                  SENTIENT_E_NOT_INITIALIZED: You did not call SentientInitialize() first.
	///                  SENTIENT_E_TOO_MANY_CALLS: You tried to flush too quickly after a previous flush.
	///                  S_OK: Buffered stats will be flushed to the server on the next Sentient::Update() call
	///
	/// @details		 This API can only be called once every minute.  Any attempts to call the API more frequently
	///					 will result in the call being throttled, and the API returning SENTIENT_E_TOO_MANY_CALLS
    ///                  Data is not actually sent until the next Sentient::Update() call
	HRESULT SentientFlushStats( );
    
	/// @brief			 Requests that Sentient immediately send any stats being buffered because the title is exiting
	///
	/// @return          Check SUCCEEDED( hresult ) or FAILED( hresult ) to determine success.  Specific values include:
	///                  SENTIENT_E_NOT_INITIALIZED: You did not call SentientInitialize() first.
	///                  SENTIENT_E_TOO_MANY_CALLS: You tried to flush on Exit more than once
	///                  S_OK: Buffered stats  will be flushed to the server on the next Sentient::Update() call
	///
	/// @details		 This API can only be called ONCE.  Any attempts to call the API more frequently
	///					 will result in the call being throttled, and the API returning SENTIENT_E_TOO_MANY_CALLS
    ///                  Data is not actually sent until the next Sentient::Update() call
	HRESULT SentientFlushStatsOnExit( );
    
	/// @brief			 Requests that Sentient immediately send any stats being buffered because the title is going to the marketplace and may not return
	///
	/// @return          Check SUCCEEDED( hresult ) or FAILED( hresult ) to determine success.  Specific values include:
	///                  SENTIENT_E_NOT_INITIALIZED: You did not call SentientInitialize() first.
	///                  SENTIENT_E_TOO_MANY_CALLS: You tried to flush on MarketPlace too many times
	///                  S_OK: Buffered stats  will be flushed to the server on the next Sentient::Update() call
	///
	/// @details		 Any attempts to call the API too frequently will result in the call being throttled, 
	///					 and the API returning SENTIENT_E_TOO_MANY_CALLS
    ///                  Data is not actually sent until the next Sentient::Update() call
	HRESULT SentientFlushStatsOnMarketPlace( );
        
	/// @brief			 Tells Sentient that an important point in the game was hit and that events should be sent as soon as possible
	///
	/// @return          Check SUCCEEDED( hresult ) or FAILED( hresult ) to determine success.  Specific values include:
	///                  SENTIENT_E_NOT_INITIALIZED: You did not call SentientInitialize() first.
	///                  S_OK: Buffered stats will be flushed to the server within the next minute
	///
	/// @details		 This API should be caleld when the game hits an important event or point. 
    ///                  Sentient Will send the event data to the server within the next minute, calling this method frequently will not cause any additional sends
	HRESULT SentientFlushStatsOnKeyEvent( );

#ifdef SEN_LOGTELEMETRY 
    // if we're in debug build log out the stat to a file for testing
    void SentientDebugLogStatSend(const char *statName, const SenStat *pStat);
#endif

} // namespace Sentient
