import type { Eq , PartialOrd } from '../utils/Types' ; import VideoPreference from './VideoPreference' ; class ObjectSet < T extends Eq & PartialOrd > implements Iterable < T > { constructor ( private items = [ ] ) { } static default ( ) { return new ObjectSet ( [ ] ) ; } [ Symbol . iterator ] ( ) { let i = 0 ; const items = this . items ; return { next ( ) { if ( i < items . length ) { return { done : false , value : items [ i ++ ] , } ; } return { done : true , value : null , } ; } , } ; } first ( ) { return this . items [ 0 ] ; } add ( item ) { this . items . push ( item ) ; } replaceFirst ( newItem , f ) { const pos = this . items . findIndex ( f ) ; if ( pos === - 1 ) { this . items . push ( newItem ) ; } else if ( ! this . has ( newItem ) ) { this . items [ pos ] = newItem ; } else { this . items . splice ( pos , 1 ) ; } } remove ( item ) { this . items = this . items . filter ( a => ! a . equals ( item ) ) ; } clear ( ) { this . items = [ ] ; } isEmpty ( ) { return this . items . length === 0 ; } equals ( other ) { if ( other === this ) { return true ; } if ( other . items . length !== this . items . length ) { return false ; } for ( const item of this . items ) { if ( ! other . items . some ( a => a . equals ( item ) ) ) { return false ; } } return true ; } has ( item ) { return this . items . some ( a => a . equals ( item ) ) ; } some ( f ) { return this . items . some ( f ) ; } clone ( ) { return new ObjectSet ( [ ... this . items ] ) ; } sort ( ) { this . items . sort ( ( a , b ) => a . partialCompare ( b ) ) ; } modify ( ) { return new SetBuilder ( this ) ; } } class SetBuilder < T extends Eq & PartialOrd > { private copied = false ; constructor ( private items = new ObjectSet ( ) ) { } private cow ( ) { if ( this . copied ) { return ; } this . items = this . items . clone ( ) ; this . copied = true ; } add ( item ) { if ( this . items . has ( item ) ) { return ; } this . cow ( ) ; this . items . add ( item ) ; } replaceFirst ( newItem , f ) { if ( this . items . has ( newItem ) && ! this . items . some ( f ) ) { return ; } this . cow ( ) ; this . items . replaceFirst ( newItem , f ) ; } remove ( item ) { if ( ! this . items . has ( item ) ) { return ; } this . cow ( ) ; this . items . remove ( item ) ; } some ( f ) { return this . items . some ( f ) ; } clear ( ) { if ( this . items . isEmpty ( ) ) { return ; } this . cow ( ) ; this . items . clear ( ) ; } build ( ) { if ( this . copied ) { this . items . sort ( ) ; } this . copied = false ; return this . items ; } } export class MutableVideoPreferences { constructor ( private builder ) { } add ( pref ) { this . builder . add ( pref ) ; } replaceFirst ( newPref , f ) { this . builder . replaceFirst ( newPref , f ) ; } remove ( pref ) { this . builder . remove ( pref ) ; } some ( f ) { return this . builder . some ( f ) ; } clear ( ) { this . builder . clear ( ) ; } build ( ) { return new VideoPreferences ( this . builder . build ( ) ) ; } } export class VideoPreferences implements Iterable < VideoPreference > , Eq { static prepare ( ) { return new MutableVideoPreferences ( new SetBuilder < VideoPreference > ( ) ) ; } static default ( ) { return new VideoPreferences ( ObjectSet . default ( ) ) ; } internal constructor ( private items ) { } [ Symbol . iterator ] ( ) { return this . items [ Symbol . iterator ] ( ) ; } highestPriority ( ) { return this . items . first ( ) ?. priority ; } sorted ( ) { return this . items [ Symbol . iterator ] ( ) ; } equals ( other ) { return other === this || this . items . equals ( other . items ) ; } modify ( ) { return new MutableVideoPreferences ( this . items . modify ( ) ) ; } some ( f ) { return this . items . some ( f ) ; } isEmpty ( ) { return this . items . isEmpty ( ) ; } } export default VideoPreferences ;