public async Task <IEnumerable <OtherMatch> > GetOpponentMatches(int teamId, int?clubId = null, string teamCode = null)
        {
            // This is also called from Team Week display where there is no opponent
            var opponent = clubId.HasValue ? OpposingTeam.Create(clubId, teamCode) : null;
            var result   = await _service.GetOpponentMatches(teamId, opponent);

            CleanSensitiveData(result);
            return(result);
        }
        // TODO: This is probably some code that fetches opponent team last year performance
        // as an indicator of what they might this year look like. Something for pre season.
        // Probably not worth the trouble...
        //public async Task<int?> SyncLastYearOpponentMatches(TeamEntity team, OpposingTeam opponent)
        //{
        //    const int prevFrenoySeason = Constants.FrenoySeason - 1;
        //    string frenoyOpponentClub = GetFrenoyClubdId(opponent.ClubId);

        //    var opponentTeams = await _frenoy.GetClubTeamsAsync(new GetClubTeamsRequest
        //    {
        //        Club = frenoyOpponentClub,
        //        Season = prevFrenoySeason.ToString()
        //    });

        //    var lastYearTeam = opponentTeams.TeamEntries.SingleOrDefault(x => x.Team == opponent.TeamCode && x.DivisionCategory == Constants.FrenoyTeamCategory);
        //    if (lastYearTeam != null)
        //    {
        //        int lastYearDivisionId = int.Parse(lastYearTeam.DivisionId);
        //        var ourTeam = _db.Teams.SingleOrDefault(x => x.Year == _currentSeason - 1 && x.FrenoyDivisionId == lastYearDivisionId && x.Competition == _settings.Competition.ToString());
        //        if (ShouldAttemptOpponentMatchSync(opponent, team.Id, prevFrenoySeason))
        //        {
        //            var matches = await _frenoy.GetMatchesAsync(new GetMatchesRequest
        //            {
        //                Club = frenoyOpponentClub,
        //                Season = prevFrenoySeason.ToString(),
        //                Team = opponent.TeamCode,
        //                WithDetailsSpecified = false,
        //                WithDetails = false,
        //                DivisionId = lastYearTeam.DivisionId
        //            });
        //            await SyncTeamMatches(ourTeam?.Id, lastYearDivisionId, matches, false, prevFrenoySeason);
        //        }

        //        return lastYearDivisionId;
        //    }
        //    return null;
        //}

        public async Task SyncOpponentMatches(TeamEntity team, OpposingTeam opponent)
        {
            if (ShouldAttemptOpponentMatchSync(opponent, team.Id))
            {
                var matches = await _frenoy.GetMatchesAsync(new GetMatchesRequest
                {
                    Club   = GetFrenoyClubdId(opponent.ClubId),
                    Season = _settings.FrenoySeason.ToString(),
                    Team   = opponent.TeamCode,
                    WithDetailsSpecified = false,
                    WithDetails          = false,
                    DivisionId           = team.FrenoyDivisionId.ToString()
                });
                await SyncTeamMatches(team.Id, team.FrenoyDivisionId, matches.GetMatchesResponse);
            }
        }
        private bool ShouldAttemptOpponentMatchSync(OpposingTeam team, int teamId, int?season = null)
        {
            season = season ?? _db.CurrentFrenoySeason;

            string hash = season + team.TeamCode + team.ClubId + '-' + teamId;

            lock (FrenoyOpponentLock)
            {
                if (!FrenoyOpponentCache.ContainsKey(hash))
                {
                    FrenoyOpponentCache.Add(hash, DateTime.Now);
                    return(true);
                }

                bool shouldSync = FrenoyOpponentCache[hash] > DateTime.Now + FrenoyPesterExpiration;
                if (shouldSync)
                {
                    FrenoyOpponentCache.Remove(hash);
                }
                return(shouldSync);
            }
        }
        public async Task <ICollection <OtherMatch> > GetOpponentMatches(int teamId, OpposingTeam opponent = null)
        {
            using (var dbContext = new TtcDbContext())
            {
                var team = await dbContext.Teams.SingleAsync(x => x.Id == teamId);

                async Task <MatchEntity[]> GetMatchEntities()
                {
                    // ReSharper disable AccessToDisposedClosure
                    var matches = dbContext.Matches
                                  .WithIncludes()
                                  .Where(match => match.FrenoyDivisionId == team.FrenoyDivisionId);

                    // ReSharper restore AccessToDisposedClosure

                    if (opponent != null)
                    {
                        matches = matches.Where(match =>
                                                (match.AwayClubId == opponent.ClubId && match.AwayTeamCode == opponent.TeamCode) ||
                                                (match.HomeClubId == opponent.ClubId && match.HomeTeamCode == opponent.TeamCode)
                                                );
                    }

                    return(await matches.ToArrayAsync());
                }

                MatchEntity[] matchEntities = await GetMatchEntities();

                if (opponent != null)
                {
                    // TODO BUG: This means that when called from Team Week Overview, no opponent is set and there is no sync...
                    // TODO PERFORMANCE: This executes too many times, make it part of initial competition load
                    var frenoy = new FrenoyMatchesApi(dbContext, Constants.NormalizeCompetition(team.Competition));
                    await frenoy.SyncOpponentMatches(team, opponent);

                    matchEntities = await GetMatchEntities();
                }

                // No comments for OpponentMatches

                var result = Mapper.Map <IList <MatchEntity>, IList <OtherMatch> >(matchEntities);
                return(result);

                // TODO: Bug PreSeason code: This doesn't work! These results are NOT displayed in the MatchCard, the spinner just keeps on spinnin'
                // Pre season: Fetch last year matches instead
                //int? divisionId = frenoy.SyncLastYearOpponentMatches(team, opponent);
                //if (divisionId.HasValue)
                //{
                //    var matchEntities = dbContext.Matches
                //        .WithIncludes()
                //        .Where(match => (match.AwayClubId == opponent.ClubId && match.AwayTeamCode == opponent.TeamCode) || (match.HomeClubId == opponent.ClubId && match.HomeTeamCode == opponent.TeamCode))
                //        .Where(match => match.FrenoyDivisionId == divisionId.Value)
                //        .ToList();

                //    // No comments for OpponentMatches

                //    // HACK: hack om vorig jaar matchen te tonen in de frontend zonder te moeten berekenen wat hun "last year division id" is
                //    foreach (var match in matchEntities)
                //    {
                //        match.FrenoyDivisionId = team.FrenoyDivisionId;
                //    }

                //    var result = Mapper.Map<IList<MatchEntity>, IList<OtherMatch>>(matchEntities);
                //    return result;
                //}
            }
        }