public EntityBuilder(string cardid, int attack, int health)
		{
			_instance = new Entity();
			_instance.SetTag(GameTag.ATK, attack);
			_instance.SetTag(GameTag.HEALTH, health);
			_cardId = cardid;
		}
		public static bool IsHero(Entity e)
		{
			return e.HasTag(GAME_TAG.CARDTYPE)
				 && e.GetTag(GAME_TAG.CARDTYPE) == (int)TAG_CARDTYPE.HERO
				 && e.HasTag(GAME_TAG.ZONE)
				 && e.GetTag(GAME_TAG.ZONE) == (int)TAG_ZONE.PLAY;
		}
		public ReplayKeyPoint(Entity[] data, KeyPointType type, int id, ActivePlayer player)
		{
			if(data != null)
				Data = Helper.DeepClone(data);
			Type = type;
			Id = id;
			Player = player;
		}
		public BoardHero(Entity hero, Entity weapon, bool activeTurn)
		{
			_hero = new BoardCard(hero, activeTurn);
			// hero gains windfury with weapon, doubling attack get base attack
			_baseAttack = hero.GetTag(GameTag.ATK);
			if(weapon != null)
				_weapon = new BoardCard(weapon, activeTurn);
			Include = activeTurn && _hero.Include;
			Attack = AttackWithWeapon();
		}
        public void Setup()
        {
            _game = new GameV2();
            _gameEventHandler = new GameEventHandler(_game);

            _heroPlayer = CreateNewEntity("HERO_01");
            _heroPlayer.SetTag(GAME_TAG.CARDTYPE, (int) TAG_CARDTYPE.HERO);
            _heroPlayer.IsPlayer = true;
            _heroOpponent = CreateNewEntity("HERO_02");
            _heroOpponent.SetTag(GAME_TAG.CARDTYPE, (int) TAG_CARDTYPE.HERO);
            _heroOpponent.IsPlayer = false;

            _game.Entities.Add(0, _heroPlayer);
            _game.Player.Id = _heroPlayer.Id;
            _game.Entities.Add(1, _heroOpponent);
            _game.Opponent.Id = _heroOpponent.Id;

            _playerMinion1 = CreateNewEntity("EX1_010");
            _playerMinion1.SetTag(GAME_TAG.CARDTYPE, (int)TAG_CARDTYPE.MINION);
            _playerMinion1.SetTag(GAME_TAG.CONTROLLER, _heroPlayer.Id);
            _opponentMinion1 = CreateNewEntity("EX1_020");
            _opponentMinion1.SetTag(GAME_TAG.CARDTYPE, (int)TAG_CARDTYPE.MINION);
            _opponentMinion1.SetTag(GAME_TAG.CONTROLLER, _heroOpponent.Id);
            _opponentMinion2 = CreateNewEntity("EX1_021");
            _opponentMinion2.SetTag(GAME_TAG.CARDTYPE, (int)TAG_CARDTYPE.MINION);
            _opponentMinion2.SetTag(GAME_TAG.CONTROLLER, _heroOpponent.Id);

            _game.Entities.Add(2, _playerMinion1);
            _game.Entities.Add(3, _opponentMinion1);
            _game.Entities.Add(4, _opponentMinion2);

            _secretHunter1 = CreateNewEntity("");
            _secretHunter1.SetTag(GAME_TAG.CLASS, (int) TAG_CLASS.HUNTER);
            _secretHunter2 = CreateNewEntity("");
            _secretHunter2.SetTag(GAME_TAG.CLASS, (int) TAG_CLASS.HUNTER);
            _secretMage1 = CreateNewEntity("");
            _secretMage1.SetTag(GAME_TAG.CLASS, (int) TAG_CLASS.MAGE);
            _secretMage2 = CreateNewEntity("");
            _secretMage2.SetTag(GAME_TAG.CLASS, (int) TAG_CLASS.MAGE);
            _secretPaladin1 = CreateNewEntity("");
            _secretPaladin1.SetTag(GAME_TAG.CLASS, (int) TAG_CLASS.PALADIN);
            _secretPaladin2 = CreateNewEntity("");
            _secretPaladin2.SetTag(GAME_TAG.CLASS, (int) TAG_CLASS.PALADIN);

            _gameEventHandler.HandleOpponentSecretPlayed(_secretHunter1, "", 0, 0, false, _secretHunter1.Id);
            _gameEventHandler.HandleOpponentSecretPlayed(_secretMage1, "", 0, 0, false, _secretMage1.Id);
            _gameEventHandler.HandleOpponentSecretPlayed(_secretPaladin1, "", 0, 0, false, _secretPaladin1.Id);
        }
		public void Setup()
		{
			_entities = new Dictionary<int, Entity>();
			_entities[0] = new Entity(0);
			_entities[0].SetTag(GameTag.FIRST_PLAYER, 1);
			_entities[0].IsPlayer = true;
			_entities[1] = new Entity(1);
			_entities[1].Name = "GameEntity";
			_entities[1].SetTag(GameTag.TURN, 11);

			_player = new List<Entity>();
			_player.Add(new EntityBuilder("", 3, 1).InPlay().Charge().ToEntity());
			_player.Add(new EntityBuilder("", 4, 5).InPlay().ToEntity());
			_player.Add(new EntityBuilder("", 3, 2).InPlay().Exhausted().ToEntity());

			_opponent = new List<Entity>();
			_opponent.Add(new EntityBuilder("", 7, 5).InPlay().ToEntity());
			_opponent.Add(new EntityBuilder("", 3, 1).InPlay().Windfury().AttacksThisTurn(1).ToEntity());
			_opponent.Add(new EntityBuilder("", 2, 2).InPlay().Exhausted().ToEntity());
		}
		public void Setup()
		{
			Core.Game = null;
			_game = new GameV2();
			Core.Game = _game;
			_game.Player.Id = 0;


			_entities = new Dictionary<int, Entity>();
			_entities[0] = new Entity(0);
			_entities[0].SetTag(GameTag.FIRST_PLAYER, 1);
			_entities[1] = new Entity(1);
			_entities[1].Name = "GameEntity";
			_entities[1].SetTag(GameTag.TURN, 11);

			_heroA = new Entity(4);
			_heroA.CardId = "HERO_08";
			_heroA.Name = null;
			_heroA.SetTag(GameTag.HEALTH, 30);
			_heroA.SetTag(GameTag.ZONE, 1);
			_heroA.SetTag(GameTag.CONTROLLER, 1);
			_heroA.SetTag(GameTag.ENTITY_ID, 4);
			_heroA.SetTag(GameTag.CARDTYPE, 3);
			_heroA.SetTag(GameTag.DAMAGE, 7);
			_heroA.SetTag(GameTag.ARMOR, 0);

			_heroB = new Entity(36);
			_heroB.CardId = "HERO_03";
			_heroB.Name = null;
			_heroB.SetTag(GameTag.HEALTH, 30);
			_heroB.SetTag(GameTag.ZONE, 1);
			_heroB.SetTag(GameTag.CONTROLLER, 2);
			_heroB.SetTag(GameTag.ENTITY_ID, 36);
			_heroB.SetTag(GameTag.CARDTYPE, 3);
			_heroB.SetTag(GameTag.DAMAGE, 14);
			_heroB.SetTag(GameTag.ARMOR, 0);
			_heroB.SetTag(GameTag.ATK, 1);
			_heroB.SetTag(GameTag.EXHAUSTED, 1);
		}
		public void PlayToGraveyard(Entity entity, string cardId, int turn)
		{
			entity.Info.Turn = turn;
			Log(entity);
		}
		public void RemoveFromPlay(Entity entity, int turn)
		{
			entity.Info.Turn = turn;
			Log(entity);
		}
		public void SecretPlayedFromDeck(Entity entity, int turn)
		{
			UpdateKnownEntitesInDeck(entity.CardId);
			entity.Info.Turn = turn;
			Log(entity);
		}
		public void SecretPlayedFromHand(Entity entity, int turn)
		{
			entity.Info.Turn = turn;
			SpellsPlayedCount++;
			Log(entity);
		}
		public void Draw(Entity entity, int turn)
		{
			if(IsLocalPlayer)
				UpdateKnownEntitesInDeck(entity.CardId);
			if(!IsLocalPlayer)
			{
				if(_game.OpponentEntity?.GetTag(GameTag.MULLIGAN_STATE) == (int)HearthDb.Enums.Mulligan.DEALING)
					entity.Info.Mulliganed = true;
				else
					entity.Info.Hidden = true;
			}
			entity.Info.Turn = turn;
			Log(entity);
		}
		public void SecretTriggered(Entity entity, int turn)
		{
			entity.Info.Turn = turn;
			Log(entity);
		}
		public CardEntity(string cardId, Entity entity)
		{
			CardId = (string.IsNullOrEmpty(cardId) && entity != null) ? entity.CardId : cardId;
			Entity = entity;
			Turn = -1;
			CardMark = (entity != null && entity.Id > 68) ? CardMark.Created : CardMark.None;
		}
		public void DeckToPlay(Entity entity, int turn)
		{
			UpdateKnownEntitesInDeck(entity.CardId);
			entity.Info.Turn = turn;
			Log(entity);
		}
		public void Mulligan(Entity entity) => Log(entity);
		public void HandDiscard(Entity entity, int turn)
		{
			if(!IsLocalPlayer)
				UpdateKnownEntitesInDeck(entity.CardId, entity.Info.Turn);
			entity.Info.Turn = turn;
			entity.Info.Discarded = true;
			Log(entity);
		}
		public void RemoveFromDeck(Entity entity, int turn)
		{
			//Do not check for KnownCardIds here, this is how jousted cards get removed from the deck
			entity.Info.Turn = turn;
			entity.Info.Discarded = true;
			Log(entity);
		}
		public void CreateInSecret(Entity entity, int turn)
		{
			entity.Info.Created = true;
			entity.Info.Turn = turn;
			Log(entity);
		}
		public void CreateInDeck(Entity entity, int turn)
		{
			entity.Info.Created |= turn > 1;
			entity.Info.Turn = turn;
			Log(entity);
		}
		public void StolenFromOpponent(Entity entity, int turn)
		{
			entity.Info.Turn = turn;
			Log(entity);
		}
		private void Log(Entity entity, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "") 
			=> Log(entity.ToString(), memberName, sourceFilePath);
		public EntityBuilder()
		{
			_instance = new Entity();
		}
		public void Play(Entity entity, int turn)
		{
			if(!IsLocalPlayer)
				UpdateKnownEntitesInDeck(entity.CardId, entity.Info.Turn);
			switch(entity.GetTag(GameTag.CARDTYPE))
			{
				case (int)CardType.TOKEN:
					entity.Info.Created = true;
					break;
				case (int)CardType.SPELL:
					SpellsPlayedCount++;
					break;
			}
			entity.Info.Hidden = false;
			entity.Info.Turn = turn;
			Log(entity);
		}
		private void SetFlavorTextEntity(Entity entity)
		{
			if(!Config.Instance.ShowFlavorText)
				return;
			FlavorText = entity.Card.FlavorText;
			FlavorTextCardName = entity.Card.LocalizedName;
			FlavorTextVisibility = Visible;
		}
		public void JoustReveal(Entity entity, int turn)
		{
			entity.Info.Turn = turn;
			var card = InDeckPrecitions.FirstOrDefault(x => x.CardId == entity.CardId);
			if(card != null)
				card.Turn = turn;
			else
				InDeckPrecitions.Add(new PredictedCard(entity.CardId, turn));
			Log(entity);
		}
		public void DeckDiscard(Entity entity, int turn)
		{
			UpdateKnownEntitesInDeck(entity.CardId);
			entity.Info.Turn = turn;
			entity.Info.Discarded = true;
			Log(entity);
		}
		public void Update(Entity entity = null)
		{
			if(entity == null)
				return;
			if(Entity == null)
				Entity = entity;
			if(string.IsNullOrEmpty(CardId))
				CardId = entity.CardId;
		}
		public static bool IsHero(Entity e) => e.HasTag(CARDTYPE) && e.GetTag(CARDTYPE) == (int)CardType.HERO && e.HasTag(ZONE)
											   && e.GetTag(ZONE) == (int)Zone.PLAY;
		public void BoardToHand(Entity entity, int turn)
		{
			entity.Info.Turn = turn;
			entity.Info.Returned = true;
			Log(entity);
		}