module y4d_thread.gamescenetransiter;

private import std.gc;

private import y4d_draw.texture;
private import y4d_draw.screen;
private import y4d_draw.transbltter;
private import y4d_thread.gametask;

/** シーントランジッタに渡すべきクラス */
interface SceneTransitable {
	public Screen getScreen();
}

/**
	yaneSDK2ndにあったシーントランジッタの簡易実装
*/
class GameSceneTransiter {
	
	/// エフェクトなし指定	
	static const int C_NO_EFFECT = -1;
	
	/** シーンコントローラを設定する */
	void setGameController(inout GameTaskController v, inout GameSceneController vv) {
		gameTaskController = v;
		gameSceneControl = vv;
	}
	
	/// 遷移エフェクト中か
	bool isTransit() {
		return bTrans;
	}
	
	/** 
		遷移タイプを設定する 
		エフェクト繊維を行うときに必ず呼び出すこと
		bForce をTRUE に設定すれば、エフェクトなしでも、強制的にバックアップを作る
	*/
	void setTransitType(int type, int speed, bool bForce=false, bool bWait=false) {
		transType = type;
		transSpeed = speed;
		this.bForceBackUp = bForce;
		this.bWait = bWait;
	}
		
	/** 移動 */
	int callTaskOnMove(SceneTransitable o) {
		st = o;
		if (bTrans) {
			transPhase -= transSpeed;
			if ( transPhase < 0 ) {
				bTrans = false;
				bWait = false;
				resetTranse();
			}
		}
		
		if (bWait) {
			return 0;
		}
		
		return gameTaskController.callTaskOnMove(cast(Object) o);
	}
	
	/** 描画 */
	int callTaskOnDraw(SceneTransitable o) {
		st = o;
		int status = 0;
		if (!bWait) {
			status = gameTaskController.callTaskOnDraw(cast(Object) o);
		}
		
		if ( bTrans ) {
			Screen screen = o.getScreen();
			screen.setColor(255, 255, 255, 255);
			screen.blendSrcAlpha();
			screen.clear();
			
			TransBltter.blt( 
				transType, 
				screen, 
				backupTex, 0, 0, transPhase);
		}
		
		return status;
	}
	

	///	次のシーンに飛ぶ
	void	jumpScene(int nPriority){
		setTransit();
		gameSceneControl.jumpScene(nPriority);
	}

	///	呼び出し元のシーンに戻る
	/**
		このときに、pushSceneでスタック上にシーンが積まれていれば、
		そちらを実体化する。
	*/
	void	returnScene(){
		setTransit();
		gameSceneControl.returnScene();
	}

	///	他のシーンを呼び出す(現在実行中のタスク自体は破棄しない)
	/**
		現在実行中のシーン破棄はされません。
		ただし、task関数のなかでは(現在実行中のシーンへreturnSceneなどで
		制御が戻ってくるまでは)呼び出されなくなります。
	*/
	void	callScene(int nPriority){
		setTransit();
		gameSceneControl.callScene(nPriority);
	}

	///	指定したタスクを指定した順番で呼び出す
	/**
		指定したタスクをシーンスタックに積みます。
		(returnSceneされたときに逆順で呼び出します)

		A,B,Cと呼び出したいならば、
			static int [] a = { Cのpriority,Bのpriority,Aのpriority };
			controller.pushScene(a);
		こんな感じ。
	*/
	void	pushScene(int[] a){
		gameSceneControl.pushScene(a);
	}

	///	シーンをすべて破棄
	/**
		これを呼び出すと isEnd が true を返すようになります。
	*/
	void	exitScene(){
		gameSceneControl.exitScene();
	}
	
	/// 遷移モードの初期化
	/**
		遷移モードをなしする（初期化する）
	*/
	void resetTranse() {
		transType = C_NO_EFFECT;
	}
	
	/// 内部で使用している、バックアップテクスチャを取得
	Texture getBackupTexture() {
		return backupTex;
	}
	
private:

	/** 遷移の準備を行う */
	void setTransit() {
		
		if ( transType == C_NO_EFFECT || st is null) {
			if ( this.bForceBackUp ) {
				backupTex = st.getScreen().backup();
			}
			return;
		}
		
		backupTex = st.getScreen().backup();
		bTrans = true;
		transPhase = 255;
	}

	GameSceneController gameSceneControl;
	GameTaskController gameTaskController;
	
	SceneTransitable st;
	Texture backupTex;
	int transType = C_NO_EFFECT;
	int transSpeed = 1;
	int transPhase = 255;
	bool bTrans;		//!< 遷移中かどうか
	bool bForceBackUp;	//!< 強制バックアップフラグ
	bool bWait;			//!< 遷移時にフェードアウトするまでまつか？
}

