public LeagueTeam(League league, Team team)
 {
     if (league == null)
         throw new ArgumentNullException(nameof(league));
     if (team == null)
         throw new ArgumentNullException(nameof(team));
     League = league;
     Team = team;
     Statistics = new TeamStatistics();
 }
        private League GenerateLeague(JObject leagueDataJson, JObject fixturesJson, ref List<Team> teams)
        {
            var league = new League
            {
                ID = "PL",
                Name = "Premier League 16/17",
                Year = 2016,
            };
            var leagueTeams = new List<LeagueTeam>();
            var gameweeks = new List<Gameweek>();
            var positions = new Dictionary<int, PlayerPosition>();


            // Get playing positions
            var typeInfo = leagueDataJson?.Property("element_types")?.Value?.ToObject<JArray>();
            if (typeInfo != null)
            {
                foreach (var type in typeInfo.Select(x => x.ToObject<JObject>()).Where(x => x != null))
                {
                    PlayerPosition pos;
                    var posID = type.GetPropertyValue<int>("id");
                    var posShortName = type.GetPropertyValue<string>("singular_name_short");
                    switch (posShortName)
                    {
                        case "GKP":
                            pos = PlayerPosition.Goalkeeper;
                            break;

                        case "DEF":
                            pos = PlayerPosition.Defender;
                            break;

                        case "MID":
                            pos = PlayerPosition.Midfielder;
                            break;

                        case "FWD":
                            pos = PlayerPosition.Forward;
                            break;

                        default:
                            continue;
                    }
                    positions[posID] = pos;
                }
            }
            


            // Get teams
            var eiwTeams = leagueDataJson?.Property("teams")?.Value?.ToObject<JArray>();
            if (eiwTeams != null)
            {
                foreach (var eiwTeam in eiwTeams)
                {
                    var t = eiwTeam?.ToObjectOrDefault<JObject>();
                    if (t == null)
                        continue;
                    var teamID = t.GetPropertyValue<string>("id");
                    if (string.IsNullOrWhiteSpace(teamID))
                        throw new FormatException("Invalid TeamID");

                    var team = teams.FirstOrDefault(x => x.ID == teamID);
                    if (team == null)
                    {
                        team = new Team
                        {
                            ID = teamID,
                            Name = t.GetPropertyValue<string>("name"),
                            ShortName = t.GetPropertyValue<string>("short_name"),

                            // todo: implement
                            //Statistics = 
                            //Rating = new Rating
                            //{
                            //    // todo: normalize to a 1-10 rating
                            //    //Value = (t.GetPropertyValue<int>("strength_overall_home") +
                            //    //        t.GetPropertyValue<int>("strength_overall_away")) / 2
                            //}
                        };
                        teams.Add(team);

                        var club = _ukClubs?.FirstOrDefault(x => x.MatchName(team.Name));
                        if (club != null)
                        {
                            team.Aliases = club.Aliases;
                        }
                    }
                
                    var leagueTeam = new LeagueTeam(league, team);
                    leagueTeams.Add(leagueTeam);
                    team.Leagues = team.Leagues.Append(league);
                }
            }




            // Get players
            var elements = leagueDataJson?.Property("elements")?.Value?.ToObject<JArray>();
            if (elements != null)
            {
                foreach (var playerData in elements)
                {
                    var p = playerData?.ToObjectOrDefault<JObject>();
                    if (p == null)
                        continue;

                    var posID = p.GetPropertyValue<int>("element_type");
                    var pos = positions[posID];
                    
                    // todo: load and update player (statitics), if player plays in multiple leagues

                    var player                          = new Player();
                    player.ID                           = p.GetPropertyValue<string>("id");
                    player.FirstName                    = p.GetPropertyValue<string>("first_name");
                    player.LastName                     = p.GetPropertyValue<string>("second_name");
                    player.DisplayName                  = p.GetPropertyValue<string>("web_name");
                    
                    var currentPrice = p.GetPropertyValue<double>("now_cost") / 10;
                    var costChangeSinceStart = p.GetPropertyValue<double>("cost_change_start") / 10;

                    object indexInfo = new PremierLeagueFantasyIndex
                    {
                        EaIndex = new Assignable<double>(p.GetPropertyValue<double>("ea_index")),
                        Influence = new Assignable<double>(p.GetPropertyValue<double>("influence")),
                        Creativity = new Assignable<double>(p.GetPropertyValue<double>("creativity")),
                        Threat = new Assignable<double>(p.GetPropertyValue<double>("threat")),
                    };

                    player.Fantasy                      = new FantasyPlayer
                    {
                        Position                        = pos,
                        CurrentPrice                    = currentPrice,
                        OriginalPrice                   = currentPrice + costChangeSinceStart,
                        Unavailable                     = p.GetPropertyValue<string>("status") != "a",
                        ChanceOfPlayingNextFixture      = p.GetPropertyValue<double>("chance_of_playing_this_round", -1) / 100,
                        News                            = p.GetPropertyValue<string>("news"),
                        OwnagePercent                   = p.GetPropertyValue<double>("selected_by_percent", -1),
                        TransfersDetailsForSeason       = new TransferDetails
                        {
                            TransfersIn                 = p.GetPropertyValue<int>("transfers_in"),
                            TransfersOut                = p.GetPropertyValue<int>("transfers_out"),
                        },
                        TransfersDetailsForGW           = new TransferDetails
                        {
                            TransfersIn                 = p.GetPropertyValue<int>("transfers_in_event"),
                            TransfersOut                = p.GetPropertyValue<int>("transfers_out_event"),
                        },
                        IndexInfo = indexInfo,
                    };

                    player.Statistics                   = new PlayerStatistics
                    {
                        PlayedMinutes                   = p.GetPropertyValue<int>("minutes"),
                        Goals                           = p.GetPropertyValue<int>("goals_scored"),
                        Assists                         = p.GetPropertyValue<int>("assists"),
                        TimesInDreamteam                = p.GetPropertyValue<int>("dreamteam_count"),
                        YellowCards                     = p.GetPropertyValue<int>("yellow_cards"),
                        RedCards                        = p.GetPropertyValue<int>("red_cards"),
                        BonusPoints                     = p.GetPropertyValue<int>("bonus"),
                        Form                            = p.GetPropertyValue<double>("form"),
                        PenaltiesMissed                 = p.GetPropertyValue<int>("penalties_missed"),
                        PenaltiesSaved                  = p.GetPropertyValue<int>("penalties_scored"),
                        Saves                           = p.GetPropertyValue<int>("saves"),
                        TotalPoints                     = p.GetPropertyValue<int>("total_points"),
                        CleanSheets                     = p.GetPropertyValue<int>("clean_sheets"),
                        PointsPerGame                   = p.GetPropertyValue<double>("points_per_game"),
                        OwnGoals                        = p.GetPropertyValue<int>("own_goals"),


                        // todo:
                        //Appearances = "",
                        //Crosses = 
                        //Offsides = 
                        //PenaltiesScored = 
                        //Substitutions = 
                        //Shots = 
                    };

                    var teamID = p.GetPropertyValue<string>("team");
                    var team = teams.SingleOrDefault(x => x.ID == teamID);
                    if (team != null)
                    {
                        player.Team = team;
                        team.Players = team.Players.Append(player);
                    }
                    else
                    {
                        
                    }

                    // Update Team statistics   (todo: will get wrong if player changes team)
                    //team.Statistics.GoalsFor = player.Statistics.Goals;
                }
            }



            // Fixtures
            if (fixturesJson != null)
            {
                var fixtures = fixturesJson.GetPropertyValue<JArray>("fixtures");
                foreach (var f in fixtures)
                {
                    try
                    {
                        var fixture = new Fixture();

                        var obj = f.ToObjectOrDefault<JObject>();
                        fixture.Time = obj.GetPropertyValue<DateTime>("date");

                        var homeTeamName = obj.GetPropertyValue<string>("homeTeamName");
                        var awayTeamName = obj.GetPropertyValue<string>("awayTeamName");
                        var homeTeam = leagueTeams.SingleOrDefault(x => x.Team.Name == homeTeamName || x.Team.MatchName(homeTeamName));
                        var awayTeam = leagueTeams.SingleOrDefault(x => x.Team.Name == awayTeamName || x.Team.MatchName(awayTeamName));
                        fixture.HomeTeam = homeTeam;
                        fixture.AwayTeam = awayTeam;

                        var resultsJson = obj.GetPropertyValue<JObject>("result");
                        var status = obj.GetPropertyValue<string>("status");
                        var finished = status == "FINISHED";
                        var min = obj.GetPropertyValue<int>("minute");      // todo: correct?
                        if (finished && min <= 0)
                            min = 90;
                        var goalsHome = resultsJson?.GetPropertyValue<int>("goalsHomeTeam") ?? 0;
                        var goalsAway = resultsJson?.GetPropertyValue<int>("goalsAwayTeam") ?? 0;
                        fixture.Statistics = new FixtureStatistics
                        {
                            PlayedMinutes = min,
                            GameFinished = finished,
                            Score = FixtureScore.Create(goalsHome, goalsAway),
                        };


                        var matchday = obj.GetPropertyValue<int>("matchday");
                        var gw = gameweeks.SingleOrDefault(x => x.Number == matchday);
                        if (gw == null)
                        {
                            gw = new Gameweek(league)
                            {
                                Number = matchday,
                            };
                            gameweeks.Add(gw);
                        }
                        fixture.Gameweek = gw;
                        gw.Fixtures = gw.Fixtures.Append(fixture);


                        // Update Team statistics
                        if (fixture.HomeTeam != null && fixture.AwayTeam != null)
                        {
                            fixture.HomeTeam.UpdateStatisticsBasedOnFixture(fixture);
                            fixture.AwayTeam.UpdateStatisticsBasedOnFixture(fixture);
                        }
                        else
                        {

                        }
                    }
                    catch (Exception ex)
                    {
                        throw;
                    }
                }
            }
            

            
            league.Teams = leagueTeams.ToArray();
            league.Gameweeks = gameweeks.ToArray();
            return league;
        }
 public static LeagueTeam GetLeagueTeam(this Player player, League league)
 {
     var leaugeTeam = league.Teams.FirstOrDefault(x => x.Team?.ID == player.Team?.ID);
     return leaugeTeam;
 }
 public Gameweek(League league)
 {
     League = league;
     Fixtures = new List<Fixture>().ToArray();
 }
        public async Task<SoccerSimulationData> Generate()
        {
            var league = new League
            {
                Name = "Sample League",
                Year = DateTime.Now.Year,
            };

            #region Players

            var teams = new List<Team>
            {
                new Team
                {
                    ID = "MCI",
                    Name = "Manchester City",
                    Rating = (Rating) 9,
                    Players = new List<Player>
                    {
                        new Player
                        {
                            ID = "SILVA",
                            DisplayName = "David Silva",
                            Rating = (Rating) 8,
                            CurrentPrice = 9.0,
                            Position = PlayerPosition.Midfielder,
                        },

                        new Player
                        {
                            ID = "KOMPANY",
                            DisplayName = "Vincent Kompany",
                            Rating = (Rating) 7,
                            CurrentPrice = 7.0,
                            Position = PlayerPosition.Defender,
                        },
                    }.ToArray(),
                },


                new Team
                {
                    ID = "CHE",
                    Name = "Chelsea",
                    Rating = (Rating) 9,
                    Players = new List<Player>
                    {
                        new Player
                        {
                            ID = "HAZARD",
                            DisplayName = "Eden Hazard",
                            Rating = (Rating) 9,
                            OriginalPrice = 11.0,
                            CurrentPrice = 11.0,
                            Position = PlayerPosition.Midfielder,
                        },

                    }.ToArray(),
                },


                new Team
                {
                    ID = "LIV",
                    Name = "Liverpool",
                    Rating = (Rating) 8,
                    Players = new List<Player>
                    {
                        new Player
                        {
                            ID = "MIGNOLET",
                            DisplayName = "Simon Mignolet",
                            Rating = (Rating) 7,
                            OriginalPrice = 5.0,
                            CurrentPrice = 5.0,
                            Position = PlayerPosition.Goalkeeper,
                        },

                        new Player
                        {
                            ID = "HENDERSON",
                            DisplayName = "Jordan Henderson",
                            Rating = (Rating) 7,
                            OriginalPrice = 7.0,
                            CurrentPrice = 7.0,
                            Position = PlayerPosition.Midfielder,
                        },

                        new Player
                        {
                            ID = "COUTINHO",
                            DisplayName = "Philipe Couthinho",
                            Rating = (Rating) 8,
                            OriginalPrice = 8.5,
                            CurrentPrice = 8.5,
                            Position = PlayerPosition.Midfielder,
                        },

                    }.ToArray(),
                },


                new Team
                {
                    ID = "BOU",
                    Name = "AFC Bournemouth",
                    Rating = (Rating) 4,
                    Players = new List<Player>
                    {
                        new Player
                        {
                            ID = "RICHE",
                            DisplayName = "Matt Richie",
                            Rating = (Rating) 7,
                            OriginalPrice = 5.0,
                            CurrentPrice = 5.0,
                            Position = PlayerPosition.Midfielder,
                        },

                        new Player
                        {
                            ID = "WILSON",
                            DisplayName = "Calum Wilson",
                            Rating = (Rating) 6,
                            OriginalPrice = 5.5,
                            CurrentPrice = 5.5,
                            Position = PlayerPosition.Forward,
                        },

                    }.ToArray(),
                },

            }.ToArray();


            foreach (var team in teams)
            {
                foreach (var player in team.Players)
                {
                    player.Team = team;
                }
            }

            var leagueTeams = teams.Select(x => new LeagueTeam(league, x)).ToList();

            #endregion
            

            #region Gameweeks

            var gameweeks = new List<Gameweek>
            {
                new Gameweek(league)
                {
                    Number = 1,
                    Fixtures = new List<Fixture>
                    {
                        new Fixture
                        {
                            HomeTeam = leagueTeams.Single(x => x.Team.ID == "MCI"),
                            AwayTeam = leagueTeams.Single(x => x.Team.ID == "CHE"),
                            Statistics = new FixtureStatistics
                            {
                                GameFinished = true,
                                PlayedMinutes = 90,
                                Score = new FixtureScore
                                {
                                    GoalsForHomeTeam = 2,
                                    GoalsForAwayTeam = 2,
                                },
                            },
                        },

                        new Fixture
                        {
                            HomeTeam = leagueTeams.Single(x => x.Team.ID == "LIV"),
                            AwayTeam = leagueTeams.Single(x => x.Team.ID == "BOU"),
                            Statistics = new FixtureStatistics
                            {
                                GameFinished = false,
                                PlayedMinutes = 74,
                                Score = new FixtureScore
                                {
                                    GoalsForHomeTeam = 3,
                                    GoalsForAwayTeam = 0,
                                },
                            },
                        },

                    }.ToArray(),
                },

                new Gameweek(league)
                {
                    Number = 2,
                    Fixtures = new List<Fixture>
                    {
                        new Fixture
                        {
                            HomeTeam = leagueTeams.Single(x => x.Team.ID == "BOU"),
                            AwayTeam = leagueTeams.Single(x => x.Team.ID == "MCI"),
                        },

                        new Fixture
                        {
                            HomeTeam = leagueTeams.Single(x => x.Team.ID == "CHE"),
                            AwayTeam = leagueTeams.Single(x => x.Team.ID == "LIV"),
                        },
                    }.ToArray(),
                },

                new Gameweek(league)
                {
                    Number = 3,
                    Fixtures = new List<Fixture>
                    {
                        new Fixture
                        {
                            HomeTeam = leagueTeams.Single(x => x.Team.ID == "LIV"),
                            AwayTeam = leagueTeams.Single(x => x.Team.ID == "MCI"),
                        },

                        new Fixture
                        {
                            HomeTeam = leagueTeams.Single(x => x.Team.ID == "BOU"),
                            AwayTeam = leagueTeams.Single(x => x.Team.ID == "CHE"),
                        },
                    }.ToArray(),
                },

            }.ToArray();


            foreach (var week in gameweeks)
            {
                foreach (var fixture in week.Fixtures)
                {
                    fixture.Gameweek = week;
                }
            }

            #endregion


            league.Teams = leagueTeams.ToArray();
            league.Gameweeks = gameweeks;

            var simulationData = new SoccerSimulationData();
            simulationData.Leagues = simulationData.Leagues.Append(league);
            //simulationData.Teams = teams;
            //simulationData.Gameweeks = gameweeks;
            return simulationData;
        }