module kyojintati4d.taskendingoption;

private import SDL;

private import y4d;
private import y4d_aux.filesys;
private import y4d_aux.lineparser;

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

private import yamalib.serialize;
private import yamalib.counterfsp;

private import yamalib.input.adapter;
private import yamalib.input.adaptedkey;
private import yamalib.input.multimouse;

private import yamalib.gui.guibutton;
private import yamalib.gui.keygroup;

private import yamalib.log.log;

/// オプション画面タスク
class TaskEndingOption : GameTaskBase {

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


	/// 移動の処理を行います
	override int onMove(Object o) {
		try {
			info = cast(GameInfo)o;
	
			// 初期化
			if (!init) {
				init = true;
				onInit();
			}
			
			info.screen.blendSrcAlpha();
			alpha++;
			m_tox++;
			
			m_mouse.update();
			// キー操作によるフォーカシング
			if ( info.key.isPush(1) ) {
				m_keyGroup.prev();
			} else if ( info.key.isPush(2) ) {
				m_keyGroup.next();
			} else {
				// フォーカス移動
				foreach (GUIButton parts; button) {
					if ( parts.isIn() ) {
						m_keyGroup.setSelectNo(parts);
						break;
					}
				}
			}
	
			// ボタンの移動
			foreach (inout GUIButton bt; button) {
				bt.onMove(info.screen);
			}
	
			// エフェクト中ならここでかえる
			if (!alpha.isEnd()) {
				return 0;
			}
	
			// ボタンクリックチェック
			GUIBlinkButtonListener v;
			GUIBlinkButtonListener.TYPE typeBlink = GUIBlinkButtonListener.TYPE.DEFAULT 
								| GUIBlinkButtonListener.TYPE.IN_ACTIVE;
			GUIBlinkButtonListener.TYPE typeFix = GUIBlinkButtonListener.TYPE.OFFSET_FIX; 

			for (int i = 0; i < button.length; ++i) {
				if ( info.isShowYesNo() ) {
					break;				
				}
				// クリックされた？
				if (button[i].isLClick()) {
					switch (i) {
					case eButtonID.AUTO_PLAY:
					case eButtonID.SHOW_GUIDE:
					case eButtonID.SHOW_MOVIE:
					case eButtonID.SHOW_TIME:
					case eButtonID.SHOW_SCORE:
						{
							onClickOption(i, optionValues[i]);
						}
						break;
					case eButtonID.START:
						{
							// タイトル画面ＢＧＭの終了
							info.bgmloader.stopFade(0,1000);

							// 設定したフラグを格納
							info.endingOptionFlg = optionValues;
							
							// すべてのスタックを破棄		
							info.gameSceneTransiter.exitScene();
							// 強制バックアップを行う
							info.gameSceneTransiter.setTransitType( 19, 1, true, true );
							info.gameSceneTransiter.jumpScene(KyojinConst.Task.Task_EndingKyojin);
						}
						break;
					case eButtonID.BACK:
						{
							info.gameSceneTransiter.returnScene();
							// セーブデータを保存しておく
							info.saveAppData();
							destroy();
							info.playSystemSE(SYS_SE.CLICK_TITLE_NEGATIVE);
						}
						return 1;
					default:
						Log.printError("UNDEF NUMBER : %d", i);
					}

					// ボタン押下SE再生
					info.playSEActive();
					
					break;
				}
				
			}
			
			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 (!init) {
				init = true;
				onInit();
			}

			info.screen.clear();
			info.screen.blendSrcAlpha();
	
			if (!alpha.isEnd()) {
				info.screen.setColor(255,255,255,alpha.get());
			}
	
			// 背景描画
			info.screen.blt(bg,0,0);
			// タイトル描画
			info.screen.blt(m_titleTex, m_tox.getSined(), 0);

			// アルファMAX
			info.screen.setColor( 255,255,255, 255 );
	
			// ボタンの描画
			foreach (inout GUIButton bt; button) {
				bt.onDraw(info.screen);
			}
			
			return 0;
		} catch (Exception e) {
			Log.printFatal("RuntimeException %s#onDraw : [%s] [%s]", 
				super.toString(), e.toString(), e.msg);
			throw e;
		}
	}

	/// OnDraw+OnMove
	override int task(Object o) {
		return 0;
	}

	/// オブジェクトのメモリを解放する
	override void destroy() {
		Texture.safeRelease(bg);

		alpha = cast(RootCounterS) null;
		
		m_keyGroup = null;
		button = null;
		
		if ( !(tl is null) ) {
			tl.releaseAll();
			tl.releaseFileList();
		}

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

	/// コンストラクタ
	this () {
		m_keyGroup = new KeyGroup();
		bg = new Texture;
		alpha = new RootCounterS(0,255,4);

		tl = new TextureLoader();
		tl.loadDefRW( FileSys.read(cast(char[]) "img2/ending/option/op_bt.lst") );

		// 表示位置
		static const PointInt[] point = [
			{x:238,y:100},	// オートプレイ
			{x:238,y:146},	// ガイド表示
			{x:238,y:192},	// ムービー表示
			{x:238,y:238},	// タイム表示
			{x:238,y:284},	// スコア表示
			{x:300,y:338},	// プレイ
			{x:538,y:425},	// 戻る
		];

		int i;
		foreach(inout PointInt pt; point) {
			GUIButton bt = new GUIButton;
			bt.setXY(pt.x, pt.y);
			button ~= bt;
			++i;
		}
		
		//
		optionValues = new bool[eButtonID.max];
	}

	/// コンストラクタ
	this (MouseInput mouse) {
		this();
		foreach (inout GUIButton bt; button) {
			bt.setMouse(mouse);
		}
	}

private:

	/// BGM OFF がクリックされたときの処理
	void onClickOption(int type, inout bool flg) {
		GUIBlinkButtonListener.TYPE typeBlink 
			= GUIBlinkButtonListener.TYPE.DEFAULT | GUIBlinkButtonListener.TYPE.IN_ACTIVE;
		GUIBlinkButtonListener.TYPE typeFix 
			= GUIBlinkButtonListener.TYPE.OFFSET_FIX; 
		GUIBlinkButtonListener v = 
			cast(GUIBlinkButtonListener) button[type].getEvent();
		if (flg) {
			v.setType(typeBlink);
		} else {
			v.setType(typeFix);
			v.setImageOffset(1);
		}

		flg = cast(bool) !flg;
	}
	
	/// 初期化
	void onInit() {
		// メモリー状況をプリント
		GameInfo.printMemoryState();

		m_mouse = info.keyDecolateMouse;

		foreach (inout GUIButton bt; button) {
			bt.setMouse(m_mouse);
		}

		// 背景テクスチャロード
		bg.load(FileSys.makeFullName(cast(char[]) "img2/ending/option/bg.jpg"));
		// タイトルテクスチャ
		m_titleTex = new Texture();
		m_titleTex.load(FileSys.makeFullName(cast(char[]) "img2/ending/option/op_title_last.png"));
		m_tox = new RootCounterS();
		m_tox.set(-50, 0, 1);

		// ボタンの画像番号
		static const int bt_no[] = 
			[	0,	// オートプレイ
				0,	// ガイド表示
				0,	// ムービー表示
				0,	// タイム表示
				0,	// スコア表示
				2,
				4
			];

		// ボタンの初期化
		foreach(int i,inout GUIButton bt; button) {
			GUIBlinkButtonListener v  = new GUIBlinkButtonListener();
			v.setTextureLader(tl,bt_no[i]);

			GUIBlinkButtonListener.TYPE typeBlink = GUIBlinkButtonListener.TYPE.DEFAULT 
								| GUIBlinkButtonListener.TYPE.IN_ACTIVE;

			switch (i) {
			case eButtonID.AUTO_PLAY:
			case eButtonID.SHOW_GUIDE:
			case eButtonID.SHOW_MOVIE:
			case eButtonID.SHOW_TIME:
			case eButtonID.SHOW_SCORE:
				{
					v.setType(typeBlink);
					v.setImageOffset(0);
				}
				break;
			case eButtonID.START:
				{
					v.setType(BT_TYPE_BACK);
					v.setBlinkSpeed(4);
				}
				break;
			case eButtonID.BACK:
				{
					v.setType(BT_TYPE_BACK);
					v.setBlinkSpeed(4);
				}
				break;
			default:
				assert(false);
			}

			bt.setEvent(v);
		}
		

		initKeyGroup();
		
		// フォーカスデフォルト設定
		m_keyGroup.focus(button[eButtonID.BACK]);
	}
	
	/// キーグループを初期化する
	void initKeyGroup() {
		m_keyGroup.add(button[eButtonID.AUTO_PLAY]);
		m_keyGroup.add(button[eButtonID.SHOW_GUIDE]);
		m_keyGroup.add(button[eButtonID.SHOW_MOVIE]);
		m_keyGroup.add(button[eButtonID.SHOW_TIME]);
		m_keyGroup.add(button[eButtonID.SHOW_SCORE]);
		m_keyGroup.add(button[eButtonID.START]);
		m_keyGroup.add(button[eButtonID.BACK]);
	}
	
private:
	// ボタンの名前付け
	enum eButtonID : int { 
				AUTO_PLAY,
				SHOW_GUIDE,
				SHOW_MOVIE,
				SHOW_TIME,
				SHOW_SCORE,
				START,
				BACK,		// 終了、タイトル、戻る
	};
	
	static final GUIBlinkButtonListener.TYPE BT_TYPE_BACK = 
		GUIBlinkButtonListener.TYPE.DEFAULT	| GUIBlinkButtonListener.TYPE.BLINK_FIX;

	static const final int volChipWidth = 19;
	
	GameInfo info;
	MouseInput m_mouse;
	bool[] optionValues;
	
	Texture m_titleTex;
	RootCounterS m_tox;	//!< タイトルテクスチャのスライドインオフセット
	
	Texture bg;
	
	TextureLoader tl;
	bool m_keyPush;
	KeyGroup m_keyGroup;
	GUIButton[] button;

	RootCounterS alpha;

	bool init;
	
	// keyConfig 用ダイアログ
	bool m_showDlg;
}
