module kyojintati4d.tasktelop;

private import y4d;
private import y4d_aux.filesys;
private import kyojintati4d.myapp;
private import kyojintati4d.gameinfo;

private import yamalib.draw.effectsoft;
private import yamalib.headlinear;
private import yamalib.counterfsp;
private import yamalib.log.log;

/***
	シナリオテロップクラス
*/
class TaskTelop : GameTaskBase {

	/// タスク名を返却する
	/**
		このタスク名称を使って、コントローラ部でタスク判別を行う可能性があるので
		ユニークな名前で、実装しておくべきである
	*/	
	override char[] getTaskName() {
		with (kyojintati4d.val.kyojinconst) {
			return cast(char[]) KyojinConst.TASK_NAME[KyojinConst.Task.Task_Telop];
		}
	}

	/// 移動の処理を行います
	override int onMove(Object o) {
		try {
			info = cast(GameInfo)o;
			if ( info.gameSceneTransiter.isTransit() ) {
				info.screen.setClearColor(255,255,255);
				return 0;
			}

			if (!init) {
				onInit();
				info.screen.setClearColor(0,0,0);
			}
			
			
			switch (m_processType) {
			case PROCESS_TYPE.FADE_IN:
				m_index.inc();
				if (m_index.isEnd() && ++m_waitCount >= WAIT_TIME) {
					m_processType = PROCESS_TYPE.FADE_OUT;
				}
				break;
			case PROCESS_TYPE.FADE_OUT:
				m_alpha.inc();
				if ( m_alpha.isEnd() ) {
					info.gameSceneTransiter.setTransitType( 5, 5 );
					info.gameSceneTransiter.returnScene();
					destroy();
					Log.print("TELOP TASK FINISH");
					return -1;
				}
				break;
			default:
				assert(false);
			}
	
			return 0;
		} catch (Exception e) {
			Log.printFatal("RuntimeException %s#onMove : [%s] [%s]", 
				super.toString(), e.toString(), e.msg);
			throw e;
		}
	}

	/// 描画の処理を行います
	override int onDraw(Object o) {
		try {
			info = cast(GameInfo) o;
	
			if ( info.gameSceneTransiter.isTransit() ) {
				return 0;
			}
	
			// 画面消去
			info.screen.clear();

			switch (m_processType) {
			case PROCESS_TYPE.FADE_IN:
				info.screen.blt(m_imgs.get(m_index.get()), 0, 0, null, cast(Size*) &BG_DRAW_SIZE);
				break;
			case PROCESS_TYPE.FADE_OUT:
				info.screen.setColor(255,255,255, m_alpha.get());
				info.screen.blt(m_imgs.get(m_index.get()), 0, 0, null, cast(Size*) &BG_DRAW_SIZE);
				break;
			default:
				assert(false);
			}
			
			return 0;
		} catch (Exception e) {
			Log.printFatal("RuntimeException %s#onDraw : [%s] [%s]", 
				super.toString(), e.toString(), e.msg);
			throw e;
		}
	}

	/// レガシーなヤツ。使わない。
	override int task(Object o) {
		assert(false);
		return 0;
	}

	/// タスクが使用したインスタンスを破棄し、ＧＣを起動する
	override void destroy() {
		m_alpha = cast(RootCounterS) null;
		if (m_imgs !is null) {
			m_imgs.releaseAll();
			m_imgs.releaseFileList();
		}
		Texture.safeRelease(m_texture);
		m_index = null;
		foreach(Surface surface; m_surfacese) {
			if ( !(surface is null) ) { 
				surface.release();
			}
		}

		Log.print("%s#destroy : destroyed.", super.toString());
	}

	/// コンストラクタ
	this() {
		m_alpha = new RootCounterS();
		m_alpha.set(255, 0, 4);
		
		m_texture = new Texture();
		m_index = new RootCounterS();
	}

private:

	/// 引数に指定したサーフェイスのディープコピーを作成する
	static Surface copySurface(Surface surface_) {
		int width = cast(int) surface_.getWidth();
		int height = cast(int) surface_.getHeight();
		bool m_alpha = cast(bool) (surface_.getSurface().format.BitsPerPixel==32);

		// createDIBして転送したほうがはやいんでないかな...
		Surface surface = new Surface();
		surface.createDIB( width, height, m_alpha );

		surface.blt( surface_, 0, 0 );
		return surface;
	}

	static bool isEnable(int[] index, int val) {
		foreach(int i; index) {
			if (i == val) {
				return true;
			}
		}
		return false;
	}

	/// 初期化処理
	void onInit() {
		// メモリー状況をプリント
		GameInfo.printMemoryState();

		Log.print("onInit START");
		init = true;
		int fileIndex = info.getData()[0];
		// 範囲チェック
		if (fileIndex<0 || fileIndex >= LIST_FILENAME.length) {
			Log.printError("TaskTelop#onInit : Invalid FILE ID : %s", fileIndex);
			fileIndex = 0;
		}
		
		m_imgs = new TextureLoader();
		m_imgs.setCacheSize(-1);	// 無限キャッシュ
		m_imgs.loadDefFile(cast(char[]) LIST_FILENAME[fileIndex]);

		// すべてキャッシュ
		for(int i = 0; i < m_imgs.getInfoList().size(); ++i) {
			Texture t = m_imgs.get(i);
		}

		m_index.set(0, m_imgs.getInfoList().size()-1, -10);
		
		m_processType = PROCESS_TYPE.FADE_IN;
		
		Log.print("onInit END");
	}
	
	/// 画像のロード
	void load(char[] filename) {
		// サーフェイスに読み込む
		Surface tmp = new Surface();
		tmp.load(filename);
		
		// 読み込んだ画像のコピー
		Surface tmp2 = copySurface(tmp);
		m_texture.setSurface(tmp2);
		
		m_surfacese ~= tmp;
		
		int[] index;
		float div = MAX_RESOLUTION / cast(float) RESOLUTION;
		index ~= 0;
		for(float f = 1.0f; f < MAX_RESOLUTION; f += div) {
			index ~= cast(int) f;
		}
		
		Surface effectTmp = copySurface( m_surfacese[length-1] );
		// ぼかしの段階画像をラスタライズしておく
		for (int i = 1; i < MAX_RESOLUTION; ++i) {
			effectTmp = EffectSoft.excecute(effectTmp, SOFT_SIZE);
			if ( isEnable(index, i) ) {
				m_surfacese ~= copySurface(effectTmp);
			}
		}
		effectTmp.release();
		Log.printLook("leng = %s", m_surfacese.length);		
		m_texture.setSurface( m_surfacese[length-1] );
	}
		


private:
	static  int MAX_RESOLUTION = 64;
	static int RESOLUTION = 96;
	static int SOFT_SIZE = 2;
	static const int WAIT_TIME = 300;
	
	static const Rect BG_DRAW_RECT = {left:0,top:0,bottom:480,right:480};
	static const Size BG_DRAW_SIZE = {cx:640,cy:480};
	
	enum PROCESS_TYPE {FADE_IN, FADE_OUT};

	/// テロップ定義ファイルの指定
	static const char[][] LIST_FILENAME = [
		"img/telop/telop1/telop1.lst",
		"img/telop/telop2/telop2.lst",
		"",
		"",
		"img/telop/telop3/telop3.lst",
		"img/telop/telop4/telop4.lst",
		"",
		"img/telop/telop6/telop6.lst",
	];

	GameInfo info;
	bool init;
	
	PROCESS_TYPE m_processType;
	TextureLoader m_imgs;	
	RootCounterS m_alpha;
	int m_waitCount;

	
	//-- プログラムぼかしの場合	
	Texture m_texture;
	ICounter m_index;
	Surface[] m_surfacese;
}


/+
/***
=============================================
	旧バージョン 2006/04/01 コメント
=============================================
	シナリオテロップクラス
*/
class TaskTelop : GameTaskBase {

	/// タスク名を返却する
	/**
		このタスク名称を使って、コントローラ部でタスク判別を行う可能性があるので
		ユニークな名前で、実装しておくべきである
	*/	
	override char[] getTaskName() {
		with (kyojintati4d.val.kyojinconst.KyojinConst) {
			return TASK_NAME[Task.Task_Telop];
		}
	}

	/// 移動の処理を行います
	override int onMove(Object o) {
		try {
			info = cast(GameInfo)o;
	
			if (!init) {
				onInit();
			}
			
			if ( info.gameSceneTransiter.isTransit() ) {
				return 0;
			}
	
			if ( headliner.isFinish() ) {
				stopCounter++;
				if ( stopCounter.isEnd() ) {
					m_alpha++;
				}
				
				if ( m_alpha.isEnd() ) {
					info.gameSceneTransiter.setTransitType( 5, 5 );
					info.gameSceneTransiter.returnScene();
					destroy();
					return -1;
				}
			}
	
			return 0;
		} catch (Exception e) {
			Log.printFatal("RuntimeException %s#onDraw : [%s] [%s]", 
				super.toString(), e.toString(), e.msg);
			throw e;
		}
	}

	/// 描画の処理を行います
	override int onDraw(Object o) {
		try {
			info = cast(GameInfo) o;
	
			if ( info.gameSceneTransiter.isTransit() ) {
				return 0;
			}
	
			// 画面消去
			info.screen.clear();
			
			// 背景の描画
			info.screen.blt(bg,0,0);
			
			// フェードアウト
			if (headliner.isFinish()) {
				if ( stopCounter.isEnd() ) {
					info.screen.setColor(255, 255, 255, m_alpha.get());
				}
			}
	
			headliner.onDraw(info.screen);
			return 0;
		} catch (Exception e) {
			Log.printFatal("RuntimeException %s#onDraw : [%s] [%s]", 
				super.toString(), e.toString(), e.msg);
			throw e;
		}
	}

	/// レガシーなヤツ。使わない。
	override int task(Object o) {
		info = cast(GameInfo)o;

		if (!init) {
			onInit();
		}

		// 背景の描画
		info.screen.blt(bg, 0, 0);
		headliner.onDraw(info.screen);

		return 0;
	}

	/// タスクが使用したインスタンスを破棄し、ＧＣを起動する
	override void destroy() {
		bg = null;
		headliner = null;
		headliner1 = null;
		m_alpha = null;
		stopCounter = null;
	}

	/// コンストラクタ
	this() {
		bg = new Texture;
		headliner = new ReduceHeadlinear;
		headliner1 = new SlideInHeadlinear;
		m_alpha = new RootCounterS();
		m_alpha.set(255, 0, 4);
		
		stopCounter = new RootCounterS();
		stopCounter.set(0, 100, 1);
	}

private:

	/// 初期化処理
	void onInit() {
//		bg.load(FileSys.makeFullName("img/telop/telop01.jpg"));
		init = true;

		int fileIndex = info.getData()[0];

		// 範囲チェック
		if (fileIndex<0 || fileIndex >= filename.length) {
			fileIndex = 0;
		}

		headliner.setStyle(ReduceHeadlinear.Style.BOTTOM_RIGHT);
		headliner.addTexture(filename[fileIndex]);
		headliner.setMargin(0,15,0,20);
		headliner.setInterval(30);
		headliner.setStartRate(5.5);
		headliner.setFadeOut(false);
		
		headliner1.setInterval(8);
		headliner1.setDisposeStep(40);

		SlideInHeadlinear.style s = cast(SlideInHeadlinear.style)1;
		headliner1.setXY(100,350);
		headliner1.setMoveXY(30,50);
		headliner1.setStyle(s);
		headliner1.setFadeOut(true);
		headliner1.addTexture( FileSys.makeFullName("img/telop/s2/telop02.lst") );
	}


private:

	/// テロップ定義ファイルの指定
	static const char[][] filename = [
		"img/telop/s1/telop01.lst",
		"img/telop/s2/telop02.lst",
		"img/telop/s3/telop03.lst",
		"img/telop/s4/telop04.lst",
		"img/telop/s5/telop05.lst",
		"img/telop/s6/telop06.lst",
	];

	GameInfo info;
	bool init;
	
	RootCounterS m_alpha;
	RootCounterS stopCounter;
	
	Texture bg;						//!< 背景テクスチャ
	ReduceHeadlinear headliner;		//!< 表題表示クラス
	SlideInHeadlinear headliner1;

}
+/