
/*
画像でアニメーションを行う。GIFアニメをGIF以外でもでき、細かい制御が可能
*/

/*
inner_data=[{anime_id}]{{
original_src		最初のsrc。stopされたときここに戻す
base_src		アニメナンバーを除く部分のsrc
pre_loaded		pre_load が完了しているかどうか
timer			タイマーハンドラ
current_session_id	現在実行しているアニメがどのセッションなのか
}

session=[{session_id}]{
queue{
	obj_list				アニメを行うオブジェクトを全て保持しておく
	=[{animeid}]{
		obj				queueに入れるオブジェクト
		status			queue の状態
	}
	obj_count			アニメを行うオブジェクトの数
	playend_count		アニメが終了したオブジェクトの数
}
}
*/

(function($){
	var options={};
	var inner_data={};//内部で使うデータ
	var session={};
	var session_id=0;
	
	$.fn.imganime=function(mode,arg1,arg2){

		if(mode=="config"){
			config(this,arg1);
		}else if(mode=="stop"){
			config(this,arg2);
			
			pause(this);
			this.each(function(i){
				var anime_id=get_anime_id(this);
				$(this).attr("src",inner_data[anime_id]["original_src"]);
			});
		}else if(mode=="pause"){
			config(this,arg2);
			
			pause(this);
		}else if(mode=="seek"){
			config(this,arg2);
			
			seek(this,arg1);
		}else if(mode=="reset"){
			config(this,arg2);
			this.each(function(i){
				var anime_id=$(this).attr('anime_id');
				$(this).attr("src",inner_data[anime_id]["original_src"]);
			});
		}else{
			//デフォルト動作は play
			config(this,arg2);
			pause(this);
			
			var current_session_id=session_id++;
			session[current_session_id]={queue:{}};
			session[current_session_id]["queue"]["obj_list"]={};
			session[current_session_id]["queue"]["obj_count"]=0;
			session[current_session_id]["queue"]["playend_count"]=0;
			
			this.each(function(i){
				var anime_id=$(this).attr('anime_id');
				
				session[current_session_id]["queue"]["obj_list"][anime_id]={};
				
				var src=$(this).attr( 'src' );
				var anime_num;//何番目の画像か
				var formats=arg1 || "";//play 指示子
				
				if(!inner_data[anime_id])
					inner_data[anime_id]={};
				inner_data[anime_id]["original_src"]=src;
				inner_data[anime_id]["current_session_id"]=current_session_id;
				
				//指示子の中に含まれる一時オプション
				var target;
				var span={};
				var loop_count;
				var fps;
				var enable_queue;
				
				var match=src.match(/\-anime([0-9]+)/);
				if(match){
					anime_num=match[1];
					var base_src=src.replace(/\-anime([0-9]+)/,"-anime[*anime_num*]");
					inner_data[anime_id]["base_src"]=base_src;
					
					//再生しながら同時並行で読み込む処理・・のはずだが今は完全にロードしてから
					if(!inner_data[anime_id]["pre_loaded"]){
						img_preload(anime_id);
					}
					
					var format_list=formats.split(",");
					//それぞれの play 命令
					if(format_list.length)
					for(var list_num=0;list_num<format_list.length;list_num++){
						enable_queue=target=loop_count=fps=false;
						var format_parts=format_list[list_num].split(":");
						if(!format_parts){
							format_parts={};
						}
						
						span=format_parts[0];
						loop_count=parseFloat(format_parts[1]);
						fps=parseFloat(format_parts[2]);
						//target=format_parts[3];
						
						if(!target)
							target=this;
						if(!loop_count)
							loop_count=	parseFloat(options[anime_id]["loop_count"]);
						if(!fps)
							fps=parseFloat(options[anime_id]["fps"]);
						
						if(loop_count!=-1){
							enable_queue=true;
							session[current_session_id]["queue"]["obj_list"][anime_id]["obj"]=this;
							session[current_session_id]["queue"]["obj_list"][anime_id]["status"]="wait";
							session[current_session_id]["queue"]["obj_count"]++;
						}
						
						var frame_count=options[anime_id]["frame_count"];
						var span_array=span.split("-");
						var start=span_array[0]?parseFloat(span_array[0]):1;//何コマ目から始めるか
						var end=span_array[1]?parseFloat(span_array[1]):frame_count;//終了コマ
						if(end>frame_count){
							end=frame_count;
						}
						if(start>frame_count){
							start=frame_count;
						}
						
						var interval=1000/fps;
						var play_num=start;//現在のコマ
						var play_loop_count=0;//現在のループ回数
						
						var anime_play=function(){
							session[current_session_id]["queue"]["obj_list"][anime_id]["status"]="play";
							var animetimer=setInterval(function(){
								if(loop_count<=0 || play_loop_count<loop_count){
									//コマを進める
									if(play_num<=end){
										$(target).attr("src",base_src.replace("[*anime_num*]",play_num++));
									}
									//最後まで行ったら最初に戻る
									if(play_num>end){
										play_num=start;
										play_loop_count++;
									}
								}else{
									//最大ループ回数を超えたら停止
									clearInterval(animetimer);
									session[current_session_id]["queue"]["obj_list"][anime_id]["status"]="complete";
									inner_data[anime_id]["timer"]=false;
									if(++session[current_session_id]["queue"]["playend_count"]==session[current_session_id]["queue"]["obj_count"]){
										session_end(current_session_id);
									}
								}
							},interval);
							inner_data[anime_id]["timer"]=animetimer;
						};
						if(enable_queue){
							$(this).queue(anime_play);
						}else{
							anime_play();
						}
					}
				}
			});
		}
		
		function pause(obj){
			obj.each(function(i){
				var anime_id=$(this).attr('anime_id');
				if(inner_data[anime_id]){
					var current_session_id=inner_data[anime_id]["current_session_id"];
					if(session[current_session_id]["queue"]["obj_list"]){
						session[current_session_id]["queue"]["obj_list"][anime_id]["status"]="complete";
						if(++session[current_session_id]["queue"]["playend_count"]==session[current_session_id]["queue"]["obj_count"]){
							session_end(current_session_id);
						}
					}
					
					if(inner_data[anime_id]["timer"]){
						clearInterval(inner_data[anime_id]["timer"]);
						inner_data[anime_id]["timer"]=null;
					}
				}
			});
		}
			
		//frame_num のコマにシークする
		function seek(obj,frame_num){
			frame_num=parseFloat(frame_num);
			obj.each(function(i){
				anime_id=get_anime_id(this);
				var base_src=inner_data[anime_id]["base_src"];
				
				$(this).attr("src",base_src.replace("[*anime_num*]",frame_num));
			});
		}
		
		//オプション値を設定
		function config(obj,config){
			var tagoption;//タグでのオプションを入れる一時的な変数。毎回上書き用
			var anime_id;
			var static_option={};//HTMLタグに直接記述するオプション
			
			if(!config)
				config={};
			
			obj.each(function(i){
				anime_id=get_anime_id(this);
				static_option[anime_id]={};
				
				if(tagoption=$(this).attr('auto_play')){
					static_option[anime_id]["auto_play"]=tagoption;
				}
				if(tagoption=$(this).attr('loop_count')){
					static_option[anime_id]["loop_count"]=tagoption;
				}
				if(tagoption=$(this).attr('frame_count')){
					static_option[anime_id]["frame_count"]=tagoption;
				}
				if(tagoption=$(this).attr('fps')){
					static_option[anime_id]["fps"]=tagoption;
				}
				
				//デフォルトオプションの設定
				options[anime_id]={
					loop_count : -1
					,fps : 30
					//frame_count
				};
				options[anime_id]=$.extend(options[anime_id], static_option[anime_id]);
				options[anime_id]=$.extend(options[anime_id], config);
				options[anime_id]["frame_count"]=options[anime_id]["frame_count"]?parseFloat(options[anime_id]["frame_count"]):0;
			});
		}
		
		//画像を先に読み込んでおく
		function img_preload(anime_id){
			if(!inner_data[anime_id]["pre_loaded"]){
				if(!$("#img_preload").length){
					$(document.body).prepend('<div id="img_preload" style="display:none;"></div>');
				}
				var i=1;
				var src;
				var frame_count=options[anime_id]["frame_count"];
				var preload_base_src=inner_data[anime_id]["base_src"];
				
				while(i<=frame_count){
					src=preload_base_src.replace("[*anime_num*]",i);
					$("#img_preload").append('<img src="'+src+'" class="imganime_preload"/>');
					i++;
				}
				inner_data[anime_id]["pre_loaded"]=true;
			}
		}
		
		function get_anime_id(dom_obj){
			var tagoption;//タグでのオプションを入れる一時的な変数。毎回上書き用
			var anime_id;
			if(tagoption=$(dom_obj).attr('anime_id')){
				anime_id=tagoption;
			}else{
				anime_id=$(dom_obj).set_uid();
				$(dom_obj).attr('anime_id',anime_id);
			}
			return anime_id;
		}
		
		//セッションを削除する
		function session_end(current_session_id){
			var obj;
			jQuery.each(session[current_session_id]["queue"]["obj_list"],function(anime_id){
				obj=session[current_session_id]["queue"]["obj_list"][anime_id]["obj"];
				$(obj).dequeue();
			});
			session[current_session_id]["queue"]={};
		}
	};
	
})(jQuery);

$(document).ready(function(){
	$(".auto_imganime").imganime("play");
}); 


