import { Injectable } from '@angular/core'; import { Router } from '@angular/router'; import { HttpClient } from '@angular/common/http'; import { ApiSocketListenAction, SocketsService } from '@arrow/bom/core'; import { ConfigService } from '@arrow/bom/config'; import { OrmService } from './ORM/orm.service'; import { Observable, Subject, merge, timer, Subscription } from 'rxjs'; import { mergeAll, debounce, map } from 'rxjs/operators'; // Type Definitions import { Row } from './ORM/types/custom/row.interface'; import { Row as RawRow } from './ORM/types/bom-api/row.interface'; const DEBOUNCE_TIME_MS = 350; @Injectable() export class ListService { private _store: Map = new Map(); private _list$: Subject = new Subject(); private _BO$$: Subject<{ row: Row; response: any }> = new Subject(); private _altPricing$$: Subject = new Subject(); private _multiplier = 1; constructor( private _sockets: SocketsService, private _orm: OrmService, private _router: Router, private config: ConfigService, private http: HttpClient ) { this._sockets .observeAction(ApiSocketListenAction.PART_ROW_COMPLETE) .pipe(map((arr: string) => ({ id: arr[0] }))) .subscribe((row: Row) => this._upsertReducer(this._loadedRowAction(row))); this._sockets .observeAction(ApiSocketListenAction.NO_PARTS_FOUND) .subscribe((data: any) => { this.resetRowsReducer(); }); merge( this._sockets.observeAction(ApiSocketListenAction.BOM_STUB) .pipe(map((stub: any) => { this.resetRowsReducer(); return stub.bom.rows; }) ), this._sockets.observeAction(ApiSocketListenAction.PART_ROW_INFORMATION), this._sockets.observeAction(ApiSocketListenAction.PART_ROW_PRICING), this._sockets.observeAction(ApiSocketListenAction.CUSTOMER_PART_NUMBER) ) .pipe(mergeAll()) .subscribe((rr: RawRow) => { this._upsertReducer( this._upsertRowAction(this._orm.transform('row', rr)) ) } ); this._sockets .observeAction(ApiSocketListenAction.ROW_DELETED) .pipe(map((id: string) => ({ id: id }))) .subscribe((row: Row) => this._deleteReducer(row)); this._sockets .observeAction(ApiSocketListenAction.ROW_RESTORED) .subscribe((rr: RawRow) => this._restoreRowReducer(this._orm.transform('row', rr)) ); this._sockets .observeAction(ApiSocketListenAction.BUYIING_OPTIONS) .subscribe((response: any) => { const row = this._store.get(response.rowId); if (row) { const buyingInfo = this._multiplier > 1 ? response.stockInfoGroups.multiplied.buyingInfo : response.stockInfoGroups.original.buyingInfo; row.item.totalCount = buyingInfo.totalCount; row.item.totalPrice = buyingInfo.totalPrice; row.item.buyingOptions = row.item.getbuyingOptions( response.sources, response.stockInfoGroups, this._multiplier > 1 ? 'multiplied' : 'original', response.stockInfoGroups.original?.buyingInfo?.availableStock ); row.item.refreshAfterBuyingOptionsChanges(); row.item.setHasArrowReelSelected(); this._upsertReducer(row); (response.original = response.stockInfoGroups.original.buyingInfo), (response.multiplied = response.stockInfoGroups.multiplied.buyingInfo), this._BO$$.next({ row, response }); } }); this._router.events.subscribe(() => this.resetRowsReducer()); this._sockets .observeAction(ApiSocketListenAction.ALTERNATE_PART_PRICING) .subscribe((response: any) => { this._altPricing$$.next(response); }); } private _upsertRowAction(row: Row): Row { const _row = this._store.get(row.id) || { loading: true, loaded: false }; return Object.assign({}, _row, row); } private _loadedRowAction(row: Row) { const _row = Object.assign({}, this._store.get(row.id), { loading: false, loaded: true }); return Object.assign({}, _row, row); } private _restoreRowReducer(row: Row) { const oldRow = this._store.get(row.id); delete oldRow.deleted; const newRow = Object.assign({}, oldRow, { loading: false, loaded: true }); this._store.set(newRow.id, newRow); this._list$.next(Array.from(this._store, (elements: any[]) => elements[1])); } private _upsertReducer(row: Row) { const newRow = Object.assign({}, row); this._store.set(newRow.id, newRow); this._list$.next(Array.from(this._store, (elements: any[]) => elements[1])); } private _deleteReducer(row: Row) { const newRow = Object.assign({ deleted: true }, this._store.get(row.id)); this._store.set(newRow.id, newRow); this._list$.next(Array.from(this._store, (elements: any[]) => elements[1])); } public getObservable(): Observable { return this._list$ .asObservable() .pipe(debounce(() => timer(DEBOUNCE_TIME_MS))); } public getBOptObservable(): Observable { return this._BO$$.asObservable(); } public setMultiplier(multiplier: number) { this._multiplier = multiplier; } public resetRowsReducer() { this._store.clear(); this._list$.next([]); } public getAlternates(bomId, params): any { const ALTERNATES_URL = `${this.config.apiCoreUrl}/service/pricing/${bomId}/GetStockPricing`; return this.http.get(ALTERNATES_URL, { withCredentials: true, params: params } ); } }