import { ExportNs } from '../../esl-utils/environment/export-ns' ; import { Observable } from '../../esl-utils/abstract/observable' ; import { evaluate } from '../../esl-utils/misc/format' ; import { isPrimitive } from '../../esl-utils/misc/object' ; import { ESLMediaRule } from './esl-media-rule' ; export type RulePayloadParser < T > = ( val : string ) => T | undefined ; export type RuleChangedCallback < T > = ( rule : ESLMediaRule < T | undefined > , list : ESLMediaRuleList < T > ) => void ; /**
 * ESLMediaRuleList -  ESLMediaRule observable collection
 *  author @ ExportNs ( 'MediaRuleList' ) export class ESLMediaRuleList < T = any > extends Observable < RuleChangedCallback < T > > { returns public static STRING_PARSER : RulePayloadParser < string > = ( val ) : string => val ; /**
     * Object value parser. Uses  evaluate to parse value
     *  returns public static OBJECT_PARSER = < U > ( val ) : U | undefined => evaluate ( val ) ; param query public static parse ( query ) ; param query param parser - value parser function. See built in  ESLMediaRuleList . OBJECT_PARSER or  ESLMediaRuleList . STRING_PARSER (default)
      public static parse < U > ( query , parser ) ; public static parse ( query , parser = ESLMediaRuleList . STRING_PARSER ) { const rules = [ ] ; query . split ( '|' ) . forEach ( ( part ) => { const lex = part . trim ( ) ; const rule = ESLMediaRule . parse ( lex , parser ) ; if ( ! rule ) return ; rule . default ? rules . unshift ( rule ) : rules . push ( rule ) ; } ) ; return new ESLMediaRuleList ( rules ) ; } param values param mask example public static parseTuple ( values , mask ) { const valueList = values . split ( '|' ) ; const conditions = mask . split ( '|' ) ; if ( valueList . length !== conditions . length ) throw new Error ( 'Value doesn\'t correspond to mask' ) ; const rules = conditions . map ( ( query , i ) => new ESLMediaRule ( valueList [ i ] , query ) ) ; return new ESLMediaRuleList ( rules ) ; } private readonly _rules : ESLMediaRule < T > [ ] ; private readonly _default : ESLMediaRule < T | undefined > | undefined ; private _active : ESLMediaRule < T | undefined > ; private constructor ( rules ) { super ( ) ; this . _rules = rules ; this . _default = rules . filter ( ( rule ) => rule . default ) [ 0 ] ; this . _onMatchChanged = this . _onMatchChanged . bind ( this ) ; } /** Subscribes to the instance active rule change */ public addListener ( listener ) { super . addListener ( listener ) ; if ( this . _listeners . size > 1 ) return ; this . _rules . forEach ( ( rule ) => rule . addListener ( this . _onMatchChanged ) ) ; } /** Unsubscribes from the instance active rule change */ public removeListener ( listener ) { super . removeListener ( listener ) ; if ( this . _listeners . size ) return ; this . _rules . forEach ( ( rule ) => rule . removeListener ( this . _onMatchChanged ) ) ; } /** List of inner  ESLMediaRule s  public get rules ( ) : ESLMediaRule < T > [ ] { return this . _rules ; } /** Cached active  ESLMediaRule public get active ( ) : ESLMediaRule < T | undefined > { if ( ! this . _active || ! this . _listeners . size ) { this . _active = this . activeRule ; } return this . _active ; } /** Returns last active rule in the list */ public get activeRule ( ) : ESLMediaRule < T | undefined > { const satisfiedRules = this . rules . filter ( ( rule ) => rule . matches ) ; return satisfiedRules . length > 0 ? satisfiedRules [ satisfiedRules . length - 1 ] : ESLMediaRule . empty ( ) ; } /** Active rule payload value */ public get activeValue ( ) : T | undefined { const value = this . active . payload ; if ( isPrimitive ( value ) || ! this . default || isPrimitive ( this . default . payload ) ) return value ; return Object . assign ( { } , this . default . payload || { } , value ) ; } /**  ESLMediaRule that is used as a default rule  public get default ( ) : ESLMediaRule < T | undefined > | undefined { return this . _default ; } /** Handle inner rules state change */ private _onMatchChanged ( ) { const rule = this . activeRule ; if ( this . _active === rule ) return ; this . fire ( this . _active = rule , this ) ; } } declare global { export interface ESLLibrary { MediaRuleList : typeof ESLMediaRuleList ; } }