/// <summary>
        /// Retrieves the relevant details for a specified user, which the external match-making service can then use to compute effective matches
        /// </summary>
        public static void UserInfo(UserInfoRequest request, UserInfoCallback resultCallback, ErrorCallback errorCallback, object customData = null)
        {
            if (PlayFabSettings.DeveloperSecretKey == null)
            {
                throw new Exception("Must have PlayFabSettings.DeveloperSecretKey set to call this method");
            }

            string serializedJson = JsonConvert.SerializeObject(request, Util.JsonFormatting, Util.JsonSettings);
            Action <CallRequestContainer> callback = delegate(CallRequestContainer requestContainer)
            {
                UserInfoResponse result = ResultContainer <UserInfoResponse> .HandleResults(requestContainer, resultCallback, errorCallback);

                if (result != null)
                {
                }
            };

            PlayFabHTTP.Post("/Matchmaker/UserInfo", serializedJson, "X-SecretKey", PlayFabSettings.DeveloperSecretKey, callback, request, customData);
        }
        public RepoCacheManager(string rootfolder, int cachesize, string gitRemoteRepoURL, string gitBinariesPath, UserInfoCallback callbackInfoUpdate)
        {
            mRootFolder          = rootfolder;
            mCacheSize           = cachesize;
            mGitBinariesPath     = gitBinariesPath;
            mRemoteGitRepository = gitRemoteRepoURL;
            mCallbackInfo        = callbackInfoUpdate;

            mRepoCacheStateFilepath = mRootFolder + REPOCACHE_FOLDER + STATE_FILEPATH;

            if (!Directory.Exists(mRootFolder + REPOCACHE_FOLDER))
            {
                Directory.CreateDirectory(mRootFolder + REPOCACHE_FOLDER);
            }

            mCacheCreateThreads = new List <ThreadArgs>();

            LoadCacheState();
            VerifyCacheState();

            var repoCacheList = BorrowRepoCacheStates(null);

            try
            {
                var AvailableCaches = repoCacheList.Where(x => x.CloneCompleted).Count();
                mAvailableCaches = AvailableCaches;
                callbackInfoUpdate?.Invoke($"Available Caches: {AvailableCaches}/{cachesize}", AvailableCaches);
            }
            finally
            {
                ReturnRepoCacheState(null);
            }

            StartManager();
            DeleteTrash();
        }
		/// <summary>
		/// Retrieves the relevant details for a specified user, which the external match-making service can then use to compute effective matches
		/// </summary>
		public static void UserInfo(UserInfoRequest request, UserInfoCallback resultCallback, ErrorCallback errorCallback, object customData = null)
		{
			if (PlayFabSettings.DeveloperSecretKey == null) throw new Exception ("Must have PlayFabSettings.DeveloperSecretKey set to call this method");

			string serializedJSON = JsonConvert.SerializeObject(request, Util.JsonFormatting, Util.JsonSettings);
			Action<string,PlayFabError> callback = delegate(string responseStr, PlayFabError pfError)
			{
				UserInfoResponse result = null;
				ResultContainer<UserInfoResponse>.HandleResults(responseStr, ref pfError, out result);
				if(pfError != null && errorCallback != null)
				{
					errorCallback(pfError);
				}
				if(result != null)
				{
					
					result.CustomData = customData;
					result.Request = request;
					if(resultCallback != null)
					{
						resultCallback(result);
					}
				}
			};
			PlayFabHTTP.Post(PlayFabSettings.GetURL()+"/Matchmaker/UserInfo", serializedJSON, "X-SecretKey", PlayFabSettings.DeveloperSecretKey, callback);
		}
	IEnumerator lmsGetUserInfo( UserInfoCallback callback )
	{
		// make JSON
		JSONObject j = new JSONObject(JSONObject.Type.OBJECT);
		//number
		j.AddField("action", "User_Info");
		// make param area
		j.AddField("params", "null");
		// add authkey
		string keyNoQuotes = pingAuthKey.Replace ("\"","");
		j.AddField ("authKey",keyNoQuotes);
		// get bodystring
		string bodyString = j.print();

		LMSDebug("lmsGetUserInfo: bodyString=[" + bodyString +"]");
		
		// Create a download object
		string url = "http://" + URL + "statefull/get";
		WWW download = new WWW(url,Encoding.ASCII.GetBytes(bodyString),pingHeaders);
		yield return download;
		
		if (download.error != null)
		{
			LMSDebug("lmsGetUserInfo: download.error=" + download.error);

			// save the error
			if ( callback != null )
				callback(false,download.error);
			UserInfo.Valid = false;
		}
		else
		{
			// decode
			// "{"action":"response","params":{"fname":"Itay","lname":"Moav","email":"*****@*****.**","current_org":"eonflux"},"authKey":"c1nsqupar527qcjhc0s5m93le5","dbgenv":"192.168.12.148"}"			
			JSONObject decoder = new JSONObject(download.text);
			if ( CheckReturn(decoder) == true )
			{
				var N = JSONNode.Parse(download.text);
				UserInfo.FirstName = N["params"]["fname"].ToString(); 
				UserInfo.LastName = N["params"]["lname"].ToString(); 
				UserInfo.Email = N["params"]["email"].ToString();
				UserInfo.Org = N["params"]["current_org"].ToString();
				UserInfo.Valid = true;
				LMSDebug("lmsGetUserInfo: UserInfo.Valid=" + LMSIntegration.UserInfo.Valid);
				if ( callback != null )
					callback(true,download.text);
			}
			else
			{
				LMSDebug("lmsGetUserInfo: download.text=" + download.text);
				if ( callback != null )
					callback(false,download.text);
			}
		}
	}
	public void LMSGetUserInfo( UserInfoCallback callback=null )
	{
		StartCoroutine(lmsGetUserInfo(callback));
	}