public PlayByPlayWindow(
            Dictionary<int, TeamStats> tst, Dictionary<int, PlayerStats> pst, BoxScoreEntry bse, int t1ID, int t2ID)
            : this()
        {
            _tst = tst;
            _pst = pst;
            _bse = bse;
            _t1ID = t1ID;
            _t2ID = t2ID;
            Plays = new ObservableCollection<PlayByPlayEntry>(bse.PBPEList);

            Height = Tools.GetRegistrySetting("PBPHeight", MinHeight);
            Width = Tools.GetRegistrySetting("PBPWidth", MinWidth);
            Left = Tools.GetRegistrySetting("PBPX", Left);
            Top = Tools.GetRegistrySetting("PBPY", Top);
        }
 private static object getValue(BoxScoreEntry bse, string parameter)
 {
     return bse.BS.GetType().GetProperty(parameter).GetValue(bse.BS, null);
 }
        /// <summary>
        ///     Creates a team box score and all the required player box score instances using data from the downloaded DataSet.
        /// </summary>
        /// <param name="ds">The DataSet.</param>
        /// <param name="parts">The parts of the split date string.</param>
        /// <param name="bse">The resulting BoxScoreEntry.</param>
        /// <returns>0 if every required player was found in the database; otherwise, -1.</returns>
        private static int boxScoreFromDataSet(DataSet ds, string[] parts, out BoxScoreEntry bse)
        {
            DataTable awayDT = ds.Tables[0];
            DataTable homeDT = ds.Tables[1];

            var bs = new TeamBoxScore(ds, parts);
            bse = new BoxScoreEntry(bs) {Date = bs.GameDate, PBSList = new List<PlayerBoxScore>()};
            int result = 0;
            for (int i = 0; i < awayDT.Rows.Count - 1; i++)
            {
                if (i == 5)
                {
                    continue;
                }
                var pbs = new PlayerBoxScore(awayDT.Rows[i], bs.Team1ID, bs.ID, (i < 5), MainWindow.PST);
                if (pbs.PlayerID == -1)
                {
                    result = -1;
                    continue;
                }
                bse.PBSList.Add(pbs);
            }
            for (int i = 0; i < homeDT.Rows.Count - 1; i++)
            {
                if (i == 5)
                {
                    continue;
                }
                var pbs = new PlayerBoxScore(homeDT.Rows[i], bs.Team2ID, bs.ID, (i < 5), MainWindow.PST);
                if (pbs.PlayerID == -1)
                {
                    result = -1;
                    continue;
                }
                bse.PBSList.Add(pbs);
            }
            return result;
        }
        private void extractFromBoxScoreEntry(
            BoxScoreEntry bse,
            ref Dictionary<int, TeamStats> advtst,
            ref Dictionary<int, TeamStats> advtstOpp,
            ref Dictionary<int, PlayerStats> advpst,
            ref Dictionary<int, TeamStats> advPPtst,
            ref Dictionary<int, TeamStats> advPPtstOpp,
            bool doPlays)
        {
            var team1ID = bse.BS.Team1ID;
            var team2ID = bse.BS.Team2ID;
            var bs = bse.BS;
            if (!advtst.ContainsKey(team1ID))
            {
                advtst.Add(
                    team1ID,
                    new TeamStats
                        {
                            ID = team1ID,
                            Name = MainWindow.TST[team1ID].Name,
                            DisplayName = MainWindow.TST[team1ID].DisplayName
                        });
                advtstOpp.Add(
                    team1ID,
                    new TeamStats
                        {
                            ID = team1ID,
                            Name = MainWindow.TST[team1ID].Name,
                            DisplayName = MainWindow.TST[team1ID].DisplayName
                        });
            }
            var ts1 = advtst[team1ID];
            var ts1Opp = advtstOpp[team1ID];
            if (!advtst.ContainsKey(team2ID))
            {
                //advTeamOrder.Add(MainWindow.tst[team2ID].name, advTeamOrder.Any() ? advTeamOrder.Values.Max() + 1 : 0);
                advtst.Add(
                    team2ID,
                    new TeamStats
                        {
                            ID = team2ID,
                            Name = MainWindow.TST[team2ID].Name,
                            DisplayName = MainWindow.TST[team2ID].DisplayName
                        });
                advtstOpp.Add(
                    team2ID,
                    new TeamStats
                        {
                            ID = team2ID,
                            Name = MainWindow.TST[team2ID].Name,
                            DisplayName = MainWindow.TST[team2ID].DisplayName
                        });
            }
            var ts2 = advtst[team2ID];
            var ts2Opp = advtstOpp[team2ID];
            if (!doPlays)
            {
                TeamStats.AddTeamStatsFromBoxScore(bs, ref ts1, ref ts2, true);
                TeamStats.AddTeamStatsFromBoxScore(bs, ref ts2Opp, ref ts1Opp, true);
            }
            foreach (var pbs in bse.PBSList)
            {
                if (advpst.All(pair => pair.Key != pbs.PlayerID))
                {
                    advpst.Add(pbs.PlayerID, MainWindow.PST[pbs.PlayerID].CustomClone());
                    advpst[pbs.PlayerID].ResetStats();
                }
                if (!doPlays)
                {
                    advpst[pbs.PlayerID].AddBoxScore(pbs, false);
                }

                var teamID = pbs.TeamID;
                if (!advPPtst.ContainsKey(pbs.PlayerID))
                {
                    advPPtst.Add(
                        pbs.PlayerID,
                        new TeamStats
                            {
                                ID = teamID,
                                Name = MainWindow.TST[teamID].Name,
                                DisplayName = MainWindow.TST[teamID].DisplayName
                            });
                }
                if (!advPPtstOpp.ContainsKey(pbs.PlayerID))
                {
                    advPPtstOpp.Add(
                        pbs.PlayerID,
                        new TeamStats
                            {
                                ID = teamID,
                                Name = MainWindow.TST[teamID].Name,
                                DisplayName = MainWindow.TST[teamID].DisplayName
                            });
                }
                if (!doPlays)
                {
                    var ts = advPPtst[pbs.PlayerID];
                    var tsopp = advPPtstOpp[pbs.PlayerID];
                    if (team1ID == pbs.TeamID)
                    {
                        TeamStats.AddTeamStatsFromBoxScore(bs, ref ts, ref tsopp, true);
                    }
                    else
                    {
                        TeamStats.AddTeamStatsFromBoxScore(bs, ref tsopp, ref ts, true);
                    }
                }
            }

            if (doPlays)
            {
                /*
                if (cmbPlayer1.SelectedIndex > 0)
                {
                    var curPlayer1ID = ((KeyValuePair<int, string>) ((cmbPlayer1).SelectedItem)).Key;
                    if (advpst.All(pair => pair.Key != curPlayer1ID))
                    {
                        advpst.Add(curPlayer1ID, MainWindow.PST[curPlayer1ID].CustomClone());
                        advpst[curPlayer1ID].ResetStats();
                    }
                }
                if (cmbPlayer2.SelectedIndex > 0)
                {
                    var curPlayer2ID = ((KeyValuePair<int, string>) ((cmbPlayer2).SelectedItem)).Key;
                    if (advpst.All(pair => pair.Key != curPlayer2ID))
                    {
                        advpst.Add(curPlayer2ID, MainWindow.PST[curPlayer2ID].CustomClone());
                        advpst[curPlayer2ID].ResetStats();
                    }
                }
                */
                var tempbse = bse.BinarySerializationClone();

                // Calculate
                for (var i = 0; i < tempbse.PBSList.Count; i++)
                {
                    var pbs = tempbse.PBSList[i];
                    if (advpst.ContainsKey(pbs.PlayerID) == false)
                    {
                        continue;
                    }
                    pbs.CalculateFromPBPEList(tempbse.FilteredPBPEList);
                    advpst[pbs.PlayerID].AddBoxScore(pbs, false);
                }
                var teamBoxScore = tempbse.BS;
                BoxScoreWindow.CalculateTeamsFromPlayers(
                    ref teamBoxScore,
                    tempbse.PBSList.Where(pbs => pbs.TeamID == team1ID).ToList(),
                    tempbse.PBSList.Where(pbs => pbs.TeamID == team2ID).ToList());
                TeamStats.AddTeamStatsFromBoxScore(tempbse.BS, ref ts1, ref ts2, true);
                TeamStats.AddTeamStatsFromBoxScore(tempbse.BS, ref ts2Opp, ref ts1Opp, true);
                foreach (var pbs in tempbse.PBSList)
                {
                    var ts = advPPtst[pbs.PlayerID];
                    var tsopp = advPPtstOpp[pbs.PlayerID];
                    if (team1ID == pbs.TeamID)
                    {
                        TeamStats.AddTeamStatsFromBoxScore(bs, ref ts, ref tsopp, true);
                    }
                    else
                    {
                        TeamStats.AddTeamStatsFromBoxScore(bs, ref tsopp, ref ts, true);
                    }
                }
            }
        }
        /// <summary>
        ///     Initializes a new instance of the <see cref="BoxScoreWindow" /> class.
        /// </summary>
        /// <param name="bse">The Box Score Entry from which to load the box score to be viewed.</param>
        /// <param name="onImport">
        ///     if set to <c>true</c>, a box score is being imported into the database, and the window is prepared accordingly.
        /// </param>
        public BoxScoreWindow(BoxScoreEntry bse, bool onImport = false)
            : this()
        {
            _bseToLoad = bse;
            _onImport = onImport;

            if (onImport)
            {
                chkDoNotUpdate.IsEnabled = false;
                cmbSeasonNum.IsEnabled = false;
                cmbTeam1.IsEnabled = false;
                cmbTeam2.IsEnabled = false;
                btnCalculateTeams_Click(null, null);
            }
        }
        /// <summary>Loads the given box score.</summary>
        /// <param name="bse">The BoxScoreEntry to load.</param>
        private void loadBoxScore(BoxScoreEntry bse)
        {
            var bs = bse.BS;
            MainWindow.TempBSE_BS = bse.BS;
            FillTeamBoxScore(bs);

            dtpGameDate.SelectedDate = bs.GameDate;
            _curSeason = bs.SeasonNum;
            //LinkInternalsToMainWindow();
            chkIsPlayoff.IsChecked = bs.IsPlayoff;

            calculateScoreAway();
            calculateScoreHome();

            pbsAwayList = new SortableBindingList<PlayerBoxScore>();
            pbsHomeList = new SortableBindingList<PlayerBoxScore>();

            pbsAwayList.AllowNew = true;
            pbsAwayList.AllowEdit = true;
            pbsAwayList.AllowRemove = true;
            pbsAwayList.RaiseListChangedEvents = true;

            pbsHomeList.AllowNew = true;
            pbsHomeList.AllowEdit = true;
            pbsHomeList.AllowRemove = true;
            pbsHomeList.RaiseListChangedEvents = true;

            dgvPlayersAway.ItemsSource = pbsAwayList;
            dgvPlayersHome.ItemsSource = pbsHomeList;
            _loading = true;
            foreach (var pbs in bse.PBSList)
            {
                if (pbs.TeamID == bs.Team1ID)
                {
                    pbsAwayList.Add(pbs);
                }
                else
                {
                    pbsHomeList.Add(pbs);
                }
            }

            pbsAwayList.Sort((pbs1, pbs2) => (pbs2.MINS - pbs1.MINS));
            pbsHomeList.Sort((pbs1, pbs2) => (pbs2.MINS - pbs1.MINS));

            try
            {
                cmbTeam1.SelectedItem = MainWindow.TST[bs.Team1ID].DisplayName;
                cmbTeam2.SelectedItem = MainWindow.TST[bs.Team2ID].DisplayName;
            }
            catch
            {
                MessageBox.Show(
                    "One of the teams requested is disabled for this season. This box score is not available.\n"
                    + "To be able to see this box score, enable the teams included in it.");
                Close();
            }
            populateSeasonCombo();

            pbpeList = new ObservableCollection<PlayByPlayEntry>(bse.PBPEList);
            pbpeList.Sort(new PlayByPlayEntryComparerAsc());
            lstPlayByPlay.ItemsSource = pbpeList;

            _loading = false;
        }
        /// <summary>
        ///     Parses the local box score instance; adds the stats to the according teams and players and adds the box score to the box
        ///     score history.
        /// </summary>
        private async Task parseBoxScoreResult()
        {
            if (TempBSE_BS.Done == false)
            {
                return;
            }

            IsEnabled = false;

            var id1 = TempBSE_BS.Team1ID;
            var id2 = TempBSE_BS.Team2ID;

            var list = TempBSE_PBSLists.SelectMany(pbsList => pbsList).ToList();

            if (!TempBSE_BS.DoNotUpdate)
            {
                TeamStats.AddTeamStatsFromBoxScore(TempBSE_BS, ref TST, ref TSTOpp, id1, id2);

                foreach (var pbs in list)
                {
                    if (pbs.PlayerID == -1)
                    {
                        continue;
                    }
                    PST[pbs.PlayerID].AddBoxScore(pbs, TempBSE_BS.IsPlayoff);
                }
            }

            if (TempBSE_BS.ID == -1)
            {
                TempBSE_BS.ID = getFreeBseID();
            }

            if (BSHist.Any(bse => bse.BS.ID == TempBSE_BS.ID) == false)
            {
                var bse = new BoxScoreEntry(TempBSE_BS, list, TempBSE_PBPEList);
                BSHist.Add(bse);
            }
            else
            {
                BSHist.Single(bse => bse.BS.ID == TempBSE_BS.ID).BS = TempBSE_BS;
            }

            startProgressWatchTimer();
            ProgressHelper.Progress = new ProgressInfo(0, "Inserting box score to database...");
            await
                Task.Run(() => SQLiteIO.SaveSeasonToDatabase(CurrentDB, TST, TSTOpp, PST, CurSeason, SQLiteIO.GetMaxSeason(CurrentDB)));
            await UpdateAllData();
            UpdateStatus("One or more Box Scores have been added/updated. Database saved.");
            StopProgressWatchTimer();
            IsEnabled = true;
        }
        /// <summary>
        ///     Calculates the box score by comparing the participating team's current and previous team and player stats.
        /// </summary>
        /// <param name="tst">The team stats dictionary.</param>
        /// <param name="oldTST">The old team stats dictionary.</param>
        /// <param name="pst">The player stats dictionary.</param>
        /// <param name="oldPST">The old player stats dictionary.</param>
        /// <param name="t1">The away team ID.</param>
        /// <param name="t2">The home team ID.</param>
        /// <returns></returns>
        private static BoxScoreEntry prepareBoxScore(Dictionary<int, TeamStats> tst, Dictionary<int, TeamStats> oldTST,
                                                     Dictionary<int, PlayerStats> pst, Dictionary<int, PlayerStats> oldPST, int t1,
                                                     int t2)
        {
            bool isPlayoff = (tst[t1].GetPlayoffGames() > 0);
            var bs = new TeamBoxScore
                {
                    IsPlayoff = isPlayoff,
                    Team1ID = t1,
                    MINS1 = getDiff(tst, oldTST, t1, TAbbr.MINS, isPlayoff),
                    Team2ID = t2,
                    MINS2 = getDiff(tst, oldTST, t2, TAbbr.MINS, isPlayoff)
                };

            var bse = new BoxScoreEntry(bs) {PBSList = new List<PlayerBoxScore>()};

            /*
                        var team1Players = pst.Where(pair => pair.Value.TeamF == bs.Team1);
                        var team2Players = pst.Where(pair => pair.Value.TeamF == bs.Team2);
                        */

            IEnumerable<KeyValuePair<int, PlayerStats>> bothTeamsPlayers =
                pst.Where(pair => pair.Value.TeamF == bs.Team1ID || pair.Value.TeamF == bs.Team2ID);
            foreach (var playerKVP in bothTeamsPlayers)
            {
                KeyValuePair<int, PlayerStats> oldplayerKVP = oldPST.Single(pair => pair.Value.ID == playerKVP.Value.ID);

                PlayerStats newPlayer = playerKVP.Value;
                PlayerStats oldPlayer = oldplayerKVP.Value;

                PlayerBoxScore pbs;
                if (getDiff(newPlayer, oldPlayer, PAbbr.GP) == 1)
                {
                    pbs = new PlayerBoxScore
                        {
                            PlayerID = newPlayer.ID,
                            TeamID = newPlayer.TeamF,
                            IsStarter = (getDiff(newPlayer, oldPlayer, PAbbr.GS) == 1),
                            PlayedInjured = newPlayer.Injury.IsInjured,
                            MINS = getDiff(newPlayer, oldPlayer, PAbbr.MINS),
                            PTS = getDiff(newPlayer, oldPlayer, PAbbr.PTS),
                            OREB = getDiff(newPlayer, oldPlayer, PAbbr.OREB),
                            DREB = getDiff(newPlayer, oldPlayer, PAbbr.DREB),
                            AST = getDiff(newPlayer, oldPlayer, PAbbr.AST),
                            STL = getDiff(newPlayer, oldPlayer, PAbbr.STL),
                            BLK = getDiff(newPlayer, oldPlayer, PAbbr.BLK),
                            TOS = getDiff(newPlayer, oldPlayer, PAbbr.TOS),
                            FGM = getDiff(newPlayer, oldPlayer, PAbbr.FGM),
                            FGA = getDiff(newPlayer, oldPlayer, PAbbr.FGA),
                            TPM = getDiff(newPlayer, oldPlayer, PAbbr.TPM),
                            TPA = getDiff(newPlayer, oldPlayer, PAbbr.TPA),
                            FTM = getDiff(newPlayer, oldPlayer, PAbbr.FTM),
                            FTA = getDiff(newPlayer, oldPlayer, PAbbr.FTA),
                            FOUL = getDiff(newPlayer, oldPlayer, PAbbr.FOUL)
                        };
                    pbs.REB = (ushort) (pbs.OREB + pbs.DREB);
                    pbs.FGp = (float) pbs.FGM/pbs.FGA;
                    pbs.TPp = (float) pbs.TPM/pbs.TPA;
                    pbs.FTp = (float) pbs.FTM/pbs.FTA;
                }
                else
                {
                    pbs = new PlayerBoxScore {PlayerID = newPlayer.ID, TeamID = newPlayer.TeamF, IsOut = true};
                }

                bse.PBSList.Add(pbs);
            }
            bse.Date = DateTime.Today;
            bse.BS.GameDate = bse.Date;
            bse.BS.SeasonNum = MainWindow.CurSeason;

            return bse;
        }
        /// <summary>
        ///     Parses the local box score instance; adds the stats to the according teams and players and adds the box score to the box score history.
        /// </summary>
        private void parseBoxScoreResult()
        {
            if (bs.Done == false)
            {
                return;
            }

            IsEnabled = false;

            int id1 = bs.Team1ID;
            int id2 = bs.Team2ID;

            List<PlayerBoxScore> list = PBSLists.SelectMany(pbsList => pbsList).ToList();

            if (!bs.DoNotUpdate)
            {
                TeamStats.AddTeamStatsFromBoxScore(bs, ref TST, ref TSTOpp, id1, id2);

                foreach (PlayerBoxScore pbs in list)
                {
                    if (pbs.PlayerID == -1)
                    {
                        continue;
                    }
                    PST[pbs.PlayerID].AddBoxScore(pbs, bs.IsPlayoff);
                }
            }

            if (bs.BSHistID == -1)
            {
                var bse = new BoxScoreEntry(bs, bs.GameDate, list);
                BSHist.Add(bse);
            }
            else
            {
                BSHist[bs.BSHistID].BS = bs;
            }

            StartProgressWatchTimer();
            ProgressHelper.Progress = new ProgressInfo(0, "Inserting box score to database...");
            Task.Factory.StartNew(
                () => SQLiteIO.SaveSeasonToDatabase(CurrentDB, TST, TSTOpp, PST, CurSeason, SQLiteIO.GetMaxSeason(CurrentDB)))
                .ContinueWith(t => UpdateAllData())
                .ContinueWith(t => finishParsingBoxScore(), UIScheduler)
                .FailFastOnException(UIScheduler);
        }
        /// <summary>
        ///     Initializes a new instance of the <see cref="BoxScoreWindow" /> class.
        /// </summary>
        /// <param name="bse">The Box Score Entry from which to load the box score to be viewed.</param>
        /// <param name="pst">The player stats dictionary to use for this instance.</param>
        /// <param name="onImport">
        ///     if set to <c>true</c>, a box score is being imported into the database, and the window is prepared accordingly.
        /// </param>
        public BoxScoreWindow(BoxScoreEntry bse, Dictionary<int, PlayerStats> pst, bool onImport)
            : this()
        {
            _pst = pst;

            loadBoxScore(bse);
            _onImport = onImport;

            if (onImport)
            {
                MainWindow.bs = bse.BS;
                chkDoNotUpdate.IsEnabled = false;
                cmbSeasonNum.IsEnabled = false;
                cmbTeam1.IsEnabled = false;
                cmbTeam2.IsEnabled = false;
                btnCalculateTeams_Click(null, null);
            }

            btnOK_Click(null, null);
        }
        /// <summary>
        ///     Loads the given box score.
        /// </summary>
        /// <param name="bse">The BoxScoreEntry to load.</param>
        private void loadBoxScore(BoxScoreEntry bse)
        {
            TeamBoxScore bs = bse.BS;
            MainWindow.bs = bse.BS;
            txtPTS1.Text = bs.PTS1.ToString();
            txtREB1.Text = bs.REB1.ToString();
            txtAST1.Text = bs.AST1.ToString();
            txtSTL1.Text = bs.STL1.ToString();
            txtBLK1.Text = bs.BLK1.ToString();
            txtTO1.Text = bs.TOS1.ToString();
            txtFGM1.Text = bs.FGM1.ToString();
            txtFGA1.Text = bs.FGA1.ToString();
            txt3PM1.Text = bs.TPM1.ToString();
            txt3PA1.Text = bs.TPA1.ToString();
            txtFTM1.Text = bs.FTM1.ToString();
            txtFTA1.Text = bs.FTA1.ToString();
            txtOREB1.Text = bs.OREB1.ToString();
            txtFOUL1.Text = bs.FOUL1.ToString();
            txtMINS1.Text = bs.MINS1.ToString();
            txtPTS2.Text = bs.PTS2.ToString();
            txtREB2.Text = bs.REB2.ToString();
            txtAST2.Text = bs.AST2.ToString();
            txtSTL2.Text = bs.STL2.ToString();
            txtBLK2.Text = bs.BLK2.ToString();
            txtTO2.Text = bs.TOS2.ToString();
            txtFGM2.Text = bs.FGM2.ToString();
            txtFGA2.Text = bs.FGA2.ToString();
            txt3PM2.Text = bs.TPM2.ToString();
            txt3PA2.Text = bs.TPA2.ToString();
            txtFTM2.Text = bs.FTM2.ToString();
            txtFTA2.Text = bs.FTA2.ToString();
            txtOREB2.Text = bs.OREB2.ToString();
            txtFOUL2.Text = bs.FOUL2.ToString();
            txtMINS2.Text = bs.MINS2.ToString();

            dtpGameDate.SelectedDate = bs.GameDate;
            _curSeason = bs.SeasonNum;
            //LinkInternalsToMainWindow();
            chkIsPlayoff.IsChecked = bs.IsPlayoff;

            calculateScoreAway();
            calculateScoreHome();

            pbsAwayList = new SortableBindingList<PlayerBoxScore>();
            pbsHomeList = new SortableBindingList<PlayerBoxScore>();

            pbsAwayList.AllowNew = true;
            pbsAwayList.AllowEdit = true;
            pbsAwayList.AllowRemove = true;
            pbsAwayList.RaiseListChangedEvents = true;

            pbsHomeList.AllowNew = true;
            pbsHomeList.AllowEdit = true;
            pbsHomeList.AllowRemove = true;
            pbsHomeList.RaiseListChangedEvents = true;

            dgvPlayersAway.ItemsSource = pbsAwayList;
            dgvPlayersHome.ItemsSource = pbsHomeList;
            _loading = true;
            foreach (PlayerBoxScore pbs in bse.PBSList)
            {
                if (pbs.TeamID == bs.Team1ID)
                {
                    pbsAwayList.Add(pbs);
                }
                else
                {
                    pbsHomeList.Add(pbs);
                }
            }

            pbsAwayList.Sort((pbs1, pbs2) => (pbs2.MINS - pbs1.MINS));
            pbsHomeList.Sort((pbs1, pbs2) => (pbs2.MINS - pbs1.MINS));

            try
            {
                cmbTeam1.SelectedItem = MainWindow.TST[bs.Team1ID].DisplayName;
                cmbTeam2.SelectedItem = MainWindow.TST[bs.Team2ID].DisplayName;
            }
            catch
            {
                MessageBox.Show("One of the teams requested is disabled for this season. This box score is not available.\n" +
                                "To be able to see this box score, enable the teams included in it.");
                Close();
            }
            populateSeasonCombo();

            _loading = false;
        }