import { throttle } from "@zwave-js/shared" ; import type EventEmitter from "events" ; /** Mixin to provide statistics functionality. Requires the base class to extend EventEmitter. */ export abstract class StatisticsHost < T > { protected abstract createEmpty ( ) ; private _statistics : T | undefined ; public get statistics ( ) : Readonly < T > { if ( ! this . _statistics ) this . resetStatistics ( ) ; return Object . freeze ( this . _statistics ! ) ; } public resetStatistics ( ) { this . updateStatistics ( ( ) => this . createEmpty ( ) ) ; } /** Can be overridden in derived classes to specify additional args to be included in the statistics event callback. */ protected getAdditionalEventArgs ( ) { return [ ] ; } private _emitUpdate : ( ( stat : T ) => void ) | undefined ; public updateStatistics ( updater ) { this . _statistics = updater ( this . _statistics ?? this . createEmpty ( ) ) ; if ( ! this . _emitUpdate ) { this . _emitUpdate = throttle ( ( this as unknown as EventEmitter ) . emit . bind ( this , "statistics updated" , ... this . getAdditionalEventArgs ( ) ) , 250 , true ) ; } this . _emitUpdate ( this . _statistics ) ; } public incrementStatistics ( property ) { this . updateStatistics ( ( s ) => { const value = s [ property ] ; if ( typeof value === "number" ) { return { ... s , [ property ] : value + 1 } ; } else { return s ; } } ) ; } } export interface StatisticsEventCallbacks < T > { "statistics updated" : ( statistics : T ) => void ; } export interface StatisticsEventCallbacksWithSelf < TSelf , TStats > { "statistics updated" : ( self : TSelf , statistics : TStats ) => void ; }