define(["Tone/core/Tone","Tone/core/Type"],function(Tone){"use strict";Tone.Timeline=function(){var options=this.optionsObject(arguments,["memory"],Tone.Timeline.defaults);this._timeline=[];this._toRemove=[];this._iterating=!1;this.memory=options.memory};Tone.extend(Tone.Timeline);Tone.Timeline.defaults={"memory":Infinity};Object.defineProperty(Tone.Timeline.prototype,"length",{get:function(){return this._timeline.length}});Tone.Timeline.prototype.addEvent=function(event){if(this.isUndef(event.time)){throw new Error("events must have a time attribute")}
event.time=this.toSeconds(event.time);if(this._timeline.length){var index=this._search(event.time);this._timeline.splice(index+1,0,event)}else{this._timeline.push(event)}
if(this.length>this.memory){var diff=this.length-this.memory;this._timeline.splice(0,diff)}
return this};Tone.Timeline.prototype.removeEvent=function(event){if(this._iterating){this._toRemove.push(event)}else{var index=this._timeline.indexOf(event);if(index!==-1){this._timeline.splice(index,1)}}
return this};Tone.Timeline.prototype.getEvent=function(time){time=this.toSeconds(time);var index=this._search(time);if(index!==-1){return this._timeline[index]}else{return null}};Tone.Timeline.prototype.getEventAfter=function(time){time=this.toSeconds(time);var index=this._search(time);if(index+1<this._timeline.length){return this._timeline[index+1]}else{return null}};Tone.Timeline.prototype.getEventBefore=function(time){time=this.toSeconds(time);var index=this._search(time);if(index-1>=0){return this._timeline[index-1]}else{return null}};Tone.Timeline.prototype.cancel=function(after){if(this._timeline.length>1){after=this.toSeconds(after);var index=this._search(after);if(index>=0){this._timeline=this._timeline.slice(0,index)}else{this._timeline=[]}}else if(this._timeline.length===1){if(this._timeline[0].time>=after){this._timeline=[]}}
return this};Tone.Timeline.prototype.cancelBefore=function(time){if(this._timeline.length){time=this.toSeconds(time);var index=this._search(time);if(index>=0){this._timeline=this._timeline.slice(index+1)}}
return this};Tone.Timeline.prototype._search=function(time){var beginning=0;var len=this._timeline.length;var end=len;while(beginning<=end&&beginning<len){var midPoint=Math.floor(beginning+(end-beginning)/2);var event=this._timeline[midPoint];if(event.time===time){for(var i=midPoint;i<this._timeline.length;i++){var testEvent=this._timeline[i];if(testEvent.time===time){midPoint=i}}
return midPoint}else if(event.time>time){end=midPoint-1}else if(event.time<time){beginning=midPoint+1}}
return beginning-1};Tone.Timeline.prototype._iterate=function(callback,lowerBound,upperBound){this._iterating=!0;lowerBound=this.defaultArg(lowerBound,0);upperBound=this.defaultArg(upperBound,this._timeline.length-1);for(var i=lowerBound;i<=upperBound;i++){callback(this._timeline[i])}
this._iterating=!1;if(this._toRemove.length>0){for(var j=0;j<this._toRemove.length;j++){var index=this._timeline.indexOf(this._toRemove[j]);if(index!==-1){this._timeline.splice(index,1)}}
this._toRemove=[]}};Tone.Timeline.prototype.forEach=function(callback){this._iterate(callback);return this};Tone.Timeline.prototype.forEachBefore=function(time,callback){time=this.toSeconds(time);var upperBound=this._search(time);if(upperBound!==-1){this._iterate(callback,0,upperBound)}
return this};Tone.Timeline.prototype.forEachAfter=function(time,callback){time=this.toSeconds(time);var lowerBound=this._search(time);this._iterate(callback,lowerBound+1);return this};Tone.Timeline.prototype.forEachFrom=function(time,callback){time=this.toSeconds(time);var lowerBound=this._search(time);while(lowerBound>=0&&this._timeline[lowerBound].time>=time){lowerBound--}
this._iterate(callback,lowerBound+1);return this};Tone.Timeline.prototype.forEachAtTime=function(time,callback){time=this.toSeconds(time);var upperBound=this._search(time);if(upperBound!==-1){this._iterate(function(event){if(event.time===time){callback(event)}},0,upperBound)}
return this};Tone.Timeline.prototype.dispose=function(){Tone.prototype.dispose.call(this);this._timeline=null;this._toRemove=null};return Tone.Timeline})