/*
http://www.tumuski.com/code/clumpy/
Copyright (c) 2009 Thomas Peri
MIT License
*/
var Clumpy=(function(){var constructor,do_while_loop,for_in_loop,while_loop,fn,nothing,num,spawn;constructor=function(options){var self=this,break_loop,continue_loop,label,for_loop,init,interrupt,once,pause,resume,set,setNow,sleep,wait,advance,clump,enqueue,findLoop,iterate,perform,schedule,wait_callback,inside,nextLabel,paused,queue,waiting,stop,clumpTimeout,sleepTimeout,between,delay,duration,manual;break_loop=function(label){return once(function(){findLoop(label);queue.head.loop.finished=true;});};continue_loop=function(label){return once(function(){findLoop(label);});};label=function(newLabel){nextLabel=newLabel;return self;};for_loop=function(init,test,inc,statements){enqueue(statements,{label:nextLabel,init:init,test:test,inc:inc,initialized:false,finished:false});return self;};once=function(statements){enqueue(statements,null);return self;};wait=function(statements){return once(function(){waiting=true;statements(wait_callback);});};sleep=function(delay){return wait(function(callback){sleepTimeout=setTimeout(callback,delay);});};pause=function(){paused=true;clearTimeout(clumpTimeout);clearTimeout(sleepTimeout);return self;};resume=function(){if(paused){paused=false;if(!waiting){schedule();}}return self;};set=function(options){return once(function(){setNow(options);});};setNow=function(options){options=options||{};function defined(key){return typeof options[key]!=='undefined';}if(defined('between')){between=fn(options.between);}if(defined('delay')){delay=num(options.delay,0);}if(defined('duration')){duration=num(options.duration,0);}if(defined('manual')){manual=options.manual?true:false;}if(queue.head&&!paused&&!waiting){pause();setTimeout(resume,0);}return self;};interrupt=function(){return once(function(){stop=true;});};init=function(){inside=false;nextLabel=null;paused=false;queue=spawn(null);stop=false;waiting=false;clearTimeout(clumpTimeout);clearTimeout(sleepTimeout);};advance=function(){var loop;while(true){loop=queue.head.loop;if(loop&&!loop.finished){loop.inc.call();}else{queue.head=queue.head.next;if(!queue.head){queue.tail=null;if(queue.parent){queue=queue.parent;continue;}}}break;}};clump=function(){var end=new Date().getTime()+duration;if(queue.head){while(true){iterate();if(!queue.head){break;}if(paused||waiting){between();break;}if(stop||(!manual&&(new Date().getTime()>end))){stop=false;between();schedule(delay);break;}}}};wait_callback=function(){if(waiting){waiting=false;if(!paused){schedule();}}};enqueue=function(statements,loop){var node;nextLabel=null;node={loop:loop,statements:statements,next:null};if(inside){inside=false;queue=spawn(queue);}if(queue.tail){queue.tail.next=node;queue.tail=node;}else{queue.head=node;queue.tail=node;if(!queue.parent){schedule();}}};findLoop=function(label){while(!queue.head.loop){queue=queue.parent;if(!queue){throw"'break_loop' and 'continue_loop' can only be used inside a Clumpy loop!";}}if(label){while(!queue.head.loop||queue.head.loop.label!==label){queue=queue.parent;if(!queue){throw"Clumpy couldn't find the label '"+label+"'.";}}}};iterate=function(){var loop;queue.begun=true;loop=queue.head.loop;if(loop){if(!loop.initialized){loop.init.call();loop.initialized=true;}if(loop.test.call()){perform();}else{loop.finished=true;}}else{perform();}if(queue.begun){advance();}};perform=function(){inside=true;queue.head.statements.call();inside=false;};schedule=function(d){if(queue.head){clumpTimeout=setTimeout(clump,d||0);}};init();between=nothing;delay=0;duration=100;manual=false;setNow(options);this.break_loop=break_loop;this.continue_loop=continue_loop;this.label=label;this.for_loop=for_loop;this.once=once;this.wait=wait;this.sleep=sleep;this.pause=pause;this.resume=resume;this.set=set;this.setNow=setNow;this.interrupt=interrupt;this.init=init;};do_while_loop=function(statements,test){var first=true;return this.while_loop(function(){var proceed=first||test();first=false;return proceed;},statements);};for_in_loop=function(obj,statements){var i,key,keys=[];for(key in obj){keys.push(key);}return this.for_loop(function(){i=0;},function(){return i<keys.length;},function(){i+=1;},function(){statements(keys[i]);});};while_loop=function(test,statements){return this.for_loop(nothing,test,nothing,statements);};fn=function(value){return typeof value==='function'?value:nothing;};nothing=function(){};num=function(value,min){value=parseInt(value,10)||0;return typeof min==='number'?Math.max(min,value):value;};spawn=function(parent){return{begun:false,parent:parent,head:null,tail:null};};constructor.prototype.do_while_loop=do_while_loop;constructor.prototype.for_in_loop=for_in_loop;constructor.prototype.while_loop=while_loop;return constructor;}());