module yamalib.draw.shellemulatordraw;

private import std.ctype;

private import y4d_aux.filesys;
private import y4d_aux.widestring;
private import y4d_aux.lineparser;
private import y4d_draw.screen;
private import y4d_draw.scenariodraw;
private import y4d_draw.fontrepository;
private import y4d_timer.timer;

private import yamalib.draw.textdraw;

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

/**
 	飾り用のクラス
 	専用フォーマットによって定義されたシェル動作を画面上に表示します
*/
class ShellEmulatorDraw {
	
	/// 毎回呼び出すなりー
	void onMove(Screen screen) {
		assert( !(infos is null) );
		
		if (drawEnd) return;
		
		analyzeTag();
		
		if (readwait == -1) {
			infos[curInfoIndex].textCount++;
		} else {
			if ( readWaitTimer.get() >= readwait ) {
				readwait = -1;
			}
		}
		
	}
	
	/// 毎回できるだけよびだすなりー
	void onDraw(Screen screen) {
		assert( !(infos is null) );
		
		if (drawEnd) return;
		
		with( infos[curInfoIndex] ) {

			int tx, ty;
			// 描画する矩形情報
			ScenarioTextDraw.DrawChar[] drawchar = sd.getDrawChar();
			
			for(int i = 0; i < textCount.get() && i < drawchar.length; ++i) {
				float size = drawchar[i].size; 
				
				// 影の描画
				screen.setColor(0,0,0);
				tx = ox + cast(int) drawchar[i].pos.x + 2;
				ty = oy + cast(int) drawchar[i].pos.y + 1;
				
				// 拡大ありで描画
				if (1.0f != size) {
					screen.bltRotate(
						drawchar[i].texture,	// テクスチャ 
						tx, ty, 	// x,y 位置
						0, 			// 回転角
						size, 		// 拡大率
						0			// 描画ベース位置（左上）
						);
				} else {
					screen.blt(drawchar[i].texture, tx, ty);
				}
	
				// 本文字の描画
				screen.setColor( drawchar[i].color );
				tx = ox + cast(int) drawchar[i].pos.x;
				ty = oy + cast(int) drawchar[i].pos.y;
				
				// 拡大ありで描画
				if (1.0f != size) {
					screen.bltRotate(
						drawchar[i].texture,	// テクスチャ 
						tx, ty, 	// x,y 位置
						0, 			// 回転角
						size, 		// 拡大率
						0			// 描画ベース位置（左上）
						);
				} else {
					screen.blt(drawchar[i].texture, tx, ty);
				}
			}
			
			carsor.setXY(tx+8, ty+3);
			carsor.onDraw(screen);
			
			if (oy + ty > 450) {
				oy -= 15;
			}
			
			
			if ( textCount.isEnd() ) {
				if ( curInfoIndex > 0 ) {
					curInfoIndex--;
				} else {
					drawEnd = true;
				}
			}

			screen.resetColor();
		} // with
		
	}
	
	/// 表示する画面情報スクリプトファイルを設定する
	void setCommands(char[][] filenames_, FontLoader fl) {

		// 一応前の情報を消去する
		infos = null;

		foreach (char[] filename; filenames_) {
			
			ShellDrawInfo info = new ShellDrawInfo();
			FontRepository fr = info.sd.getFontRepository();
			fr.setLoader(fl, 1);
			// ほとんど英数字だからこんくらいあれば...
			fr.setMax(64);
			
			TextDrawContext textdrawcontext = new TextDrawContext();
			char[] strText = cast(char[]) FileSys.read( filename );

			textdrawcontext.setText( toWCS(strText) );
			info.sd.setTextDrawContext( textdrawcontext );
			info.sd.updateText();
			ScenarioTextDraw.DrawChar[] drawchar = info.sd.getDrawChar();
			info.textCount.set(0, drawchar.length, TYPE_SPEED);
			info.ox = 40;
			
			infos ~= info;
		}
	}
	
	/// 全描画が終了したか
	bool isEnd() {
		return drawEnd;
	}
	
	/// コンストラクタ
	this() {
		readWaitTimer = new Timer();
		carsor = new PromptCarsor();
		Texture carsortexture = new Texture();
		carsortexture.load( FileSys.makeFullName("img/ending/carsor.png") );
		carsor.setTexture( carsortexture );
		readwait = -1;
	}
	
private:

	/// タグの解析を行います
	void analyzeTag() {

		//	どのタグに該当するかを調べる
		static char[][] tags = [
			"readstop",	 	// 0 .読み止まり
			"nowait",		// 1 .読み飛ばしSTART
			"/nowait",		// 2 .読み飛ばしEND
			"push"			// 3 .次のプロンプト画面へ
		];
		
		LineParser lineparser = new LineParser();
		
		with( infos[curInfoIndex] ) {

			ScenarioTextDraw.UnknownTagInfo[] tag = sd.getUnknownTagInfo();
			
			while (analyzedTag < tag.length && tag[analyzedTag].pos <= textCount.get() ) {
			
				char[] strTag = toMBS( tag[analyzedTag].tag );
				lineparser.setLine(strTag);
				char[] cc = lineparser.getStr();
				char[] strErorr;
		
				// タグは小文字化して探査しよう
				foreach (inout char c; cc) {
					c = std.ctype.tolower(c);
				}
		
				int found = -1; // not found marker
				for(int i = 0; i < tags.length; ++i){
					if ( cc == tags[i]) {
						found = i;
						Log.print("SED tag %s", tags[found]);
						break;
					}
				}
		
				//	このタグの処理
				switch(found) {
				case 0:		// readstop
					if ( !lineparser.isEnd() ) {
						readwait = cast(int) lineparser.getNum(-1);
						readWaitTimer.reset();
					}
					break;
		
				case 1:		// nowait
					textCount.opAssign( tag[analyzedTag+1].pos );
					break;
		
				case 2:		// nowaitend
					break;
					
				case 3:		// push
					curInfoIndex++;
					break;
					
				default:
					break;
				}
				
				analyzedTag++;

			}	// while
		
		} // with
		
	}

	static final const int TYPE_SPEED = 1;	// タイピングスピード

	/// シェル画面情報
	class ShellDrawInfo {
		ScenarioTextDraw sd;
		RootCounterS textCount;
		int ox; 	// 描画位置オフセット
		int oy;
		int analyzedTag;
		
		/// コンストラクタ
		this() {
			sd = new ScenarioTextDraw();
			textCount = new RootCounterS();
		}
	}

	PromptCarsor carsor;
	ShellDrawInfo[] infos;
	int curInfoIndex;	// 現在表示中のScenarioDrawインデックス
	Timer readWaitTimer;
	int readwait;
	bool drawEnd;
	
	
	
}