(function(){
	var next_id = 0,
		creepers = [],
		MAX_SPEED = 1,
		INTERVAL = 20,
		CREEPS_PER_TURN=20,
		MAX_CREEPS_PER_TURN=300,
		CREEP_FACTOR = 0.3,
		MIN_SPEED = 0.2,
		timer=0,
		delay=5000,
		moving=false;
	window["creepify"] = function(interval){
		//document.body.style.overflow = "hidden";
		window.onmousemove = function(){timer=0;}
		
		var dom_item = document.body,
			dom_text,
			original_text,
			new_text,
			words_array,
			start_id=next_id,
			text_strings;	
		delay = Number(interval) ? Math.round(interval*1000) : delay;
					
			
		if( !dom_item ){
			error("Creepify Error: There is no element with id '" + dom_id + "'!");
			return false;
		}
		
		dom_text = dom_item.innerHTML.toString();
		text_strings = dom_text.split(/\<[^<>]*\>/);
		
		for( var x=0,xlen=text_strings.length;x<xlen;x++){
			original_text = text_strings[x];
			words_array = original_text.split(/ /);
			new_text=""
			for( var y=0,ylen=words_array.length;y<ylen;y++){
				if( words_array[y].length && words_array[y].match(/[^\s]/) )
					new_text+="<span id='creeper-"+(next_id++)+"'>"+words_array[y]+"</span> ";
			}
			
			var text_to_replace = dom_text.match(new RegExp(">[^<>]*"+regEscape(original_text)+"[^<>]*<"));
			if( text_to_replace ){
				var new_replacement_text = text_to_replace[0].replace(/\s*/, " ").replace(new RegExp(regEscape(original_text)), new_text);
				dom_text=dom_text.replace(new RegExp(regEscape(text_to_replace[0])), new_replacement_text);
			}
		}
		
		dom_text=dom_text.replace(/undefined/,"");
		dom_item.innerHTML = dom_text;
		create_creeper_span(start_id,next_id);
		
		initialize_creepin();
	
	}
	
	
	function create_creeper_span(start,end){
		CREEPS_PER_TURN = Math.round( CREEP_FACTOR*(end-start) );
		CREEPS_PER_TURN = CREEPS_PER_TURN < MAX_CREEPS_PER_TURN ? CREEPS_PER_TURN : MAX_CREEPS_PER_TURN;
		for(var x=start;x<=end;x++){
			var new_creeper = creeper("creeper-" + x );
			if( new_creeper && new_creeper.element )
				creepers.push( new_creeper );
		}
	}
	
	function creeper(dom_id){
		var initial_x_offset = Math.random()*2-1,
			initial_y_offset = Math.random()*2-1,
			initial_x = Math.abs(initial_x_offset) > MIN_SPEED ? initial_x_offset : (initial_x_offset>0?initial_x_offset+MIN_SPEED:initial_x_offset-MIN_SPEED),
			initial_y = Math.abs(initial_y_offset) > MIN_SPEED ? initial_y_offset : (initial_y_offset>0?initial_y_offset+MIN_SPEED:initial_y_offset-MIN_SPEED),
			element = document.getElementById(dom_id);
		if( !element ){
			error("Creepify Error: There is no element with id '" + dom_id + "'!");
			return null;
		}
		//element.style.position='absolute';
		element.style.zIndex = dom_id.split('-')[1];
		element.style.position = 'relative';
		element.style.left = '0px';
		element.style.top = '0px';
		return {
			element:element,
			velocity: {	x:initial_x*MAX_SPEED, y:initial_y*MAX_SPEED },
			position: { x:0,y:0 },
			reset:function(){
				this.position = {x:0,y:0};
				this.element.style.left="0px";
				this.element.style.top="0px";
			},
			step:function(){
				this.position.x+=this.velocity.x;
				this.position.y+=this.velocity.y;
				this.element.style.left=Math.round(this.position.x)+"px";
				this.element.style.top=Math.round(this.position.y)+"px";
			}
		};
	}
	
	function initialize_creepin(){
		setTimeout( function(){
			creep(0);
		}, INTERVAL );
	}
	
	function creep(next){
		if( timer >= delay ){
			moving = true;
			for( var x=0;x<CREEPS_PER_TURN;x++ )	
				creepers[(next+x)%creepers.length].step();

			next=(next+CREEPS_PER_TURN)%creepers.length;
		} else if( moving ){
			moving=false;
			for( var x=0,xlen=creepers.length;x<xlen;x++)
				creepers[x].reset();
		} else  
			timer+=INTERVAL;
		
		setTimeout(function(){
			creep(next);
		}, INTERVAL );		
	}
	
	
	function error(error){
		try{
			console.log(error);
		}catch(e){}
	}
	
	function regEscape(string){
		var delimiters = "\\[]{}!^*()+>{}/.-?";
		delimiters = delimiters.split("");
		for( var x=0,xlen=delimiters.length;x<xlen;x++){
			string = string.replace( delimiters[x] , "\\"+delimiters[x] );
		}
		return string;
	}
	
})();
