internal DeckStats Add(Deck deck)
        {
            var ds = new DeckStats(deck);

            Instance.DeckStats.TryAdd(deck.DeckId, ds);
            return(ds);
        }
		public DeckStats GetDeckStats(string hero)
		{
			if(string.IsNullOrEmpty(hero))
				return null;
			var ds = DeckStats.FirstOrDefault(d => d.Name == hero);
			if(ds != null)
				return ds;
			ds = new DeckStats {Name = hero};
			DeckStats.Add(ds);
			return ds;
		}
		public DeckStats GetDeckStats(string hero)
		{
			if(!Enum.GetNames(typeof(HeroClass)).Contains(hero))
				return null;
			var ds = DeckStats.FirstOrDefault(d => d.Name == hero);
			if(ds == null)
			{
				ds = new DeckStats {Name = hero};
				DeckStats.Add(ds);
			}
			return ds;
		}
        public DeckStats GetDeckStats(string hero)
        {
            if (!Enum.GetNames(typeof(HeroClass)).Contains(hero))
            {
                return(null);
            }
            var ds = DeckStats.FirstOrDefault(d => d.Name == hero);

            if (ds == null)
            {
                ds = new DeckStats(hero);
                DeckStats.Add(ds);
            }
            return(ds);
        }
        public DeckStats GetDeckStats(string hero)
        {
            if (string.IsNullOrEmpty(hero))
            {
                return(null);
            }
            var ds = DeckStats.FirstOrDefault(d => d.Name == hero);

            if (ds != null)
            {
                return(ds);
            }
            ds = new DeckStats {
                Name = hero
            };
            DeckStats.Add(ds);
            return(ds);
        }
        public static Deck[] CreateStats(List<DeckStats> list)
        {
            // Deck A - no stats
            var deckA = new Deck();
            deckA.Name = "DeckA";
            var deckAStats = new DeckStats(deckA);

            // Deck B - a single game
            var deckB = new Deck();
            deckB.Name = "DeckB";
            var deckBStats = new DeckStats(deckB);
            deckBStats.Games = new List<GameStats>()
            {
                CreateGame(deckB.DeckId, Region.EU, GameMode.Ranked, 2)
            };

            // Deck C - multiple games
            var deckC = new Deck();
            deckC.Name = "DeckC";
            var deckCStats = new DeckStats(deckC);
            deckCStats.Games = new List<GameStats>()
            {
                CreateGame(deckC.DeckId, Region.EU, GameMode.Arena, 2),
                CreateGame(deckC.DeckId, Region.EU, GameMode.Arena, 4),
                CreateGame(deckC.DeckId, Region.US, GameMode.Ranked, 7),
                CreateGame(deckC.DeckId, Region.ASIA, GameMode.Ranked, 30),
                CreateGame(deckC.DeckId, Region.US, GameMode.Casual, 1),
                CreateGame(deckC.DeckId, Region.UNKNOWN, GameMode.Casual, 1),
                CreateGame(deckC.DeckId, Region.EU, GameMode.Ranked, 2),
                CreateGame(deckC.DeckId, Region.EU, GameMode.Ranked, 80),
            };

            list.Add(deckAStats);
            list.Add(deckBStats);
            list.Add(deckCStats);

            return new Deck[] { deckA, deckB, deckC };
        }
		private async void BtnCloneDeck_Click(object sender, RoutedEventArgs e)
		{
			var clone = (Deck)DeckPickerList.SelectedDeck.Clone();
			var originalStatsEntry = clone.DeckStats;

			while(DeckList.DecksList.Any(d => d.Name == clone.Name))
			{
				var settings = new MetroDialogSettings {AffirmativeButtonText = "Set", DefaultText = clone.Name};
				var name =
					await
					this.ShowInputAsync("Name already exists",
					                    "You already have a deck with that name, please select a different one.", settings);

				if(String.IsNullOrEmpty(name))
					return;

				clone.Name = name;
			}

			DeckList.DecksList.Add(clone);
			DeckPickerList.AddAndSelectDeck(clone);
			WriteDecks();

			//clone game stats
			var newStatsEntry = DeckStatsList.Instance.DeckStats.FirstOrDefault(d => d.Name == clone.Name);
			if(newStatsEntry == null)
			{
				newStatsEntry = new DeckStats(clone.Name);
				DeckStatsList.Instance.DeckStats.Add(newStatsEntry);
			}
			foreach(var game in originalStatsEntry.Games)
				newStatsEntry.AddGameResult(game.CloneWithNewId());
			Logger.WriteLine("cloned gamestats");

			DeckStatsList.Save();
			DeckPickerList.UpdateList();
		}
		internal async void BtnCloneSelectedVersion_Click(object sender, RoutedEventArgs e)
		{
			var deck = DeckPickerList.SelectedDecks.FirstOrDefault();

			if(deck == null)
				return;
	
			deck = deck.GetSelectedDeckVersion();

			var cloneStats =
				(await
				 this.ShowMessageAsync("Clone game history?", "(Cloned games do not count towards class or overall stats.)",
				                       MessageDialogStyle.AffirmativeAndNegative,
				                       new MetroDialogSettings
				                       {
					                       AffirmativeButtonText = "clone history",
					                       NegativeButtonText = "do not clone history"
				                       })) == MessageDialogResult.Affirmative;

			var clone = (Deck)deck.CloneWithNewId(false);

			clone.ResetVersions();
			clone.ResetHearthstatsIds();
			clone.Archived = false;

			var originalStatsEntry = clone.DeckStats;

			DeckList.Instance.Decks.Add(clone);
			DeckPickerList.UpdateDecks();
			DeckList.Save();

			var newStatsEntry = DeckStatsList.Instance.DeckStats.FirstOrDefault(ds => ds.BelongsToDeck(clone));
			if(newStatsEntry == null)
			{
				newStatsEntry = new DeckStats(clone);
				DeckStatsList.Instance.DeckStats.Add(newStatsEntry);
			}

			//clone game stats
			if(cloneStats)
			{
				foreach(var game in originalStatsEntry.Games)
					newStatsEntry.AddGameResult(game.CloneWithNewId());
				Logger.WriteLine("cloned gamestats (version)", "Edit");
			}

			DeckStatsList.Save();
			//DeckPickerList.UpdateList();
			DeckPickerList.SelectDeckAndAppropriateView(clone);

			if(Config.Instance.HearthStatsAutoUploadNewDecks && HearthStatsAPI.IsLoggedIn)
				HearthStatsManager.UploadDeckAsync(clone);
		}
		public async void SaveDeck(bool overwrite, SerializableVersion newVersion, bool workInProgressDeck = false)
		{
			var deckName = TextBoxDeckName.Text;

			if(string.IsNullOrEmpty(deckName))
			{
				var settings = new MetroDialogSettings {AffirmativeButtonText = "Set", DefaultText = deckName};

				var name = await this.ShowInputAsync("No name set", "Please set a name for the deck", settings);

				if(string.IsNullOrEmpty(name))
					return;

				deckName = name;
				TextBoxDeckName.Text = name;
			}

			if(_newDeck.Cards.Sum(c => c.Count) != 30 && workInProgressDeck == false)
			{
				var settings = new MetroDialogSettings {AffirmativeButtonText = "Yes", NegativeButtonText = "No"};

				var result =
					await
					this.ShowMessageAsync("Not 30 cards",
					                      string.Format("Deck contains {0} cards. Is this what you want to save anyway?",
					                                    _newDeck.Cards.Sum(c => c.Count)), MessageDialogStyle.AffirmativeAndNegative, settings);
				if(result != MessageDialogResult.Affirmative)
					return;
			}

			var previousVersion = _newDeck.Version;
			if(overwrite && (_newDeck.Version != newVersion))
			{
				AddDeckHistory();
				_newDeck.Version = newVersion;
				_newDeck.SelectedVersion = newVersion;
				_newDeck.HearthStatsDeckVersionId = "";
			}

			if(EditingDeck && overwrite)
				DeckList.Instance.Decks.Remove(_newDeck);

			var oldDeckName = _newDeck.Name;

			_newDeck.Name = deckName;

			var newDeckClone = (Deck)_newDeck.Clone();
			newDeckClone.Archived = false;

			DeckList.Instance.Decks.Add(newDeckClone);

			newDeckClone.LastEdited = DateTime.Now;

			DeckList.Save();

			Logger.WriteLine("Saved Decks", "SaveDeck");

			if(EditingDeck)
			{
				TagControlEdit.SetSelectedTags(new List<string>());
				if(deckName != oldDeckName)
				{
					var statsEntry = DeckStatsList.Instance.DeckStats.FirstOrDefault(ds => ds.BelongsToDeck(_newDeck));
					if(statsEntry != null)
					{
						if(overwrite)
						{
							statsEntry.Name = deckName;
							Logger.WriteLine("Deck has new name, updated deckstats", "SaveDeck");
							foreach(var game in statsEntry.Games)
								game.DeckName = deckName;
						}
						else
						{
							var newStatsEntry = DeckStatsList.Instance.DeckStats.FirstOrDefault(ds => ds.BelongsToDeck(_newDeck));
							if(newStatsEntry == null)
							{
								newStatsEntry = new DeckStats(_newDeck);
								DeckStatsList.Instance.DeckStats.Add(newStatsEntry);
							}
							foreach(var game in statsEntry.Games)
								newStatsEntry.AddGameResult(game.CloneWithNewId());
							Logger.WriteLine("cloned gamestats for \"Set as new\"", "SaveDeck");
						}
						DeckStatsList.Save();
					}
				}
			}


			if(Config.Instance.HearthStatsAutoUploadNewDecks && HearthStatsAPI.IsLoggedIn)
			{
				Logger.WriteLine("auto uploading new/edited deck", "SaveDeck");
				if(EditingDeck)
				{
					if(previousVersion != newVersion)
						HearthStatsManager.UploadVersionAsync(newDeckClone, _originalDeck.HearthStatsIdForUploading, background: true);
					else
						HearthStatsManager.UpdateDeckAsync(newDeckClone, background: true);
				}
				else
					HearthStatsManager.UploadDeckAsync(newDeckClone, background: true);
			}

			//after cloning the stats, otherwise new stats will be generated
			//DeckPickerList.AddAndSelectDeck(newDeckClone);
			if(EditingDeck)
				DeckManagerEvents.OnDeckUpdated.Execute(newDeckClone);
			else
				DeckManagerEvents.OnDeckCreated.Execute(newDeckClone);


			EditingDeck = false;

			foreach(var tag in _newDeck.Tags)
				SortFilterDecksFlyout.AddSelectedTag(tag);

			DeckPickerList.SelectDeckAndAppropriateView(newDeckClone);
			DeckPickerList.UpdateDecks(forceUpdate: new[] {newDeckClone});
			CloseNewDeck();
			ClearNewDeckSection();
		}
		public void RemoveDeck(DeckStats deck) => RemoveDeck(deck.DeckId);
		private async void SaveDeck(bool overwrite)
		{
			var deckName = TextBoxDeckName.Text;

			if(string.IsNullOrEmpty(deckName))
			{
				var settings = new MetroDialogSettings {AffirmativeButtonText = "Set", DefaultText = deckName};

				var name = await this.ShowInputAsync("No name set", "Please set a name for the deck", settings);

				if(String.IsNullOrEmpty(name))
					return;

				deckName = name;
				TextBoxDeckName.Text = name;
			}

			while(DeckList.DecksList.Any(d => d.Name == deckName) && (!EditingDeck || !overwrite))
			{
				var settings = new MetroDialogSettings {AffirmativeButtonText = "Set", DefaultText = deckName};
				var name =
					await
					this.ShowInputAsync("Name already exists", "You already have a deck with that name, please select a different one.", settings);

				if(String.IsNullOrEmpty(name))
					return;

				deckName = name;
				TextBoxDeckName.Text = name;
			}

			if(NewDeck.Cards.Sum(c => c.Count) != 30)
			{
				var settings = new MetroDialogSettings {AffirmativeButtonText = "Yes", NegativeButtonText = "No"};

				var result =
					await
					this.ShowMessageAsync("Not 30 cards",
					                      string.Format("Deck contains {0} cards. Is this what you want to save anyway?",
					                                    NewDeck.Cards.Sum(c => c.Count)),
					                      MessageDialogStyle.AffirmativeAndNegative, settings);
				if(result != MessageDialogResult.Affirmative)
					return;
			}

			if(EditingDeck && overwrite)
			{
				DeckList.DecksList.Remove(NewDeck);
				DeckPickerList.RemoveDeck(NewDeck);
			}

			var oldDeckName = NewDeck.Name;

			NewDeck.Name = deckName;
			NewDeck.Class = ComboBoxSelectClass.SelectedValue.ToString();
			NewDeck.Tags = TagControlNewDeck.GetTags();

			var newDeckClone = (Deck)NewDeck.Clone();
			DeckList.DecksList.Add(newDeckClone);

			newDeckClone.LastEdited = DateTime.Now;

			WriteDecks();
			Logger.WriteLine("Saved Decks");
			BtnSaveDeck.Content = "Save";

			if(EditingDeck)
			{
				TagControlNewDeck.SetSelectedTags(new List<string>());
				if(deckName != oldDeckName)
				{
					var statsEntry = DeckStatsList.Instance.DeckStats.FirstOrDefault(d => d.Name == oldDeckName);
					if(statsEntry != null)
					{
						if(overwrite)
						{
							statsEntry.Name = deckName;
							Logger.WriteLine("Deck has new name, updated deckstats");
						}
						else
						{
							var newStatsEntry = DeckStatsList.Instance.DeckStats.FirstOrDefault(d => d.Name == deckName);
							if(newStatsEntry == null)
							{
								newStatsEntry = new DeckStats(deckName);
								DeckStatsList.Instance.DeckStats.Add(newStatsEntry);
							}
							foreach(var game in statsEntry.Games)
								newStatsEntry.AddGameResult(game.CloneWithNewId());
							Logger.WriteLine("cloned gamestats for \"Set as new\"");
						}
						DeckStatsList.Save();
					}
				}
			}

			//after cloning the stats, otherwise new stats will be generated
			DeckPickerList.AddAndSelectDeck(newDeckClone);

			TabControlTracker.SelectedIndex = 0;
			EditingDeck = false;

			foreach(var tag in NewDeck.Tags)
				SortFilterDecksFlyout.AddSelectedTag(tag);

			DeckPickerList.UpdateList();
			DeckPickerList.SelectDeck(newDeckClone);

			ClearNewDeckSection();
		}
 public void RemoveDeck(DeckStats deck) => RemoveDeck(deck.DeckId);
		internal DeckStats Add(Deck deck)
		{
			var ds = new DeckStats(deck);
			Instance.DeckStats.TryAdd(deck.DeckId, ds);
			return ds;
		}
		internal async void BtnCloneDeck_Click(object sender, RoutedEventArgs e)
		{
			var deck = DeckPickerList.SelectedDecks.FirstOrDefault();

			if(deck == null)
				return;
			var cloneStats =
				(await
				 this.ShowMessageAsync("Clone game history?", "(Cloned games do not count towards class or overall stats.)",
				                       MessageDialogStyle.AffirmativeAndNegative,
				                       new MessageDialogs.Settings
				                       {
					                       AffirmativeButtonText = "clone history",
					                       NegativeButtonText = "do not clone history"
				                       })) == MessageDialogResult.Affirmative;

			var clone = (Deck)deck.CloneWithNewId(false);

			clone.ResetHearthstatsIds();
			clone.Versions.ForEach(v => v.ResetHearthstatsIds());
			clone.Archived = false;

			var originalStats = deck.DeckStats;

			DeckList.Instance.Decks.Add(clone);
			DeckList.Save();

			DeckStats newStatsEntry;
			if(!DeckStatsList.Instance.DeckStats.TryGetValue(clone.DeckId, out newStatsEntry))
			{
				newStatsEntry = new DeckStats(clone);
				DeckStatsList.Instance.DeckStats.TryAdd(clone.DeckId, newStatsEntry);
			}

			if(cloneStats)
			{
				foreach(var game in originalStats.Games)
					newStatsEntry.AddGameResult(game.CloneWithNewId());
				Log.Info("cloned gamestats");
			}

			DeckStatsList.Save();
			DeckPickerList.SelectDeckAndAppropriateView(clone);

			if(Config.Instance.HearthStatsAutoUploadNewDecks && HearthStatsAPI.IsLoggedIn)
				HearthStatsManager.UploadDeckAsync(clone).Forget();
		}
		internal async void BtnCloneSelectedVersion_Click(object sender, RoutedEventArgs e)
		{
			var deck = DeckPickerList.SelectedDecks.FirstOrDefault();
			if(deck == null)
				return;
			var cloneStats =
				(await
				 this.ShowMessageAsync("Clone game history?", "(Cloned games do not count towards class or overall stats.)",
				                       MessageDialogStyle.AffirmativeAndNegative,
				                       new MetroDialogSettings
				                       {
					                       AffirmativeButtonText = "clone history",
					                       NegativeButtonText = "do not clone history"
				                       })) == MessageDialogResult.Affirmative;
			var clone = (Deck)deck.CloneWithNewId(false);
			// bug #1316 - ResetVersions needs the current version as an argument
			clone.ResetVersions();
			clone.ResetHearthstatsIds();
			clone.Archived = false;

			var originalStatsEntry = clone.DeckStats;

			/*while(DeckList.DecksList.Any(d => d.Name == clone.Name))
			{
				var settings = new MetroDialogSettings {AffirmativeButtonText = "Set", DefaultText = clone.Name};
				var name =
					await
					this.ShowInputAsync("Name already exists", "You already have a deck with that name, please select a different one.", settings);

				if(string.IsNullOrEmpty(name))
					return;

				clone.Name = name;
			}*/

			DeckList.Instance.Decks.Add(clone);
			DeckPickerList.UpdateDecks();
			DeckList.Save();


			var newStatsEntry = DeckStatsList.Instance.DeckStats.FirstOrDefault(ds => ds.BelongsToDeck(clone));
			if(newStatsEntry == null)
			{
				newStatsEntry = new DeckStats(clone);
				DeckStatsList.Instance.DeckStats.Add(newStatsEntry);
			}

			//clone game stats
			if(cloneStats)
			{
				foreach(var game in originalStatsEntry.Games)
					newStatsEntry.AddGameResult(game.CloneWithNewId());
				Logger.WriteLine("cloned gamestats (version)", "Edit");
			}

			DeckStatsList.Save();
			//DeckPickerList.UpdateList();
			DeckPickerList.SelectDeckAndAppropriateView(clone);

			if(Config.Instance.HearthStatsAutoUploadNewDecks && HearthStatsAPI.IsLoggedIn)
				HearthStatsManager.UploadDeckAsync(clone);
		}