import { ReferenceCard } from '@firestone-hs/reference-data' ; import { CardsFacadeService } from '@services/cards-facade.service' ; import { DeckCard } from '../../../models/decktracker/deck-card' ; import { DeckState } from '../../../models/decktracker/deck-state' ; import { GameState } from '../../../models/decktracker/game-state' ; import { GameEvent } from '../../../models/game-event' ; import { LocalizationFacadeService } from '../../localization-facade.service' ; import { DeckManipulationHelper } from './deck-manipulation-helper' ; import { EventParser } from './event-parser' ; export class CardBackToDeckParser implements EventParser { constructor ( private readonly helper , private readonly allCards , private readonly i18n ) { } applies ( gameEvent , state ) { return state && gameEvent . type === GameEvent . CARD_BACK_TO_DECK ; } async parse ( currentState , gameEvent ) { const [ cardId , controllerId , localPlayer , entityId ] = gameEvent . parse ( ) ; const initialZone = gameEvent . additionalData . initialZone ; const isPlayer = controllerId === localPlayer . PlayerId ; const deck = isPlayer ? currentState . playerDeck : currentState . opponentDeck ; const card = this . findCard ( initialZone , deck , cardId , entityId ) ; const newHand = this . buildNewHand ( initialZone , deck . hand , card ) ; const newBoard = this . buildNewBoard ( initialZone , deck . board , card ) ; const newOther = this . buildNewOther ( initialZone , deck . otherZone , card ) ; const previousDeck = deck . deck ; const shouldKeepDeckAsIs = deck . deckstring && card ?. inInitialDeck && ! card ?. cardId ; const cardWithoutInfluence = card ? card . update ( { lastAffectedByCardId : undefined , } as DeckCard ) : card ; const newDeck = shouldKeepDeckAsIs ? previousDeck : this . helper . addSingleCardToZone ( previousDeck , cardWithoutInfluence ) ; const newPlayerDeck = Object . assign ( new DeckState ( ) , deck , { deck : newDeck , hand : newHand , board : newBoard , otherZone : newOther , } as DeckState ) ; return Object . assign ( new GameState ( ) , currentState , { [ isPlayer ? 'playerDeck' : 'opponentDeck' ] : newPlayerDeck , } ) ; } event ( ) { return GameEvent . CARD_BACK_TO_DECK ; } private findCard ( initialZone , deckState , cardId , entityId ) { let result = null ; if ( initialZone === 'HAND' ) { result = this . helper . findCardInZone ( deckState . hand , cardId , entityId ) ; } else if ( initialZone === 'PLAY' ) { result = this . helper . findCardInZone ( deckState . board , cardId , entityId ) ; } else if ( [ 'GRAVEYARD' , 'REMOVEDFROMGAME' , 'SETASIDE' , 'SECRET' ] . indexOf ( initialZone ) !== - 1 ) { result = this . helper . findCardInZone ( deckState . otherZone , cardId , entityId ) ; } const dbCard = ( cardId && this . allCards . getCard ( cardId ) ) || ( { } as ReferenceCard ) ; return ( result ?? DeckCard . create ( { cardId : cardId , entityId : entityId , cardName : this . i18n . getCardName ( dbCard . id ) , manaCost : dbCard . cost , rarity : dbCard . rarity ? dbCard . rarity . toLowerCase ( ) : null , } as DeckCard ) ) ; } private buildNewHand ( initialZone , previousHand , movedCard ) { if ( initialZone !== 'HAND' || ! movedCard ) { return previousHand ; } return this . helper . removeSingleCardFromZone ( previousHand , movedCard . cardId , movedCard . entityId ) [ 0 ] ; } private buildNewOther ( initialZone , previousOther , movedCard ) { if ( [ 'GRAVEYARD' , 'REMOVEDFROMGAME' , 'SETASIDE' , 'SECRET' ] . indexOf ( initialZone ) !== - 1 || ! movedCard ) { return this . helper . removeSingleCardFromZone ( previousOther , movedCard . cardId , movedCard . entityId ) [ 0 ] ; } return previousOther ; } private buildNewBoard ( initialZone , previousBOard , movedCard ) { if ( initialZone !== 'PLAY' || ! movedCard ) { return previousBOard ; } return this . helper . removeSingleCardFromZone ( previousBOard , movedCard . cardId , movedCard . entityId ) [ 0 ] ; } }