// todo: return rank?
        public IRequestToken SubmitScore(double score, uint mode, ScoreloopCallback<Score> callback)
        {
            if (!this.IsNetworkAvailable)
            {
                callback.InvokeIfNotNull(new ScoreloopResponse<Score>(null, null, false));
                return null;
            }

            IScoreController scoreController = _client.CreateScoreController();
            scoreController.RequestFailed += (o, e) => callback.InvokeIfNotNull(new ScoreloopResponse<Score>(null, scoreController, false));
            scoreController.RequestCancelled += (o, e) => callback.InvokeIfNotNull(new ScoreloopResponse<Score>(null, scoreController, false));
            scoreController.ScoreSubmitted += (o, e) => callback.InvokeIfNotNull(new ScoreloopResponse<Score>(scoreController.Score, scoreController, true));

            scoreController.Submit(scoreController.CreateScore(score, mode));

            return new RequestToken(scoreController);
        }
        public IRequestToken LoadScores(LeaderboardScope leaderboardScope, RangeInt scoreRange, uint mode, ScoreloopCallback<LeaderboardScoresResponse> callback)
        {
            if (!this.IsNetworkAvailable)
            {
                callback.InvokeIfNotNull(new ScoreloopResponse<LeaderboardScoresResponse>(null, null, false));
                return null;
            }

            Ensure.True(scoreRange.Length > 0);

            IScoresController scoresController = _client.CreateScoresController();
            scoresController.RequestCancelled += (o, e) => callback.InvokeIfNotNull(new ScoreloopResponse<LeaderboardScoresResponse>(null, scoresController, false));
            scoresController.RequestFailed += (o, e) => callback.InvokeIfNotNull(new ScoreloopResponse<LeaderboardScoresResponse>(null, scoresController, false));
            scoresController.ScoresLoaded += (o, e) => callback.InvokeIfNotNull(new ScoreloopResponse<LeaderboardScoresResponse>(new LeaderboardScoresResponse(e.Controller.Scores, scoreRange.Min), scoresController, true));

            scoresController.LoadScores(ScoreloopHelper.GetSearchList(leaderboardScope, scoresController), new ScoreloopRange(scoreRange.Min, (uint)scoreRange.Length), mode);
            return new RequestToken(scoresController);
        }
        public IRequestToken RenameUser(string newName, ScoreloopCallback callback)
        {
            if (!this.IsNetworkAvailable)
            {
                callback.InvokeIfNotNull(new ScoreloopResponse(null, false));
                return null;
            }

            Ensure.NotNull(newName);

            IUserController userController = _client.CreateUserController();
            userController.RequestFailed += (o, e) => callback.InvokeIfNotNull(new ScoreloopResponse(userController, false));
            userController.RequestCancelled += (o, e) => callback.InvokeIfNotNull(new ScoreloopResponse(userController, false));
            userController.UserUpdated += (o, e) => callback.InvokeIfNotNull(new ScoreloopResponse(userController, true));
         
            userController.Update(newName, "");
            return new RequestToken(userController);
        }
        public IRequestToken GetRank(LeaderboardScope leaderboardScope, Score score, ScoreloopCallback<RankResponse> callback)
        {
            if (!this.IsNetworkAvailable)
            {
                callback.InvokeIfNotNull(new ScoreloopResponse<RankResponse>(new RankResponse(-1, null, leaderboardScope), null, false));
                return null;
            }

            IRankingController rankingController = _client.CreateRankingController();
            rankingController.RequestFailed += (o, e) => callback.InvokeIfNotNull(new ScoreloopResponse<RankResponse>(new RankResponse(-1, null, leaderboardScope), rankingController, false));
            rankingController.RequestCancelled += (o, e) => callback.InvokeIfNotNull(new ScoreloopResponse<RankResponse>(new RankResponse(-1, null, leaderboardScope), rankingController, false));
            rankingController.RankingLoaded += (o, e) => callback.InvokeIfNotNull(new ScoreloopResponse<RankResponse>(new RankResponse((int)e.Controller.Rank, e.Controller.Score, leaderboardScope), rankingController, true));

            rankingController.LoadRanking(ScoreloopHelper.GetSearchList(leaderboardScope, rankingController), score);
            return new RequestToken(rankingController);
        }