import { Iterate , IterateAction } from 'iteratez' ; import { Day } from './Day' ; import { DaySpan } from './DaySpan' ; import { Functions as fn } from './Functions' ; import { Identifier , IdentifierInput } from './Identifier' ; import { Time } from './Time' ; /**
 * A map of values in the [[ScheduleModifier]] keyed by the descriptions of the
 * identifiers.
 */ export interface ScheduleModifierDescription < T > { [ description ] : T ; } /**
 * An object which carries the span taken from an identifier and the value
 * mapped to it in a [[ScheduleModifier]].
 */ export interface ScheduleModifierSpan < T > { span : DaySpan ; value : T ; } type Iter < R , T > = Iterate < R , string , ScheduleModifier < T > > ; typeparam export class ScheduleModifier < T > { /**
     * The map of values mapped by their [[Identifier]]s.
     */ public map : { [ id ] : T ; } ; /**
     * Creates a new schedule modifier.
     */ public constructor ( ) { this . map = { } ; } /**
     * Clears the modifier of all modifications.
     */ public clear ( ) { this . map = { } ; return this ; } /**
     * Returns `true` if this modifier lacks any modifications, otherwise `false`.
     */ public isEmpty ( ) { for ( const id in this . map ) { return ! id ; } return true ; } param day param otherwise param lookAtTime returns public get ( day , otherwise , lookAtTime = true ) { const map = this . map ; return ( lookAtTime && map [ day . timeIdentifier ] ) || map [ day . dayIdentifier ] || map [ day . monthIdentifier ] || map [ day . weekIdentifier ] || map [ day . quarterIdentifier ] || otherwise ; } param day param lookAtTime returns public getIdentifier ( day , lookAtTime = true ) { const map = this . map ; if ( lookAtTime && fn . isDefined ( map [ day . timeIdentifier ] ) ) return Identifier . Time ; if ( fn . isDefined ( map [ day . dayIdentifier ] ) ) return Identifier . Day ; if ( fn . isDefined ( map [ day . monthIdentifier ] ) ) return Identifier . Month ; if ( fn . isDefined ( map [ day . weekIdentifier ] ) ) return Identifier . Week ; if ( fn . isDefined ( map [ day . quarterIdentifier ] ) ) return Identifier . Quarter ; if ( fn . isDefined ( map [ day . year ] ) ) return Identifier . Year ; return null ; } param day returns public getAll ( day ) { const map = this . map ; const all = [ ] ; if ( map [ day . timeIdentifier ] ) all . push ( map [ day . timeIdentifier ] ) ; if ( map [ day . dayIdentifier ] ) all . push ( map [ day . dayIdentifier ] ) ; if ( map [ day . monthIdentifier ] ) all . push ( map [ day . monthIdentifier ] ) ; if ( map [ day . weekIdentifier ] ) all . push ( map [ day . weekIdentifier ] ) ; if ( map [ day . quarterIdentifier ] ) all . push ( map [ day . quarterIdentifier ] ) ; return all ; } param from param fromType param to param toType public move ( from , fromType , to , toType ) { const fromIdentifier = fromType . get ( from ) ; const toIdentifier = toType . get ( to ) ; this . map [ toIdentifier ] = this . map [ fromIdentifier ] ; delete this . map [ fromIdentifier ] ; return this ; } param fromTime param toTime returns public moveTime ( fromTime , toTime ) { const type = Identifier . Time ; const moveIds = [ ] ; this . iterate ( ) . each ( ( [ id , value ] ) => { if ( type . is ( id ) ) { const start = type . start ( id ) ; if ( start . sameTime ( fromTime ) ) { moveIds . push ( id ) ; } } } ) ; let moved = 0 ; for ( const id of moveIds ) { const value = this . map [ id ] ; const start = type . start ( id ) ; const newStart = start . withTime ( toTime ) ; const newId = type . get ( newStart ) ; if ( ! this . map [ newId ] ) { this . map [ newId ] = value ; delete this . map [ id ] ; moved ++ ; } } return moved ; } param time returns public removeTime ( time ) { const type = Identifier . Time ; let removed = 0 ; this . iterate ( ) . each ( ( [ id , ] , key , iterator ) => { if ( type . is ( id ) ) { const start = type . start ( id ) ; if ( start . sameTime ( time ) ) { iterator . remove ( ) ; removed ++ ; } } } ) ; return removed ; } param day param value param type public set ( day , value , type ) { this . map [ type . get ( day ) ] = value ; return this ; } param day param type public unset ( day , type ) { delete this . map [ type . get ( day ) ] ; return this ; } returns public iterate ( ) { return new Iterate < [ IdentifierInput , T ] , string , ScheduleModifier < T > > ( iterator => { const map = this . map ; for ( const rawId in map ) { const asNumber = parseInt ( rawId ) ; const validAsNumber = asNumber + '' === rawId ; const id = validAsNumber ? asNumber : rawId ; switch ( iterator . act ( [ id , map [ rawId ] ] , rawId ) ) { case IterateAction . STOP : return ; case IterateAction . REMOVE : delete map [ rawId ] ; break ; } } } ) ; } param prefix returns public query ( query ) { return this . iterate ( ) . where ( ( [ id , value ] ) => Identifier . contains ( query , id ) ) ; ; } /**
     * Returns all identifiers stored in this modifier.
     */ public identifiers ( filter ? ) { return this . iterate ( ) . where ( ( [ id , value ] ) => ! filter || filter ( value , id ) ) . transform < IdentifierInput > ( ( [ id , ] ) => id ) ; } param endInclusive returns public spans ( endInclusive = false ) { return this . iterate ( ) . transform ( ( [ id , value ] ) => { const type = Identifier . find ( id ) ; if ( type ) { const span = type . span ( id , endInclusive ) ; return { span , value } ; } } ) ; } param short returns public describe ( short = false ) { return this . iterate ( ) . transform < string > ( ( [ id , ] ) => { const type = Identifier . find ( id ) ; if ( type ) { return type . describe ( id , short ) ; } } ) ; } param short returns public describeMap ( short = false ) { const map = this . map ; const out = { } ; for ( const id in map ) { const type = Identifier . find ( id ) ; if ( type ) { out [ type . describe ( id , short ) ] = map [ id ] ; } } return out ; } }