import { Injectable } from '@angular/core' ; import { SceneMode } from '@firestone-hs/reference-data' ; import { BehaviorSubject , combineLatest , Observable } from 'rxjs' ; import { concatMap , distinctUntilChanged , filter , map } from 'rxjs/operators' ; import { MainWindowState } from '../../../models/mainwindow/main-window-state' ; import { NavigationState } from '../../../models/mainwindow/navigation/navigation-state' ; import { MercenariesOutOfCombatState } from '../../../models/mercenaries/out-of-combat/mercenaries-out-of-combat-state' ; import { Preferences } from '../../../models/preferences' ; import { CardsFacadeService } from '../../cards-facade.service' ; import { BroadcastEvent , Events } from '../../events.service' ; import { OverwolfService } from '../../overwolf.service' ; import { MemoryInspectionService } from '../../plugins/memory-inspection.service' ; import { PreferencesService } from '../../preferences.service' ; import { AppUiStoreFacadeService } from '../../ui-store/app-ui-store-facade.service' ; import { MercenariesMemoryCacheService } from '../mercenaries-memory-cache.service' ; import { MercenariesOutOfCombatOverlayHandler } from './overlay/_mercenaries-out-of-combat-overlay-handler' ; import { MercenariesTreasureSelectionParser } from './parser/mercenaries-treasure-selection-parser' ; import { MercenariesOutOfCombatParser } from './parser/_mercenaries-out-of-combat-parser' ; @ Injectable ( ) export class MercenariesOutOfCombatService { public store$ = new BehaviorSubject < MercenariesOutOfCombatState > ( null ) ; private internalStore$ = new BehaviorSubject < MercenariesOutOfCombatState > ( new MercenariesOutOfCombatState ( ) ) ; private preferences$ : Observable < Preferences > ; private events$ : Observable < BroadcastEvent > ; private mainWindowState$ : Observable < [ MainWindowState , NavigationState ] > ; private parsers : { [ eventType ] : readonly MercenariesOutOfCombatParser [ ] ; } ; private eventEmitters : ( ( state : MercenariesOutOfCombatState ) => void ) [ ] = [ ] ; private overlayHandlers : MercenariesOutOfCombatOverlayHandler [ ] ; constructor ( private readonly events , private readonly allCards , private readonly prefs , private readonly memoryService , private readonly memoryCache , private readonly ow , private readonly store ) { this . init ( ) ; window [ 'mercenariesOutOfCombatStore' ] = this . store$ ; } private async processEvent ( event , currentScene ) { try { const parsers = this . getParsersFor ( event . key , this . internalStore$ . value ) ; if ( ! parsers ?. length ) { return ; } let state = this . internalStore$ . value ; for ( const parser of parsers ) { state = await parser . parse ( state , event , currentScene ) ; } this . internalStore$ . next ( state ) ; } catch ( e ) { console . error ( '[mercenaries-ooc-store] could not process event' , event . key , event , e ) ; } } private async emitState ( newState , currentScene , preferences ) { this . eventEmitters . forEach ( ( emitter ) => emitter ( newState ) ) ; await Promise . all ( this . overlayHandlers . map ( ( handler ) => handler . updateOverlay ( newState , currentScene , preferences ) ) ) ; } private async init ( ) { this . registerParser ( ) ; this . buildEventEmitters ( ) ; this . buildOverlayHandlers ( ) ; await this . store . initComplete ( ) ; this . preferences$ = ( this . ow . getMainWindow ( ) . preferencesEventBus as BehaviorSubject < any > ) . asObservable ( ) . pipe ( map ( ( theEvent ) => theEvent . preferences as Preferences ) ) ; this . mainWindowState$ = ( this . ow . getMainWindow ( ) . mainWindowStoreMerged as BehaviorSubject < [ MainWindowState , NavigationState ] > ) . asObservable ( ) ; this . events$ = this . events . on ( Events . MEMORY_UPDATE ) ; combineLatest ( this . events$ , this . store . listen$ ( ( [ main , nav , prefs ] ) => main . currentScene ) ) . pipe ( distinctUntilChanged ( ) , filter ( ( [ event , currentScene ] ) => ! ! event ) , concatMap ( async ( [ event , [ currentScene ] ] ) => await this . processEvent ( event , currentScene ) ) ) . subscribe ( ) ; combineLatest ( this . preferences$ , this . internalStore$ . asObservable ( ) , this . store . listen$ ( ( [ main , nav , prefs ] ) => main . currentScene ) ) . pipe ( concatMap ( async ( [ prefs , newState , [ currentScene ] ] ) => await this . emitState ( newState , currentScene , prefs ) ) ) . subscribe ( ) ; } private getParsersFor ( type , state ) { const candidates = this . parsers [ type ] ; return candidates ?. filter ( ( parser ) => parser . applies ( state ) ) ; } private buildEventEmitters ( ) { const result = [ ( state ) => this . store$ . next ( state ) ] ; this . eventEmitters = result ; } private buildOverlayHandlers ( ) { this . overlayHandlers = [ ] ; } private registerParser ( ) { const parsers = [ new MercenariesTreasureSelectionParser ( this . allCards ) , ] ; this . parsers = { } ; for ( const parser of parsers ) { if ( ! this . parsers [ parser . eventType ( ) ] ) { this . parsers [ parser . eventType ( ) ] = [ ] ; } this . parsers [ parser . eventType ( ) ] = [ ... this . parsers [ parser . eventType ( ) ] , parser ] ; } } }