/*
*  Copyright 2008 tarotarorg
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package org.tarotaro.flash.pv3d {
	import flash.display.BitmapData;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.TimerEvent;
	import flash.display.Bitmap;
	import flash.display.Loader;
	import flash.events.EventDispatcher;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.utils.Dictionary;
	import flash.utils.Timer;
	import com.voidelement.images.BMPDecoder;
	import org.libspark.pv3d.decoders.TGADecoder;
	import org.tarotaro.flash.pv3d.ZipLoader;

	public class ImageManager extends EventDispatcher{
		////////////////////////////////////////////////////////////////////////////////////////
		//クラス変数定義
		////////////////////////////////////////////////////////////////////////////////////////
		/**
		 * ロードしたビットマップのキャッシュ
		 * ロード待ち中：null
		 * ロード済み：BitmapData
		 * ロード中：この画像をロードしているLoader
		 */
		private static var _loadedBitmaps:Dictionary = new Dictionary();
		////////////////////////////////////////////////////////////////////////////////////////
		//メンバ変数定義
		////////////////////////////////////////////////////////////////////////////////////////
		private var _bitmapData:BitmapData;
		private var _path:String;
		private var _name:String;

		/**
		 * ロードした画像をBitmapData形式で返す
		 * @return
		 */
		public function get bitmapData() :BitmapData {
			return this._bitmapData != null ? this._bitmapData.clone() : null;
		}

		/**
		 * ローダ名
		 * @return
		 */
		public function get name():String {
			return this._name;
		}

		/**
		 * ロード対象のパス
		 * @return
		 */
		public function get path():String {
			return this._path;
		}

		public function ImageManager(name:String):void {
			this._name = name;
		}

		public function getImage(path:String) : void {
			if (path.search( /\.(jpg|png|gif|tga|bmp)$/i) == -1) {
				throw new Error("非対応の画像形式です");
			}
			var bd:BitmapData = _loadedBitmaps[this.name] as BitmapData;
			if ( bd ) {
				//キャッシュ内に画像発見→イベントを投げる
				this._bitmapData = bd;
				trace("キャッシュから画像を発見：", this.name);
				dispatchEvent(new ImageManagerEvent(this));
			} else {
				//キャッシュ内に画像なし→ロード処理
				//trace("画像をロード：", this.name);
				this.load(path);
			}
		}
		private function load(path:String):void {
			this._path = path;
			this.loadBinary();
		}

		/**
		 * バイナリからエンコードする必要のある画像をロードする
		 * @return
		 */
		private function loadBinary():void {
			var loader:ZipLoader = _loadedBitmaps[this.name] as ZipLoader;
			if (loader == null ) {
				//新規にロードを実行
				loader = new ZipLoader();
				loader.dataFormat = URLLoaderDataFormat.BINARY;
				_loadedBitmaps[this.name] = loader;
				loader.addEventListener(Event.COMPLETE , binLoadComplete);
				loader.addEventListener(IOErrorEvent.IO_ERROR , defaultHandler);
				loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR , defaultHandler);
				loader.addEventListener(ProgressEvent.PROGRESS , defaultHandler);
				loader.load(new URLRequest(this._path));
			} else {
				//現在ロード中なのでちょっと待ってみる
				var waiting:Timer = new Timer(100 , 1);
				waiting.addEventListener(TimerEvent.TIMER_COMPLETE , waitingComplete);
				waiting.start();
			}
		}

		/**
		 * 画像ロード完了待ち
		 * @param	evt
		 */
		private function  waitingComplete(evt:TimerEvent):void {
			this.getImage(this._path);
		}

		/**
		 * デフォルトのイベント処理
		 * @param	evt
		 * @return
		 */
		private function defaultHandler(evt:Event):void {
			dispatchEvent( evt.clone());
		}

		/**
		 * 画像をバイト列として読み込み、デコードする
		 * @param	evt
		 * @return
		 */
		private function binLoadComplete(evt:Event):void {
			if (this.path.search( /\.(jpg|png|gif)$/i) != -1) {
				var ldr:Loader = new Loader();
				ldr.addEventListener(Event.COMPLETE, function (e:Event):void {
					this._bitmapData = (ldr.content as Bitmap).bitmapData;
					_loadedBitmaps[this.name] = this._bitmapData;
					dispatchEvent( new ImageManagerEvent(this));
				} );
				ldr.loadBytes(evt.target.data);
			} else if (this.path.search(/\.tga$/i) != -1) {
				var tga:TGADecoder = new TGADecoder(evt.target.data);
				this._bitmapData = tga.bitmap;
				_loadedBitmaps[this.name] = this._bitmapData;
				dispatchEvent( new ImageManagerEvent(this));
			} else if (this.path.search(/\.bmp$/i) != -1) {
				var bmpdec:BMPDecoder = new BMPDecoder();
				this._bitmapData = bmpdec.decode(evt.target.data);
				_loadedBitmaps[this.name] = this._bitmapData;
				dispatchEvent( new ImageManagerEvent(this));
			} else {
				throw new Error("非対応の画像形式です");
			}
		}
	}

}

