PlayerPanel2 GetPlayerPanelByUserGameProfileId(UserGameProfileId userGameProfileId)
        {
            PlayerPanel2 panelToFind = null;

            this.Dispatcher.Invoke(() =>
            {
                //search for data related with userGameProfileId in fisrt collection (team 1)
                foreach (var child in team1.Children)
                {
                    var control = child as PlayerPanel2;

                    if (control.UserMatchData.UserGameProfileId.ProfileId == userGameProfileId.ProfileId)
                    {
                        panelToFind = control;
                        break;
                    }
                }

                //search for data related with userGameProfileId in second collection (team 2)
                foreach (var child in team2.Children)
                {
                    if (panelToFind != null)
                    {
                        break;
                    }

                    var control = child as PlayerPanel2;

                    if (control.UserMatchData.UserGameProfileId.ProfileId == userGameProfileId.ProfileId)
                    {
                        panelToFind = control;
                        break;
                    }
                }
            });

            return(panelToFind);
        }
        public static UserRank GetUserRank(this IEnumerable <UserMatchData> userMatchDatas, UserGameProfileId userGameProfileId, Ladders userRankMode)
        {
            var userMatchData = userMatchDatas.First
                                    (umd => umd.UserGameProfileId.ProfileId == userGameProfileId.ProfileId);

            if (userMatchData == null)
            {
                return(null);
            }

            if (!(userMatchData.UserRankData.UserRatings.ContainsKey(userRankMode)))
            {
                return(null);
            }

            return(userMatchData.UserRankData.UserRatings[userRankMode]);
        }
        public static UserData GetUserRankData(this IEnumerable <UserMatchData> userMatchDatas, UserGameProfileId userGameProfileId)
        {
            var userMatchData = userMatchDatas.First
                                    (umd => umd.UserGameProfileId.ProfileId == userGameProfileId.ProfileId);

            if (userMatchData == null)
            {
                return(null);
            }

            //if (!(userMatchData.UserRankData.UserRatings.ContainsKey(userRankMode)))
            //    return null;

            return(userMatchData.UserRankData);
        }
        void HandleUserDataUpadted(Task <RequestWrapper <UserLadderData> > updateTask, UserGameProfileId userGameProfileId)
        {
            Dictionary <string, object> logProperties = null;

            //unahndled exception inside task scope
            if (updateTask.IsFaulted || updateTask.IsCanceled)
            {
                if (updateTask.Exception != null)
                {
                    logProperties = new Dictionary <string, object>
                    {
                        { "exception", updateTask.Exception.ToString() },
                        { "stack", updateTask.Exception.StackTrace }
                    };
                }

                LogService.Error("HandleUserDataUpdated: Internal task processing exception", logProperties ?? null);
                return;
            }

            //handled exception
            if (!updateTask.Result.IsSuccess)
            {
                if (updateTask.Exception != null)
                {
                    logProperties = new Dictionary <string, object>
                    {
                        { "exception", updateTask.Exception.ToString() },
                        { "stack", updateTask.Exception.StackTrace }
                    };
                }

                LogService.Warning("HandleUserDataUpdated: Unable to complete task successfully", logProperties);
                return;
            }

            if (updateTask.Exception != null)
            {
                LogService.Warning("Error while updating user rating: ");
                return;
            }

            //publish data changed event
            EventAggregator.GetEvent <UserDataChangedEvent>().Publish(Tuple.Create(userGameProfileId, updateTask.Result.Value));
        }
        Match IUserDataProcessingService.ProcessMatch(string jsonResponse, AoeNetAPIStringResources apiStringResources)
        {
            var matchResponse = JsonConvert.DeserializeObject <MatchResponse>(
                jsonResponse
                );

            var match = new Match
            {
                //todo: handle opened as separate state independent then start
                Opened = matchResponse.last_match.started,

                Finished = matchResponse.last_match.finished,
                MatchId  = matchResponse.last_match.match_id,

                Users     = new List <UserMatchData>(),
                MatchType = (MatchType)matchResponse.last_match.leaderboard_id
            };

            //create user match data models from response model
            foreach (var player in matchResponse.last_match.players)
            {
                //assign basic data
                UserMatchData userMatchData = new UserMatchData
                {
                    Name = player.name,


                    Team  = player.team,
                    Color = ((UserColors)player.color).ToString()
                };

                //for compatibility with: MatchMinimalResponse set, cause API is returning null civs sometimes
                string civilization = "";

                try
                {
                    civilization = apiStringResources.Civ //find matching civilization from API resources
                                   .First(id => id.Id == player.civ)
                                   .String;
                }
                catch (Exception e)
                {
                    if (
                        e is StackOverflowException ||
                        e is ThreadAbortException ||
                        e is AccessViolationException
                        )
                    {
                        throw e;
                    }

                    civilization = "Unknown uivilization";
                }
                finally
                {
                    userMatchData.Civilization = civilization;
                }

                //assign game profile id
                var userGameProfileId = new UserGameProfileId
                {
                    ProfileId = player.profile_id.ToString()
                };
                userMatchData.UserGameProfileId = userGameProfileId;
                userMatchData.UserRankData      = new UserData();
                userMatchData.MatchType         = (MatchType)matchResponse.last_match.leaderboard_id;

                //assign ratings if aviable
                if (player.rating != null)
                {
                    var ratingType = (Ladders)matchResponse.last_match.leaderboard_id;

                    var userRank = new UserRank
                    {
                        Elo    = player.rating.Value,
                        Ladder = null //we have to send separate request to check ladder
                    };

                    userMatchData.UserRankData.UserRatings.Add(ratingType, userRank);
                }

                match.Users.Add(userMatchData);
            }

            return(match);
        }
        public async Task <RequestWrapper <UserLadderData> > GetUserDataFromLadder(UserGameProfileId userGameProfileId, Ladders ladder, int timeout)
        {
            ValidateCacheState();

            RequestWrapper <UserLadderData> requestWrapper = new RequestWrapper <UserLadderData>();
            Dictionary <string, object>     logProperties  = new Dictionary <string, object>
            {
                { "timeout", timeout },
                { "game-profile-id", userGameProfileId.ProfileId },
                { "ladder", ladder.ToString() }
            };

            RequestState requestState = null;

            try
            {
                if (!StorageService.Has("stringResources"))
                {
                    throw new InvalidOperationException("App resources unaviable while sending request");
                }

                if (string.IsNullOrEmpty(userGameProfileId.ProfileId))
                {
                    throw new InvalidOperationException("Missing user id");
                }

                var stringResources = StorageService.Get <AoeNetAPIStringResources>("stringResources");

                //preapare query
                var query = HttpUtility.ParseQueryString(string.Empty);

                query["profile_id"]     = HttpUtility.UrlEncode(userGameProfileId.ProfileId);
                query["leaderboard_id"] = HttpUtility.UrlEncode(((int)ladder).ToString());
                query["game"]           = HttpUtility.UrlEncode("aoe2de"); //only aviable for DE at this moment, https://aoe2.net/#api

                var finallQuery = "https://aoe2.net/api/leaderboard?" + query.ToString();
                logProperties.Add("query", finallQuery);

                //create cts
                var cts = new CancellationTokenSource();
                //create timeout handler for current query
                requestState = AddTimeoutHandler(cts, timeout);

                requestState.isRunning    = true;
                requestWrapper.RequestUrl = finallQuery;
                //sumbit query via query cache service
                requestWrapper.RequestResponseWrapper = await QueryCacheService.GetOrUpdate(
                    finallQuery,
                    cts.Token,
                    DateTime.UtcNow.AddHours(1.5)
                    );

                if (!requestWrapper.RequestResponseWrapper.IsSuccess)
                {
                    throw new AggregateException("Request failed", requestWrapper.RequestResponseWrapper.Exception);
                }

                requestWrapper.Value = (this as IUserDataProcessingService).ProcessUserDataFromLadder(requestWrapper.RequestResponseWrapper.ResponseContent, stringResources);
            }
            catch (Exception e) // request timedout
            {
                if (
                    e is StackOverflowException ||
                    e is ThreadAbortException ||
                    e is AccessViolationException
                    )
                {
                    throw e;
                }

                string responseContent = "";
                string responseCode    = "";

                if (requestWrapper != null) //to make sure this will not conflict with test cases
                {
                    if (requestWrapper.RequestResponseWrapper != null)
                    {
                        if (requestWrapper.RequestResponseWrapper.ResponseContent != null)
                        {
                            responseContent = requestWrapper.RequestResponseWrapper.ResponseContent;
                        }

                        if (requestWrapper.RequestResponseWrapper.Response != null) //to make sure this will not conflict with test cases
                        {
                            responseCode = requestWrapper.RequestResponseWrapper.Response.StatusCode.ToString();
                        }
                    }
                }

                logProperties.Add("stack", e.StackTrace);
                logProperties.Add("response-code", responseCode);
                logProperties.Add("response-raw", responseContent);
                LogService.Error($"Error while requesting ladder: {e.ToString()}", logProperties);

                requestWrapper.Exception = e;
            }
            finally
            {
                if (requestState != null)
                {
                    requestState.isRunning = false; //prevent cancelling operation by timeout handler
                }
            }

            return(requestWrapper);
        }