module kyojintati4d.component.ending.scene02;

private import y4d;
private import y4d_draw.transbltter;

private import kyojintati4d.gameinfo;
private import kyojintati4d.component.rhythm.keyconfigdialon;
private import kyojintati4d.component.ending.scenebase;

private import yamalib.counterfsp;
private import yamalib.log.log;

/**
 * シーン１の効果を取り扱うクラス
 */
public class Scene02 : EndingSceneBase {
	/// コンストラクタ
	this(FixTimer timer) {
		// 使用する画像をロード
		textureLoader = new TextureLoader();
		textureLoader.setCacheSize(-1);
		textureLoader.loadDefFile(cast(char[]) "img2/ending/s02/list.txt");
		this.timer = timer;
		setupTimingData();
	}

	/// すべての画像をキャッシュする	
	override void cacheTexture() {
		cacheTextureAll(textureLoader);
	}

	// シーンは開始しているか
	override bool isStart() {
		return START_TIME <= timer.get();
	}
	
	// 念のため時間でも終了時間もチェック
	private static const uint END_TIME = 89_300 + MUSIC_OFFSET_TIME; 
	// シーンが終了したか
	override bool isEnd() {
		return sceneEndFlg || END_TIME <= timer.get();
	}
	
	// リソースの解放
	override void release() {
		textureLoader.releaseAll();
		textureLoader.releaseFileList();
	}


	/// タイミングデータ作成
	protected void setupTimingData() {
		TimingData[] t2_1 = [
			new TimingData(MUSIC_OFFSET_TIME + 65_480, [&eventCallback1_1]),
			new TimingData(MUSIC_OFFSET_TIME + 66_820, [&eventCallback1_2]),
			new TimingData(MUSIC_OFFSET_TIME + 68_160, [&eventCallback1_3]),
			new TimingData(MUSIC_OFFSET_TIME + 69_490, [&eventCallback1_4]),
			new TimingData(MUSIC_OFFSET_TIME + 69_650, [&eventCallback1_5]),
			new TimingData(MUSIC_OFFSET_TIME + 70_830, [&eventCallback1_6]),
			new TimingData(MUSIC_OFFSET_TIME + 72_160, [&eventCallback1_7]),
			new TimingData(MUSIC_OFFSET_TIME + 73_490, [&eventCallback1_8]),
			new TimingData(MUSIC_OFFSET_TIME + 74_160, [&eventCallback1_9]),
			new TimingData(MUSIC_OFFSET_TIME + 74_270, [&eventCallback1_10]),
			new TimingData(MUSIC_OFFSET_TIME + 74_650, [&eventCallback1_11]),
			new TimingData(MUSIC_OFFSET_TIME + 74_840, [&eventCallback1_12]),
			new TimingData(MUSIC_OFFSET_TIME + 74_950, [&eventCallback1_13]),
		];
		m_timingData ~= t2_1;

		TimingData[] t2_2 = [
			new TimingData(MUSIC_OFFSET_TIME + 76_150, [&eventCallback2_1]),
			new TimingData(MUSIC_OFFSET_TIME + 77_490, [&eventCallback2_2]),
			new TimingData(MUSIC_OFFSET_TIME + 78_820, [&eventCallback2_3]),
			new TimingData(MUSIC_OFFSET_TIME + 80_190, [&eventCallback2_4]),
			new TimingData(MUSIC_OFFSET_TIME + 80_330, [&eventCallback2_5]),
			new TimingData(MUSIC_OFFSET_TIME + 81_610, [&eventCallback2_6]),
			new TimingData(MUSIC_OFFSET_TIME + 82_820, [&eventCallback2_7]),
			new TimingData(MUSIC_OFFSET_TIME + 83_490, [&eventCallback2_8]),
			new TimingData(MUSIC_OFFSET_TIME + 84_150, [&eventCallback2_9]),
			new TimingData(MUSIC_OFFSET_TIME + 84_800, [&eventCallback2_10]),
			new TimingData(MUSIC_OFFSET_TIME + 85_550, [&eventCallback2_11]),
			new TimingData(MUSIC_OFFSET_TIME + 87_480, [&eventCallback2_12]),
			new TimingData(MUSIC_OFFSET_TIME + 87_840, [&eventCallback2_13]),
			new TimingData(MUSIC_OFFSET_TIME + 88_000, [&eventCallback2_14]),
			new TimingData(MUSIC_OFFSET_TIME + 88_300, [&eventCallback2_15]),
		];
		m_timingData ~= t2_2;
		
		phase1_1 = new PhaseDraw(textureLoader, 0);
		phase1_1.fadeStart();
		phase1_2 = new PhaseDraw(textureLoader, 6);
		phase2_1 = new PhaseDraw(textureLoader, 15);
		phase2_2 = new PhaseDraw(textureLoader, 21);
	}
	
	static const uint START_TIME = 65_000 + MUSIC_OFFSET_TIME;
	/// 移動処理
	void onMove(Screen screen) {
		if (!startFlg) {
			if (START_TIME <= timer.get()) {
				startFlg = true;
			}
		} else {
			phase1_1.onMove(screen);
			phase1_2.onMove(screen);
			phase2_1.onMove(screen);
			phase2_2.onMove(screen);
			foreach (hitEffect; hitEffects) {
				if (hitEffect !is null) {
					hitEffect.onMove(screen);
				}
			}
		}
	}
	
	/// 描画処理
	void onDraw(Screen screen) {
		if (startFlg) {
			phase1_1.onDraw(screen);
			phase1_2.onDraw(screen);
			phase2_1.onDraw(screen);
			phase2_2.onDraw(screen);
			foreach (hitEffect; hitEffects) {
				if (hitEffect !is null) {
					hitEffect.onDraw(screen);
				}
			}
		}
	}
	
protected:

	PhaseBase[] activePhase;
	TextureLoader textureLoader;
	FixTimer timer;
	bool startFlg = false;
	HittingEffect[] hitEffects;

	// ========================================================================================== //
	// =================================     PHASE 1 - 1     ==================================== //
	// ========================================================================================== //
	
	static const int P1_1_FADEOUT_SPEED = 10;
	
	static class Phase1Base : PhaseBase {
		/// 初期化処理
		this(TextObj obj, TextureLoader loader, HitStatus status) {
			phase = new RootCounterS(0, 255, 30);
			super(obj, loader, status);
		}

		/// ローダの画像番号
		void setImgNo(int no) {
			imgNo = no;
		}
		
		/// 描画位置
		void setXY(int x, int y) {
			posx = x;
			posy = y;
		}
		void getXY(out int x, out int y) {
			x = posx;
			y = posy;
		}
		
		/// トランスブリッタ用のカウンタ
		RootCounterS getTransCounter() {
			return phase;
		}
		
		/// トランスブリッタの効果番号
		void setEffectNo(int no) {
			effectNo = no;
		}
		void getEffectNo() {
			return effectNo;
		}

		/// 移動処理
		void onMove(Screen screen) {
			if (start) {
				phase.inc();
			}
		}
		/// 描画処理
		void onDraw(Screen screen) {
			if (start && !end) {
				setScreenColorMax(screen);
				TransBltter.blt(effectNo, screen, m_textureLoader.get(imgNo), posx, posy, phase.get());
			}
		}
		
	private:
		int effectNo;
		int posx;
		int posy;
		int imgNo;
		RootCounterS phase;
	}
	
	/** 描画クラス */
	static class PhaseDraw {
		/// 初期化処理
		this(TextureLoader loader, int bgNo) {
			assert(loader !is null);
			txtureLoader = loader;
			this.bgNo = bgNo;
			alpha =  new RootCounterS(255, 255, 1);
		}
		
		///　終了フラグ
		bool isEnd() {
			return end;
		}
		bool isEnd(bool value) {
			return end = value;
		}
		
		// 開始フラグ
		bool isStart() {
			return start;
		}
		bool isStart(bool value) {
			return start = value;
		}
		
		// フェードスタート
		void fadeStart() {
			start = true;
			alpha.set(0, 255, 15);
		}

		// フェードスタート
		void fadeEnd() {
			alpha.set(255, 0, 15);
			fadeEndFlg = true;
		}

		/// 動作処理
		void onMove(Screen screen) {
			if (!end) {
				alpha.inc();
				if (fadeEndFlg && alpha.isEnd()){
					end = true;
Log.print("PHASE EDN\n");
				}
				foreach(p;phase) {
					p.onMove(screen);
				}
			}
		}
		
		/// 描画処理
		void onDraw(Screen screen) {
			if (start && !end) {
				// 背景描画
				screen.setColor(255,255,255,alpha.get());
				screen.blt(txtureLoader.get(bgNo), 0, 0);
				foreach(p;phase) {
					p.onDraw(screen);
				}
			}
		}
		
		/// 次の画像を追加
		void next(TextObj obj, HitStatus status, int imgNo, int x, int y, int effectNo) {
			auto instance = new Phase1Base(obj, txtureLoader, status);
			instance.setImgNo(imgNo);
			instance.setXY(x,y);
			instance.getTransCounter.set(0,255,15);
			instance.setEffectNo(effectNo);
			
			phase ~= instance;
		}

	private:
		RootCounterS alpha;
		bool fadeEndFlg;
		bool start;
		bool end;
		TextureLoader txtureLoader;
		int bgNo;
		Phase1Base[] phase;
	}
	
protected:
	bool sceneEndFlg = false;

private:
	PhaseDraw phase1_1;
	PhaseDraw phase1_2;
	PhaseDraw phase2_1;
	PhaseDraw phase2_2;

	// ========================================================================================== //
	// =================================     PHASE 1 - 1     ==================================== //
	// ========================================================================================== //
	
	/// 1-1
	bool eventCallback1_1(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase1_1.next(textObj, status, 1, 15, 47, 20);
			
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}
	
	/// 1-2
	bool eventCallback1_2(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase1_1.next(textObj, status, 2, 15, 81, 20);
		
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}
	/// 1-3
	bool eventCallback1_3(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase1_1.next(textObj, status, 3, 15, 115, 20);
	
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}
	
	/// 1-4
	bool eventCallback1_4(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase1_1.next(textObj, status, 4, 15, 149, 20);
	
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}

	/// 1-5
	bool eventCallback1_5(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase1_1.next(textObj, status, 5, 15, 251, 20);
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}

	/// 1-6 有瀬
	bool eventCallback1_6(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {

		// 前のフェーズを終わらせておく
		phase1_1.fadeEnd();
			
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase1_2.fadeStart();
			phase1_2.next(textObj, status, 7, 9, 49, 20);
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}

	/// 1-7
	bool eventCallback1_7(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase1_2.next(textObj, status, 8, 9, 83, 20);
	
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}

	/// 1-8
	bool eventCallback1_8(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase1_2.next(textObj, status, 9, 9, 117, 20);
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}

	/// 1-9
	bool eventCallback1_9(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase1_2.next(textObj, status, 10, 9, 185, 20);
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}

	/// 1-10
	bool eventCallback1_10(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase1_2.next(textObj, status, 11, 9, 219, 20);
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}

	/// 1-11
	bool eventCallback1_11(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase1_2.next(textObj, status, 12, 9, 253, 20);
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}

	/// 1-12
	bool eventCallback1_12(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase1_2.next(textObj, status, 13, 9, 287, 20);
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}

	/// 1-13
	bool eventCallback1_13(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase1_2.next(textObj, status, 14, 9, 321, 20);
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}


	// ========================================================================================== //
	// =================================     PHASE 2 - 2     ==================================== //
	// ========================================================================================== //
	/// 2-1 リサ
	bool eventCallback2_1(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {

		hitEffects = null;
		
		// 前のフェーズを終わらせておく
		phase1_2.fadeEnd();
			
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase2_1.fadeStart();
			phase2_1.next(textObj, status, 16, 11, 132, 20);
			
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}
	/// 2-2 
	bool eventCallback2_2(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase2_1.next(textObj, status, 17, 11, 199, 20);
	
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}

	/// 2-3 
	bool eventCallback2_3(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase2_1.next(textObj, status, 18, 11, 264, 20);
	
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}
	/// 2-4
	bool eventCallback2_4(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase2_1.next(textObj, status, 19, 11, 300, 20);
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}
	/// 2-5　
	bool eventCallback2_5(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase2_1.next(textObj, status, 20, 11, 368, 20);
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}
	
	
	/// 2-6 ノゾミ
	bool eventCallback2_6(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {

		// 前のフェーズを終わらせておく
		phase2_1.fadeEnd();
			
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase2_2.fadeStart();
			phase2_2.next(textObj, status, 22, 6, 15, 20);
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}

	/// 2-7
	bool eventCallback2_7(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase2_2.next(textObj, status, 23, 6, 49, 20);
			hitEffects ~= createHitEffect(textObj);
		}		
		// 後は自前でやるのででええわー
		return true;
	}
	
	/// 2-8
	bool eventCallback2_8(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase2_2.next(textObj, status, 24, 6, 83, 20);
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}
	
	/// 2-9
	bool eventCallback2_9(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase2_2.next(textObj, status, 25, 6, 117, 20);
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}
	
	/// 2-10
	bool eventCallback2_10(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase2_2.next(textObj, status, 26, 6, 151, 20);
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}
	
	/// 2-11
	bool eventCallback2_11(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase2_2.next(textObj, status, 27, 6, 185, 20);
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}
	
	/// 2-12
	bool eventCallback2_12(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase2_2.next(textObj, status, 28, 6, 219, 20);
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}
	
	/// 2-13
	bool eventCallback2_13(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase2_2.next(textObj, status, 29, 6, 253, 20);
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}
	
	/// 2-14
	bool eventCallback2_14(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase2_2.next(textObj, status, 30, 6, 287, 20);
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}
	
	/// 2-15
	bool eventCallback2_15(Screen screen, TextObj textObj, long hitTime, 
		HitStatus status) {
		// ステータスカウント
		countHitStatus(status);
		if (isHitedStatus(status)) {
			phase2_2.next(textObj, status, 31, 6, 321, 20);
	
			// 前のフェーズを終わらせておく
			phase2_2.fadeEnd();
	
			hitEffects ~= createHitEffect(textObj);
		}
		// 後は自前でやるのででええわー
		return true;
	}
}