public static void UpdateDungeonRunDeck(DungeonInfo info, bool isPVPDR)
        {
            if (!Config.Instance.DungeonAutoImport)
            {
                return;
            }

            var isNewPVPDR = isPVPDR && !info.RunActive && info.SelectedLoadoutTreasureDbId > 0;

            Log.Info($"Found dungeon run deck Set={(CardSet)info.CardSet}, PVPDR={isPVPDR} (new={isNewPVPDR})");

            var allCards = info.DbfIds?.ToList() ?? new List <int>();

            // New PVPDR runs have all non-loadout cards in the DbfIds. We still add the picked loadout below.
            // So we don't want to replace allCards with baseDeck, as backDeck is empty, and we don't want to add
            // any loot or treasure, as these will be the ones from a previous run, if they exist.
            if (!isNewPVPDR)
            {
                var baseDeck = info.SelectedDeck ?? new List <int>();
                if (baseDeck.All(x => allCards.Contains(x)))
                {
                    if (info.PlayerChosenLoot > 0)
                    {
                        var loot   = new[] { info.LootA, info.LootB, info.LootC };
                        var chosen = loot[info.PlayerChosenLoot - 1];
                        for (var i = 1; i < chosen.Count; i++)
                        {
                            allCards.Add(chosen[i]);
                        }
                    }
                    if (info.PlayerChosenTreasure > 0)
                    {
                        allCards.Add(info.Treasure[info.PlayerChosenTreasure - 1]);
                    }
                }
                else
                {
                    allCards = baseDeck;
                }
            }

            var cards = allCards.GroupBy(x => x).Select(x =>
            {
                var card = Database.GetCardFromDbfId(x.Key, false);
                if (card == null)
                {
                    return(null);
                }
                card.Count = x.Count();
                return(card);
            }).Where(x => x != null).ToList();

            var loadoutCardId = info.LoadoutCardId;
            var loadout       = loadoutCardId != null?Database.GetCardFromId(loadoutCardId) : null;

            if (loadout != null && !allCards.Contains(loadout.DbfIf))
            {
                cards.Add(loadout);
            }

            if (!Config.Instance.DungeonRunIncludePassiveCards)
            {
                cards.RemoveAll(c => !c.Collectible && c.HideStats);
            }

            var cardSet = (CardSet)info.CardSet;

            string playerClass = null;

            if (cardSet == CardSet.ULDUM && loadout != null)
            {
                playerClass = DungeonRun.GetUldumHeroPlayerClass(loadout.PlayerClass);
            }
            else if (isPVPDR)
            {
                playerClass = HearthDbConverter.ConvertClass((CardClass)(info.HeroClass != 0 ? info.HeroClass : info.HeroCardClass));
            }
            else
            {
                if (allCards.Count == 10)
                {
                    playerClass = allCards.Select(x => Database.GetCardFromDbfId(x).PlayerClass).FirstOrDefault(x => x != null)?.ToUpperInvariant();
                }
                if (playerClass == null)
                {
                    playerClass = ((CardClass)info.HeroCardClass).ToString().ToUpperInvariant();
                }
            }

            var deck = DeckList.Instance.Decks.FirstOrDefault(x => (!isPVPDR && x.IsDungeonDeck || isPVPDR && x.IsDuelsDeck) && x.Class.ToUpperInvariant() == playerClass.ToUpperInvariant() &&
                                                              x.Cards.All(e => cards.Any(c => c.Id == e.Id && c.Count >= e.Count)) &&
                                                              !(x.IsDungeonRunCompleted ?? false) &&
                                                              !(x.IsDuelsRunCompleted ?? false));
            var baseDbfids = isPVPDR ? info.DbfIds : info.SelectedDeck;

            if (deck == null && (deck = CreateDungeonDeck(playerClass, cardSet, isPVPDR, baseDbfids, loadout)) == null)
            {
                Log.Info($"No existing deck - can't find default deck for {playerClass}");
                return;
            }
            if (!info.RunActive && (cardSet == CardSet.ULDUM || cardSet == CardSet.DALARAN))
            {
                Log.Info($"Inactive run for Set={cardSet.ToString()} - this is a new run");
                return;
            }
            if (cards.All(c => deck.Cards.Any(e => c.Id == e.Id && c.Count == e.Count)))
            {
                Log.Info("No new cards");
                return;
            }
            deck.Cards.Clear();
            Helper.SortCardCollection(cards, false);
            foreach (var card in cards)
            {
                deck.Cards.Add(card);
            }
            deck.LastEdited = DateTime.Now;
            DeckList.Save();
            Core.UpdatePlayerCards(true);
            Log.Info("Updated dungeon run deck");
        }
        public static Deck Import(string cards, bool localizedNames = false)
        {
            CardClass[] AvailableClasses(Card x)
            {
                var card = HearthDb.Cards.GetFromDbfId(x.DbfIf);

                switch ((MultiClassGroup)card.Entity.GetTag(GameTag.MULTI_CLASS_GROUP))
                {
                case MultiClassGroup.GRIMY_GOONS:
                    return(new[] { CardClass.WARRIOR, CardClass.HUNTER, CardClass.PALADIN });

                case MultiClassGroup.JADE_LOTUS:
                    return(new[] { CardClass.ROGUE, CardClass.DRUID, CardClass.SHAMAN });

                case MultiClassGroup.KABAL:
                    return(new[] { CardClass.MAGE, CardClass.PRIEST, CardClass.WARLOCK });

                case MultiClassGroup.PALADIN_PRIEST:
                    return(new[] { CardClass.PALADIN, CardClass.PRIEST });

                case MultiClassGroup.PRIEST_WARLOCK:
                    return(new[] { CardClass.PRIEST, CardClass.WARLOCK });

                case MultiClassGroup.WARLOCK_DEMONHUNTER:
                    return(new[] { CardClass.WARLOCK, CardClass.DEMONHUNTER });

                case MultiClassGroup.HUNTER_DEMONHUNTER:
                    return(new[] { CardClass.HUNTER, CardClass.DEMONHUNTER });

                case MultiClassGroup.DRUID_HUNTER:
                    return(new[] { CardClass.DRUID, CardClass.HUNTER });

                case MultiClassGroup.DRUID_SHAMAN:
                    return(new[] { CardClass.DRUID, CardClass.SHAMAN });

                case MultiClassGroup.MAGE_SHAMAN:
                    return(new[] { CardClass.MAGE, CardClass.SHAMAN });

                case MultiClassGroup.MAGE_ROGUE:
                    return(new[] { CardClass.MAGE, CardClass.ROGUE });

                case MultiClassGroup.ROGUE_WARRIOR:
                    return(new[] { CardClass.ROGUE, CardClass.WARRIOR });

                case MultiClassGroup.PALADIN_WARRIOR:
                    return(new[] { CardClass.PALADIN, CardClass.WARRIOR });

                default:
                    return(new[] { card.Class });
                }
            }

            try
            {
                var deck  = new Deck();
                var lines = cards.Split(Separators, StringSplitOptions.RemoveEmptyEntries);
                foreach (var line in lines)
                {
                    var   count    = 1;
                    var   cardName = line.Trim();
                    Match match    = null;
                    if (CardLineRegexCountFirst.IsMatch(cardName))
                    {
                        match = CardLineRegexCountFirst.Match(cardName);
                    }
                    else if (CardLineRegexCountLast.IsMatch(cardName))
                    {
                        match = CardLineRegexCountLast.Match(cardName);
                    }
                    if (match != null)
                    {
                        var tmpCount = match.Groups["count"];
                        if (tmpCount.Success)
                        {
                            count = int.Parse(tmpCount.Value);
                        }
                        cardName = match.Groups["cardname"].Value.Trim();
                    }

                    var card = Database.GetCardFromName(cardName.Replace("’", "'"), localizedNames);
                    if (string.IsNullOrEmpty(card?.Name) || card.Id == Database.UnknownCardId)
                    {
                        continue;
                    }
                    card.Count = count;

                    if (deck.Cards.Contains(card))
                    {
                        var deckCard = deck.Cards.First(c => c.Equals(card));
                        deck.Cards.Remove(deckCard);
                        deckCard.Count += count;
                        deck.Cards.Add(deckCard);
                    }
                    else
                    {
                        deck.Cards.Add(card);
                    }
                }
                var deckClass = deck.Cards
                                .Where(x => x.DbfIf != 0)
                                .Select(AvailableClasses)
                                .Where(x => x.Length > 1 || x[0] != CardClass.NEUTRAL)
                                .Aggregate((a, b) => a.Concat(b).GroupBy(x => x).Where(x => x.Count() > 1).Select(x => x.Key).ToArray());
                if (deckClass.Length > 1)
                {
                    Log.Warn("Could not identify a class for this deck. Found multiple potential classes: " + string.Join(", ", deckClass.Select(HearthDbConverter.ConvertClass)));
                    return(null);
                }
                else if (deckClass.Length == 0)
                {
                    Log.Warn("Could not identify a class for this deck. Found conflicting classes.");
                    return(null);
                }
                else
                {
                    deck.Class = HearthDbConverter.ConvertClass(deckClass[0]);
                    return(deck);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex);
                return(null);
            }
        }