module kyojintati4d.taskeyecatche;

private import y4d;
private import y4d_thread.gamescenetransiter;
private import y4d_draw.transbltter;

private import kyojintati4d.myapp;
private import kyojintati4d.gameinfo;

private import yamalib.counterfsp;
private import yamalib.draw.sequencedrawmanager;
private import yamalib.log.log;


/**
	アイキャッチタスク
	プロキシタスク的に呼ばれる
*/
class TaskEyeCatche : GameTaskBase {

	/// 下の DEF_FILES とあわせる（昔のための互換性）
	enum SHI_TYPE : int {
		STD = 0,
		TOMIE01,
		ALICE01,
		ANZAI01,
		RUBI01,
		MIDO01,
		YUIRI01,
		AYA01,
	};

	/// タスク名を返却する
	/**
		このタスク名称を使って、コントローラ部でタスク判別を行う可能性があるので
		ユニークな名前で、実装しておくべきである
	*/	
	override char[] getTaskName() {
		with (kyojintati4d.val.kyojinconst) {
			return cast(char[]) KyojinConst.TASK_NAME[KyojinConst.Task.Task_EyeCatche];
		}
	}
	
	/// 毎回呼び出す
	override int onMove(Object o) {
		try {
			if (!m_init) {
				onInit(cast(GameInfo) o);
				m_init = true;
			}
			
			if (!(m_defaultTask is null)) {
				return m_defaultTask.onMove(o);
			} else if (!(m_writeTask is null)) {
				return m_writeTask.onMove(o);
			}

			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 {

			if (!(m_defaultTask is null)) {
				return m_defaultTask.onDraw(o);
			} else if (!(m_writeTask is null)) {
				return m_writeTask.onDraw(o);
			}

			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) {
		return 0;
	}
	
	/// 占有しているメモリを解放する
	override void destroy() {
		if (!(m_defaultTask is null)) {
			m_defaultTask.destroy();
		}
		if (!(m_writeTask is null)) {
			m_writeTask.destroy();
		}
	}

	/// コンストラクタ
	this() {
	}
private:

	/**
	 * ここでパラメータを判定してどちらかタスクを生成するか決める
	 */
	void onInit(GameInfo info) {
		
		// 引き渡されてきたパラメータ数が３つ以上ならば、“去人たち”アイキャッチ
		// ３番目にいれてくれー
		int[] v = info.getData();
		if (v.length >= 3) {
			m_writeTask = new TaskEyeCatcheWrite();
		} else {
			m_defaultTask = new TaskEyeCatcheDefault();
		}
	}

	bool m_init;
	TaskEyeCatcheDefault m_defaultTask;	// デフォルトのタスク
	TaskEyeCatcheWrite m_writeTask;		//!< 書くタスク
}


/**
 * デフォルトのアイキャッチ
 */
class TaskEyeCatcheDefault {

	/// 毎回呼び出す
	int onMove(Object o) {
		try {
			GameInfo info = cast(GameInfo) o;

			if (!init) {
				onInit(info);
				info.screen.blendSrcAlpha();
				m_imgBackup = info.gameSceneTransiter.getBackupTexture();
				init = true;
			}
			
			switch (m_processType) {
			case PROCESS_TYPE.CHENGE_BG:
				m_phase++;
				if ( m_phase.isEnd() ) {
					m_phase.set(0, 255, 2);
					m_processType = PROCESS_TYPE.FADE_IN;
				}
				break;
			case PROCESS_TYPE.FADE_IN:
				m_phase++;
				// ある程度はからはスライドを並行させる
				if ( m_phase.get() > 32 ) {
					m_processType = PROCESS_TYPE.SLIDE;
					Log.print("STEP : PROCESS_TYPE.SLIDE");
				}
				break;
			case PROCESS_TYPE.SLIDE:
				m_offsetCounter.inc();
				m_phase.inc();
				
				if ( m_offsetCounter.isEnd() && m_phase.isEnd() ) {
					m_phase.set(255, 0, 2);
					m_processType = PROCESS_TYPE.FADE_OUT;
					Log.print("STEP : PROCESS_TYPE.FADE_OUT");
				}
				break;
			case PROCESS_TYPE.FADE_OUT:
				if ( m_waitCount >= WAIT_TIME ) {
					m_phase++;
				} else {
					++m_waitCount;
				}
				if ( m_phase.isEnd() ) {
					int[] v = info.getData();
					if ( KyojinConst.Task.Task_Scenario == v[0] ) {
						jumpScenario( info, v[1] );
						return -1;
					} else {
						// TODO 呼び出されるコンテクストで適宜追加...
						Log.print("ERROR TASK_ID = %s", v[0]);
					}
				}
				break;
			default:
				assert(false);
			}
			
			return 0;
		} catch (Exception e) {
			Log.printFatal("RuntimeException %s#onMove : [%s] [%s]", 
				super.toString(), e.toString(), e.msg);
			throw e;
		}
	}
	
	/// 毎回呼び出すなり
	int onDraw(Object o) {
		try {
			GameInfo info = cast(GameInfo) o;
			info.screen.clear();
			info.screen.setColor(255,255,255,255);

			switch (m_processType) {
			case PROCESS_TYPE.CHENGE_BG:
				// 前の画像
				info.screen.blt(m_imgBackup, 0,0);
				// 現在画像上書き
				TransBltter.blt(
					22,
					info.screen,
					m_imgBg,
					0, 0,
					m_phase.get()
				);
				break;
			case PROCESS_TYPE.FADE_IN:
				info.screen.blt(m_imgBg,0,0);
				
				// 上
				TransBltter.blt(
					22,
					info.screen,
					m_imgUpperFrame,
					0, 0,
					m_phase.get()
				);
				// 下
				TransBltter.blt(
					23,
					info.screen,
					m_imgBottomFrame,
					0, 480 - cast(int) m_imgBottomFrame.getHeight(),
					m_phase.get()
				);

				// フェードイン
				info.screen.setColor(255,255,255,m_phase.get());
				info.screen.blt(m_imgTitle,TITLE_X, TITLE_Y);
				break;
			case PROCESS_TYPE.SLIDE:
				info.screen.blt(m_imgBg,0,0);
//				info.screen.blt(m_imgUpperFrame,0, 0);
//				info.screen.blt(m_imgBottomFrame,0, 480 - cast(int) m_imgBottomFrame.getHeight());
	
				// 上
				TransBltter.blt(
					22,
					info.screen,
					m_imgUpperFrame,
					0, 0,
					m_phase.get()
				);
				// 下
				TransBltter.blt(
					23,
					info.screen,
					m_imgBottomFrame,
					0, 480 - cast(int) m_imgBottomFrame.getHeight(),
					m_phase.get()
				);
				info.screen.setColor(255,255,255,m_phase.get());
				info.screen.blt(m_imgTitle,TITLE_X, TITLE_Y);
				info.screen.setColor(255,255,255,255);
				info.screen.blt(m_imgHorizonalBar, 
					m_offsetCounter.get() - cast(int) m_imgHorizonalBar.getWidth(), 
					HORIZONAL_BAR_Y);

				info.screen.blt(m_imgVarticallBar, 
					VARTICAL_BAR_X, 
					(480 - cast(int) m_imgVarticallBar.getHeight()) 
					+ (cast(int) m_imgVarticallBar.getHeight() - m_offsetCounter.get()) );

				break;

			case PROCESS_TYPE.FADE_OUT:
				info.screen.setColor(255,255,255,m_phase.get());
				info.screen.blt(m_imgBg,0,0);
				info.screen.blt(m_imgUpperFrame,0, 0);
				info.screen.blt(m_imgBottomFrame,0, 480 - cast(int) m_imgBottomFrame.getHeight());
				info.screen.blt(m_imgTitle,TITLE_X, TITLE_Y);
				info.screen.blt(m_imgHorizonalBar, 0, HORIZONAL_BAR_Y);
				info.screen.blt(m_imgVarticallBar, VARTICAL_BAR_X, 
					480 - cast(int) m_imgVarticallBar.getHeight() );
				break;
			default:
				assert(false);
			}

			info.screen.setColor(255,255,255,255);
	
			return 0;
		} catch (Exception e) {
			Log.printFatal("RuntimeException %s#onDraw : [%s] [%s]", 
				super.toString(), e.toString(), e.msg);
			throw e;
		}
	}
	
	/// 占有しているメモリを解放する
	void destroy() {
		Texture.safeRelease(m_imgBackup);
		Texture.safeRelease(m_imgBg);
		Texture.safeRelease(m_imgTitle);
		Texture.safeRelease(m_imgHorizonalBar);
		Texture.safeRelease(m_imgVarticallBar);
		Texture.safeRelease(m_imgBottomFrame);
		Texture.safeRelease(m_imgUpperFrame);
		m_imgBackup = null;
		m_phase = cast(RootCounterS) null;
		m_offsetCounter = null;

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

	/// コンストラクタ
	this() {
		m_phase = new RootCounterS();
//		m_offsetCounter = new FreeLineCounter(new RootCounterS());
		m_offsetCounter = new RootCounterS();
	}
private:
	/// 処理タイプ	
	enum PROCESS_TYPE {
		CHENGE_BG,
		FADE_IN,
		SLIDE,
		FADE_OUT
	};
	
	static const int TITLE_X = 25;
	static const int TITLE_Y = 247;
	static const int VARTICAL_BAR_X =8;
	static const int HORIZONAL_BAR_Y =232;

	static const int WAIT_TIME = 60;
	
	

	/// 初期化処理
	void onInit(GameInfo info) {
		// キャッシュクリア
		info.releaseAllCache();
		
		// メモリー状況をプリント
		GameInfo.printMemoryState();

		// テクスチャのロード
		loadTexture();
		
		int frameSize = cast(int) m_imgHorizonalBar.getWidth();
		// アルファ
		m_phase.set(0, 255, 4);
		
		// スライド用
		m_offsetCounter.set(0, frameSize, 10);
		
		m_processType = PROCESS_TYPE.CHENGE_BG;
		
	}
	
	/// テクスチャのロード
	void loadTexture() {
		m_imgBg = new Texture();
		m_imgTitle = new Texture();
		m_imgHorizonalBar = new Texture();
		m_imgVarticallBar = new Texture();
		m_imgBottomFrame = new Texture();
		m_imgUpperFrame = new Texture();

		m_imgBg.load(cast(char[]) "img/eyecatch/ec_bg_dammy.png");
		m_imgBg.load(cast(char[]) "img/eyecatch/ec_bg_dammy.png");
		m_imgTitle.load(cast(char[]) "img/eyecatch/ec_t.png");
		m_imgHorizonalBar.load(cast(char[]) "img/eyecatch/ec_line.png");
		m_imgVarticallBar.load(cast(char[]) "img/eyecatch/ec_line_v.png");
		m_imgUpperFrame.load(cast(char[]) "img/eyecatch/ec bar_1.png");
		m_imgBottomFrame.load(cast(char[]) "img/eyecatch/ec bar_2.png");
	}
	
	/// シナリオタスクに遷移する
	void jumpScenario(GameInfo info, int sId) {
		info.selectedStory = sId;
		// 強制バックアップを行う
		info.gameSceneTransiter.setTransitType( GameSceneTransiter.C_NO_EFFECT, 1, true );
		info.gameSceneTransiter.jumpScene(KyojinConst.Task.Task_Scenario);
	}

	bool init;
	Texture m_imgBackup;
	Texture m_imgBg;
	Texture m_imgTitle;
	Texture m_imgHorizonalBar;
	Texture m_imgVarticallBar;
	Texture m_imgBottomFrame;
	Texture m_imgUpperFrame;
	
	int m_waitCount;
	
	RootCounterS m_phase;
	ICounter m_offsetCounter;
	PROCESS_TYPE m_processType;
}


/**
 * “去人たち”描画するアイキャッチ
 */
class TaskEyeCatcheWrite {

	/// 下の DEF_FILES とあわせるのぢゃ！
	enum SHI_TYPE : int {
		STD = 0,
		TOMIE01,
		ALICE01,
		ANZAI01,
		RUBI01,
		MIDO01,
		YUIRI01,
		AYA01,
		NO_CHARA
	};
	
	/// 毎回呼び出す
	int onMove(Object o) {
		try {
			GameInfo info = cast(GameInfo) o;
	
			if (!init) {
				onInit(info);
				info.screen.blendSrcAlpha();
				backup = info.gameSceneTransiter.getBackupTexture();
				init = true;
			}
			
			phase++;
			
			if ( phase.isEnd() ) {
				sdm.onMove(info.screen);
				
				if ( sdm.isFinish() ) {
					
					int[] v = info.getData();
					
					if ( KyojinConst.Task.Task_Scenario == v[0] ) {
						// シナリオ画面へ
						jumpScenario( info, v[1] );
						return -1;
					} else if ( KyojinConst.Task.Task_Title == v[0] ) {
						// タイトル画面へ
						jumpTitle(info);
						return -1;
						
					} else {
						// TODO 呼び出されるコンテクストで適宜追加...
						Log.print("ERROR TASK_ID = %s", v[0]);
					}
					
				}
			}
				
			return 0;
		} catch (Exception e) {
			Log.printFatal("RuntimeException %s#onMove : [%s] [%s]", 
				super.toString(), e.toString(), e.msg);
			throw e;
		}
	}
	
	/// 毎回呼び出すなり
	int onDraw(Object o) {
		try {
			GameInfo info = cast(GameInfo) o;
			
			info.screen.clear();
	
			info.screen.setColor(255,255,255,255);
			TransBltter.blt(
				22,
				info.screen,
				backup,
				0, 0,
				phase.get()
			);
	
			if ( phase.isEnd() ) {
				sdm.onDraw(info.screen);
			}
			
			return 0;
		} catch (Exception e) {
			Log.printFatal("RuntimeException %s#onDraw : [%s] [%s]", 
				super.toString(), e.toString(), e.msg);
			throw e;
		}
	}
	
	/// 古いやつ
	int task(Object o) {
		return 0;
	}
	
	/// 占有しているメモリを解放する
	void destroy() {
		sdm = null;
		backup = null;
		phase = cast(RootCounterS) null;
	}

	/// コンストラクタ
	this() {
		phase = new RootCounterS();
	}
private:

	/// 定義ファイル固定リスト
	static const char[][] DEF_FILES = [
		"img/eye/std/std.lst",
		"img/eye/tomie/tomie01.lst",
		"img/eye/alice/alice01.lst",
		"img/eye/anzai/anzai01.lst",
		"img/eye/rubi/rubi01.lst",
		"img/eye/mido/mido01.lst",
		"img/eye/yuiri/yuiri01.lst",
		"img/eye/aya/aya01.lst",
	];
	

	/// 初期化処理
	void onInit(GameInfo info) {
		sdm = new SequenceDrawManager();
		
		// ３番目にいれてくれー
		int[] v = info.getData();
		int selNo = 0;
	
		if (v.length >= 3) {
			if ( v[2] < DEF_FILES.length ) {
				selNo = v[2];
			}
		}	
		
		sdm.loadDefFile(cast(char[]) DEF_FILES[selNo]);
		phase.set(255, 130, 2 );
	}
	
	/// シナリオタスクに遷移する
	void jumpScenario(GameInfo info, int sId) {
		info.selectedStory = sId;
		// 強制バックアップを行う
		info.gameSceneTransiter.setTransitType( GameSceneTransiter.C_NO_EFFECT, 1, true );
		info.gameSceneTransiter.jumpScene(KyojinConst.Task.Task_Scenario);
	}

	/// シナリオタスクに遷移する
	void jumpTitle(GameInfo info) {
		// 強制バックアップを行う
		info.gameSceneTransiter.setTransitType( GameSceneTransiter.C_NO_EFFECT, 1, true );
		info.gameSceneTransiter.jumpScene(KyojinConst.Task.Task_Title);
	}

	SequenceDrawManager sdm;
	bool init;
	Texture backup;
	RootCounterS phase;
}

