module yamalib.draw.sequencedraw;

private import std.stream;

private import y4d_draw.drawbase;
private import y4d_draw.screen;
private import y4d_draw.texture;
private import y4d_aux.filesys;
private import y4d_aux.lineparser;

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


class SequenceDraw {
	
	enum DIRECTION : int {LEFT,TOP,RIGHT,BOTTOM};
	
	/// 描画終了したか
	bool isFinish() {
		return cast(bool) (nowIndex >= drawInfos.length); 
	}
	
	/// 描画位置の設定
	void setPos(int x_, int y_) {
		this.posx = x_;
		this.posy = y_;
	}
	
	/// 描画位置の取得
	void getPos(out int x_, out int y_) {
		x_ = this.posx;
		y_ = this.posy;
	}

	/// 設定ファイルの読み込み
	void loadDefFile(char[] filename) {
		drawInfos = null;
		ubyte[] mem = cast(ubyte[]) FileSys.read(filename);
		if (!mem) return; // 読み込みエラー
		
		std.stream.MemoryStream m = new std.stream.MemoryStream(mem);
		LineParser lp = new LineParser;
		while (!m.eof) {
			char[] linebuf = cast(char[]) m.readLine();
			lp.setLine(linebuf);
			char[] imgname = lp.getStr();
			if (!imgname) continue; // ダメやん

			DrawInfo info;
			Texture t = new Texture();
			t.load(imgname);
			info.t = t;

			// 方向
			int dire = cast(int) lp.getNum(0);
			// 開始位置
			int poss = cast(int) lp.getNum(0);
			// 終了位置
			int pose = cast(int) lp.getNum( cast(int) t.getWidth() );
			// ステップ
			int step = cast(int) lp.getNum(1);
			
			info.direct = dire;
			info.posS = cast(int) (poss * rate);
			info.posE = cast(int) (pose * rate);
			info.speed = step;
			
			drawInfos ~= info;
		}
		
		// 初期化
		nowIndex = 0;
		sizeCounter.set(drawInfos[0].posS, drawInfos[0].posE, drawInfos[0].speed);
		
		Log.print("Load Def File : SIZE = %s", drawInfos.length);
	}

	/// 毎回呼び出すなり
	void onMove(Screen screen) {
		if ( 0 == drawInfos.length || isFinish() ) return;
		
		sizeCounter++;
		
		if ( !isFinish() && sizeCounter.isEnd() ) {
			++nowIndex;
			
			// log...
			Log.print("Finish..%s", nowIndex);
			
			if ( !isFinish() ) {
				int start,end;
				
				switch ( drawInfos[nowIndex].direct ) {
				case DIRECTION.LEFT:
					start = drawInfos[nowIndex].posS;
					end = drawInfos[nowIndex].posE;
					break;
				case DIRECTION.TOP:
					start = drawInfos[nowIndex].posS;
					end = drawInfos[nowIndex].posE;
					break;
				case DIRECTION.RIGHT:
					start = drawInfos[nowIndex].posS;
					end = drawInfos[nowIndex].posE;
					break;
				case DIRECTION.BOTTOM:
					start = drawInfos[nowIndex].posS;
					end = drawInfos[nowIndex].posE;
					break;
				default:
					break;
				}
				// 次のカウンター設定
				sizeCounter.set(start,end,drawInfos[nowIndex].speed);
			} else {
				// 終端に達した！
				return;
			}
				
		}
		
		setDrawRect(drawInfos[nowIndex]);
	}
	
	/// 毎回呼び出すなり
	void onDraw(Screen screen) {
		if ( 0 == drawInfos.length ) return; 

		// 描画済み
		for (int i = 0; i < nowIndex; ++i) {
			screen.bltRotate(drawInfos[i].t, posx, posy, 0, rate, 0);
		}
		
		if ( !isFinish() ) {
			// 書きかけ描画
			int offsetx = 0;
			int offsety = 0;
			
			// 右から
			if (DIRECTION.RIGHT == drawInfos[nowIndex].direct) {
				offsetx = cast(int) ((drawInfos[nowIndex].t.getWidth() - this.drawRc.getWidth()) * rate);
			} else if (DIRECTION.BOTTOM == drawInfos[nowIndex].direct) {
				// 下から
				offsety = cast(int) ((drawInfos[nowIndex].t.getHeight() - this.drawRc.getHeight()) * rate);
			}
			
			screen.bltRotate(drawInfos[nowIndex].t, posx + offsetx, posy + offsety, &this.drawRc, 0, rate, 0, 0);
		}
	}
	
	/// コンストラクタ
	this() {
		sizeCounter = new RootCounterS();
	}
	
private:

	/// 現在の情報より描画矩形を設定する
	void setDrawRect(DrawInfo di) {
		int tw = cast(int) (di.t.getWidth());
		int th = cast(int) (di.t.getHeight());

		switch ( di.direct ) {
		case DIRECTION.LEFT:
			drawRc.setRect(0, 0, sizeCounter.get(), th);
			break;
		case DIRECTION.TOP:
			drawRc.setRect(0, 0, tw, sizeCounter.get());
			break;
		case DIRECTION.RIGHT:
			drawRc.setRect(sizeCounter.get(), 0, tw, th);
			break;
		case DIRECTION.BOTTOM:
			drawRc.setRect(0, sizeCounter.get(), tw, th);
			break;
		default:
			break;
		}
	}

	struct DrawInfo {
		Texture t;
		int direct;
		int posS;
		int posE;
		int speed;
	}
	
	DrawInfo[] drawInfos;
	RootCounterS sizeCounter;
	int nowIndex;
	Rect drawRc;
	
	int posx;
	int posy;
	float rate = 1.0f;


}