// called on game thread
        public void CreateQuickMatch(int minOpponents, int maxOpponents, int variant,
                                     Action <bool, TurnBasedMatch> callback)
        {
            Logger.d(string.Format("AndroidTbmpClient.CreateQuickMatch, opponents {0}-{1}, var {2}",
                                   minOpponents, maxOpponents, variant));

            mClient.CallClientApi("tbmp create quick game", () => {
                ResultProxy proxy = new ResultProxy(this, "createMatch");
                proxy.SetMatchCallback(callback);
                AndroidJavaClass tbmpUtil = JavaUtil.GetClass(JavaConsts.SupportTbmpUtilsClass);
                using (AndroidJavaObject pendingResult = tbmpUtil.CallStatic <AndroidJavaObject>(
                           "createQuickMatch", mClient.GHManager.GetApiClient(),
                           minOpponents, maxOpponents, variant)) {
                    pendingResult.Call("setResultCallback", proxy);
                }
            }, (bool success) => {
                if (!success)
                {
                    Logger.w("Failed to create tbmp quick match: client disconnected.");
                    if (callback != null)
                    {
                        callback.Invoke(false, null);
                    }
                }
            });
        }
 // called from game thread
 private void TbmpApiCall(string simpleDesc, string methodName,
                          Action <bool> callback, Action <bool, TurnBasedMatch> tbmpCallback,
                          params object[] args)
 {
     mClient.CallClientApi(simpleDesc, () => {
         ResultProxy proxy = new ResultProxy(this, methodName);
         if (callback != null)
         {
             proxy.SetSuccessCallback(callback);
         }
         if (tbmpCallback != null)
         {
             proxy.SetMatchCallback(tbmpCallback);
         }
         mClient.GHManager.CallGmsApiWithResult("games.Games", "TurnBasedMultiplayer",
                                                methodName, proxy, args);
     }, (bool success) => {
         if (!success)
         {
             Logger.w("Failed to " + simpleDesc + ": client disconnected.");
             if (callback != null)
             {
                 callback.Invoke(false);
             }
         }
     });
 }
        private void OnSelectOpponentsResult(bool success, AndroidJavaObject opponents,
                                             bool hasAutoMatch, AndroidJavaObject autoMatchCriteria,
                                             Action <bool, TurnBasedMatch> callback, int variant)
        {
            Logger.d("AndroidTbmpClient.OnSelectOpponentsResult, success=" + success +
                     ", hasAutoMatch=" + hasAutoMatch);

            if (!success)
            {
                Logger.w("Tbmp select opponents dialog terminated with failure.");
                if (callback != null)
                {
                    Logger.d("Reporting select-opponents dialog failure to callback.");
                    PlayGamesHelperObject.RunOnGameThread(() => {
                        callback.Invoke(false, null);
                    });
                }
                return;
            }

            Logger.d("Creating TBMP match from opponents received from dialog.");

            mClient.CallClientApi("create match w/ opponents from dialog", () => {
                ResultProxy proxy = new ResultProxy(this, "createMatch");
                proxy.SetMatchCallback(callback);
                AndroidJavaClass tbmpUtil = JavaUtil.GetClass(JavaConsts.SupportTbmpUtilsClass);
                using (AndroidJavaObject pendingResult = tbmpUtil.CallStatic <AndroidJavaObject>(
                           "create", mClient.GHManager.GetApiClient(),
                           opponents, variant, hasAutoMatch ? autoMatchCriteria : null)) {
                    pendingResult.Call("setResultCallback", proxy);
                }
            }, (bool ok) => {
                if (!ok)
                {
                    Logger.w("Failed to create match w/ opponents from dialog: client disconnected.");
                    if (callback != null)
                    {
                        callback.Invoke(false, null);
                    }
                }
            });
        }
        // called on game thread
        public void CreateQuickMatch(int minOpponents, int maxOpponents, int variant, 
                    Action<bool, TurnBasedMatch> callback) {
            Logger.d(string.Format("AndroidTbmpClient.CreateQuickMatch, opponents {0}-{1}, var {2}",
                    minOpponents, maxOpponents, variant));

            mClient.CallClientApi("tbmp create quick game", () => {
                ResultProxy proxy = new ResultProxy(this, "createMatch");
                proxy.SetMatchCallback(callback);
                AndroidJavaClass tbmpUtil = JavaUtil.GetClass(JavaConsts.SupportTbmpUtilsClass);
                using (AndroidJavaObject pendingResult = tbmpUtil.CallStatic<AndroidJavaObject>(
                        "createQuickMatch", mClient.GHManager.GetApiClient(), 
                        minOpponents, maxOpponents, variant)) {
                    pendingResult.Call("setResultCallback", proxy);
                }
            }, (bool success) => {
                if (!success) {
                    Logger.w("Failed to create tbmp quick match: client disconnected.");
                    if (callback != null) {
                        callback.Invoke(false, null);
                    }
                }
            });            
        }
        private void OnSelectOpponentsResult(bool success, AndroidJavaObject opponents,
                                             bool hasAutoMatch, AndroidJavaObject autoMatchCriteria,
                                             Action<bool, TurnBasedMatch> callback, int variant) {
            Logger.d("AndroidTbmpClient.OnSelectOpponentsResult, success=" + success +
                     ", hasAutoMatch=" + hasAutoMatch);

            if (!success) {
                Logger.w("Tbmp select opponents dialog terminated with failure.");
                if (callback != null) {
                    Logger.d("Reporting select-opponents dialog failure to callback.");
                    PlayGamesHelperObject.RunOnGameThread(() => {
                        callback.Invoke(false, null);
                    });
                }
                return;
            }
            
            Logger.d("Creating TBMP match from opponents received from dialog.");
             
            mClient.CallClientApi("create match w/ opponents from dialog", () => {
                ResultProxy proxy = new ResultProxy(this, "createMatch");
                proxy.SetMatchCallback(callback);
                AndroidJavaClass tbmpUtil = JavaUtil.GetClass(JavaConsts.SupportTbmpUtilsClass);
                using (AndroidJavaObject pendingResult = tbmpUtil.CallStatic<AndroidJavaObject>(
                       "create", mClient.GHManager.GetApiClient(),
                        opponents, variant, hasAutoMatch ? autoMatchCriteria : null)) {
                    
                    pendingResult.Call("setResultCallback", proxy);
                }
            }, (bool ok) => {
                if (!ok) {
                    Logger.w("Failed to create match w/ opponents from dialog: client disconnected.");
                    if (callback != null) {
                        callback.Invoke(false, null);
                    }
                }
            });
        }
 // called from game thread 
 private void TbmpApiCall(string simpleDesc, string methodName,
         Action<bool> callback, Action<bool, TurnBasedMatch> tbmpCallback,
         params object[] args) {
     mClient.CallClientApi(simpleDesc, () => {
         ResultProxy proxy = new ResultProxy(this, methodName);
         if (callback != null) {
             proxy.SetSuccessCallback(callback);
         }
         if (tbmpCallback != null) {
             proxy.SetMatchCallback(tbmpCallback);
         }
         mClient.GHManager.CallGmsApiWithResult("games.Games", "TurnBasedMultiplayer",
                                                methodName, proxy, args);
     }, (bool success) => {
         if (!success) {
             Logger.w("Failed to " + simpleDesc + ": client disconnected.");
             if (callback != null) {
                 callback.Invoke(false);
             }
         }
     });
 }