module yamalib.draw.flashintext;

private import y4d;
private import y4d_aux.filesys;
private import yamalib.counterfsp;
private import yamalib.log.log;

/**
	フラッシュインテキストの基本機能と
	インターフェースを提供します
*/
abstract class FlashInObjectBase {
	/// テキスト表示速度の設定
	/// speed フレームおきに順次表示していく
	void setShowSpeed(uint speed_) {
		speed = speed_;
	}
	
	/// 表示速度の取得
	uint getShowSpeed() { return speed; }

	/// 事前に背景真っ白のテクスチャを登録しておくこと
	void setWhiteTextureBG(Texture t) {
		flash = t;
	}

	/// テキストをカバーするフラッシュ画像
	/// 文字サイズにあわない場合、拡縮される
	void setWhiteTexture(Texture t) {
		textFlash = t;
	}
	/// 画面全体をフラッシュしているか
	bool nowBGflash() { return cast(bool) (counter<=FLASH_TIME); }
	
	/// リセット
	void reset() {
		counters  = null;
		posy = null;
	}
	
	bool isFinish() {
		return finish;
	}

	/// 実装するなり
	abstract void onMove(Screen screen);
	
	/// 実装するなり
	abstract void onDraw(Screen screen);
	
	/// 静的コンストラクタ
	static this() {
		rand = new Rand();
		rand.randomize();
	}
	
protected:
	static const int FLASH_TIME = 8;
	static const int RAND_SIZE = 100;
	static const int TEXT_MOVE = -10;
	static const int TEXT_FLASH_ALPHA = 10;
	
	static Rand rand;
	bool finish;	//!< 設定された描画が完了したか
		
	RootCounterS[] counters;	//!< 文字列移動カウンタ
	int[] posy;				//!< 表示文字列のy値

	Texture flash;	//!< 真っ白のテクスチャ
	 Texture textFlash;	//!< テキスト用の白フラッシュ画像

	RootCounterS alphaBG;
	RootCounterS alpha;	//!< アルファ値
	int alphaStep = 2;

	bool pluse;

	int showCount;	//!< 表示している文字列の数

	uint counter;

	uint speedCounter;
	uint speed;		//!< 表示速度
}

/**
	文字列から生成したテクスチャで
	フラッシュインテキストを実装します
*/
class FlashInText : FlashInObjectBase {

	/// 事前に FontLoader を喰わせておくこと
	FontRepository getFontPepository() { return fr; }

	// 事前に設定しておくこと
	void addText(wchar[] str) {
		if (str)
			texts ~= str;
	}

	/// 毎回呼び出すなり
	void onMove(Screen screen) {
		if (finish) return;

		if (!init) {
			onInit();
			init = true;
		}

		counter++;

		if ( alpha.isEnd() ) {
			speedCounter--;
			if (speedCounter==0) {
				speedCounter = speed;
				counter = 0;
				alpha.set(255,0,TEXT_FLASH_ALPHA);

				if (showCount+1 == texts.length) {
					finish = true;
				} else {
					showCount++;
				}
			}
		}

		if (counter > FLASH_TIME) {
			alphaBG++;
			alpha++;

			// 文字移動
			foreach(int i, inout RootCounterS c; counters) {
				if (i==showCount+1) break;
				c++;
			}
		}
	}

	/// 毎回呼び出すなり
	override void onDraw(Screen screen) {
		int i;
		int sx = screen.getWidth();
		int sy = screen.getHeight();

		if ( (counter < FLASH_TIME) && !finish) {
			Color4ub color = screen.getColor4ub();
			screen.setColor(255, 255, 255, 255);
			screen.drawPolygon(
				0,0,
				sx,0,
				sx,sy,
				0,sy);
			screen.setColor(color);
			
//			screen.resetColor();
//			screen.blt(flash,0,0);
			return;
		} else {
			if (!alphaBG.isEnd()) {
				screen.setColor(255, 255, 255, alphaBG.get());
				screen.blt(flash,0,0);
			}
		}

		if ( (counter > FLASH_TIME) || finish) {
			screen.setColor(255, 255, 255, 255);
			for(i=0; i<=showCount; ++i) {
				tv = fr.getTexture(texts[i]);
				screen.blt(tv, counters[i].get(), posy[i] );
			}
			
			// テキストカバーフラッシュ
			if(!alpha.isEnd() && !finish) {
				int ty = cast(int) tv.getHeight();
				screen.setColor(255,255,255,alpha.get());
				screen.drawPolygon(
					0, posy[showCount],
					sx, posy[showCount],
					sx, posy[showCount] + ty,
					0, posy[showCount] + ty);
//				screen.blt(textFlash,0,posy[showCount]);
			}
		}
	}
	
	/// リセット
	override void reset() {
		super.reset();
		init = false;
	}
	
	/// 事前にテクスチャを生成
	void update() {
		onInit();
		init = true;
	}

	/// コンストラクタ
	this() {
		fr = new FontRepository;
		alpha = new RootCounterS();
		alphaBG = new RootCounterS();
		speed = 30;
		counter = 0;
	}

private:

	/// 初期化処理
	void onInit() {
		posy = null;
		counters = null;
		alpha.set(255, 0, TEXT_FLASH_ALPHA);
		alphaBG.set(0,255,12);

		speedCounter = speed;

//		fl.loadDefRW( FileSys.read("data/font.txt") );
//		fr.setLoader(fl,0);
//		fr.setMax(150);

		int textNum = texts.length;

		int offsety = 100;
		for(int i;  i <textNum; ++i) {
			posy ~= offsety;
			offsety += (280/textNum);

			// textureサイズを調べてセンタリングする
			tv = fr.getTexture(texts[i]);
			int pos = 320 - (cast(int)tv.getWidth()/2);
			Log.print("posx:%s\n",pos);
			pluse = cast(bool) !pluse;
			RootCounterS counter = new RootCounterS;
			if (pluse) {
				counter.set(pos,int.max,TEXT_MOVE);
			} else {
				counter.set(pos,int.min,TEXT_MOVE);
			}
			counters ~= counter;
		}
 	}

private:
	bool init;	//!< 初期化フラグ

	FontRepository fr;	//!< 文字貯蔵庫
	TextureVector tv;	//!< 文字列を受け取る

	wchar[][]	texts;	//!< 表示文字列
}

/**
	設定されたテクスチャより
	フラッシュインテクストを実装します
*/
class FlashInTextualText : FlashInObjectBase {
	
	/// 表示テクスチャを追加します
	void addTexture(Texture t_) {
		if (t_ != null) {
			textures ~= t_;
		}
	}
	
	/// 毎回呼び出すなり
	override void onMove(Screen screen) {
		if (finish) return;

		if (!init) {
			onInit();
			init = true;
		}

		counter++;

		if ( alpha.isEnd() ) {
			speedCounter--;
			if ( speedCounter == 0 ) {
				speedCounter = speed;
				counter = 0;
				alpha.set(255,0,TEXT_FLASH_ALPHA);

				if (showCount+1 == textures.length) {
					finish = true;
				} else {
					showCount++;
				}
			}
		}

		if (counter > FLASH_TIME) {
			alphaBG++;
			alpha++;

			// 文字移動
			foreach(int i, inout RootCounterS c;counters) {
				if ( i == showCount+1 ) break;
				c++;
			}
		}
	}
	
	/// 毎回呼び出すなり
	override void onDraw(Screen screen) {
		int i;
		int sx = screen.getWidth();
		int sy = screen.getHeight();

		if ( (counter < FLASH_TIME) && !finish) {
			Color4ub color = screen.getColor4ub();
			screen.setColor(255, 255, 255, 255);
			screen.drawPolygon(
				0,0,
				sx,0,
				sx,sy,
				0,sy);
			screen.setColor(color);
			
			return;
		} else {
			if (!alphaBG.isEnd()) {
				screen.setColor(255, 255, 255, alphaBG.get());
				screen.blt(flash,0,0);
			}
		}

		if ( (counter > FLASH_TIME) || finish) {
			screen.setColor(255, 255, 255);
			for(i = 0; i <= showCount; ++i) {
				screen.blt(textures[i], counters[i].get(), posy[i] );
			}
			
			// テキストカバーフラッシュ
			if(!alpha.isEnd() && !finish) {
				int ty = cast(int) textures[i].getHeight();
				screen.setColor(255, 255, 255, alpha.get());
				screen.drawPolygon(
					0, posy[showCount],
					sx, posy[showCount],
					sx, posy[showCount] + ty,
					0, posy[showCount] + ty);
			}
		}
	}
	
	/// リセット
	override void reset() {
		super.reset();
		init = false;
	}
	
	/// コンストラクタ
	this() {
		alpha = new RootCounterS();
		alphaBG = new RootCounterS();
		speed = 30;
		counter = 0;
	}
	
private :
	
	/// 初期化処理
	void onInit() {
		posy = null;
		counters = null;
		alpha.set(255,0,TEXT_FLASH_ALPHA);
		alphaBG.set(0,255,12);

		speedCounter = speed;

		int textNum = textures.length;

		int offsety = 100;
		for(int i; i < textNum; ++i) {
			posy ~= offsety;
			offsety += (280/textNum);

			// textureサイズを調べてセンタリングする
			texture = textures[i];
			int pos = 320 - ( cast(int) texture.getWidth() / 2 );
			Log.print("posx:%s\n",pos);
			pluse = cast(bool) !pluse;
			RootCounterS counter = new RootCounterS();
			if (pluse) {
				counter.set(pos,int.max,TEXT_MOVE);
			} else {
				counter.set(pos,int.min,TEXT_MOVE);
			}
			counters ~= counter;
		}
 	}

private:
	Texture[] textures;
	Texture texture;;
		
	bool init;	//!< 初期化したか
}