module yamalib.draw.moveview;

private import y4d;
private import yamalib.counterfsp;

abstract class MoveViewBase {

public:
	/// 静的コンストラクタ
	static this() {
		st = SinTable.get();
		rand = new Rand;
		rand.randomize();
	}

	/// コンストラクタ
	this() {
		timer = new FixTimer;
	}

    /// 画像をロードしてくるtextureloader
	void setTextureLoader(TextureLoader tl) {
		this.tl = tl;
		t = tl.get( getNextRand() );
	}
	
	/// 毎回呼び出すなり
	void onMove(Screen screen) {
	}

    /// 毎回呼び出すナリ
	abstract void onDraw(Screen screen) {
	}

protected:
	
	/// テクスチャローダに設定されているファイルから次の適当なテクスチャ番号を取得します
	int getNextRand() {
		return rand.get( tl.getInfoList().size()-1 );
	}


	static Rand rand;
	static SinTable st;

	FixTimer timer;		//!< タイミングを計るタイマ
	TextureLoader tl;	//!< 画像をロードしてくる
	Texture t;			//!< ごにょごにょするテクスチャ
	int movecounter;	//!< フレームをカウントする
	int posx;
	int posy;
	float rate;		//!< 拡大レート
	Rect textrue_rc;
}

/// 背景ブレ描画クラス:手ぶれを再現する
class MoveView : MoveViewBase {
	this() {
		timer = new FixTimer;
		posx = 320;
		posy = 240;
		rad = 0;
		rad_speed = 36;
	}

    /// 毎回呼び出すナリ
	override void onDraw(Screen screen) {
		if(tl == null) {
			return;
		}

		rad += rad_speed;
		if (rad > 512) {
			rad = 0;
		}

		if (radiate) {

			posx += radiate_x;
			posy += radiate_y;

			float sx = t.getWidth()*rate;
			float sy = t.getHeight()*rate;

			// 画像の矩形を求めていずれかの点が画面内にあれば終了
			Rect rc;
			textrue_rc.left = posx - sx / 2;
			textrue_rc.right = posx + sx / 2;
			textrue_rc.top = posy - sy / 2;
			textrue_rc.bottom = posy + sy / 2;

			if (textrue_rc.left>0 || textrue_rc.top>0 || textrue_rc.right<640 || textrue_rc.bottom<480) {
				radiate = false;
				movecounter = 0;
				posx = 320;
				posy = 240;
				rate = 1.5;
				rad = 0;
				radiate_x = 0;
				radiate_x = 0;

				int no = rand.get(tl.getInfoList().size());
				t = tl.get( no );
			}
		}
		movecounter++;

		posx += st.sin(rad,amplitude);
		if (rand_x != 0) {
			posx += rand.get(rand_x) - rand_x/2;	// ランダムのブレをいれる
		}
		posy += rand.get(60)-30;
		rate += 0.03;

		screen.setColor(255,255,255,128);
		screen.bltRotate(t,posx,posy,0,rate,4);

		// 画面を放散させて次の画面に
		if( movecounter == 175 ) {
			radiate = true;
			radiate_x = rand.get(50)+15;
			radiate_y = rand.get(50)+10;

			if (rand.get(2)) radiate_x = -radiate_x;
			if (rand.get(2)) radiate_y = -radiate_y;
		}

	}

	/// 振幅
	void setAmplitude(int n) { amplitude = n; }

	/// ランダム幅の設定
	void setRandX(int n) { rand_x = n; }

	/// 角速度の設定
	void setAngleSpeed(int n) { rad_speed = n; }

private:
	int rad;			//!< 角度
	int rad_speed;		//!< 角速度
	int posx;
	int posy;
	float rate;		//!< 拡大レート
	int rand_x;		//!< 移動量に対するさらなるランダム幅
	int amplitude;

	bool radiate = false;
	int radiate_x;
	int radiate_y;
}

/**
	指定画像をスムースに移動させます
*/
class MoveViewSmooth : MoveViewBase {
	
	char[] toString() {
		return null;
	}

	/// コンストラクタ
	this() {
		super();
		moveX = 0.0f;
		moveY = 0.0f;
		sumMoveX = 0.0f;
		sumMoveY = 0.0f;
		rate = 1.5;		// 拡大率	

		posx = 320; // 描画の中心点
		posy = 240;
		
		alphaCounter = new RootCounterS();
		alphaCounter.set(0, LC_ALPHA_MAX, LC_FADE_STAP);
		
	}
	
	/// 移動速度を設定します
	void setMoveXY(float dx_, float dy_) {
		moveX = dx_;
		moveY = dy_;
	}
	
	void getMoveXY(out float dx_, out float dy_) {
		dx_ = moveX;
		dy_ = moveY;
	}
	
	/// 次のテクスチャに変更する
	void nextTexture() {
//		t = tl.get( getNextRand() );
		alphaCounter.set(LC_ALPHA_MAX, 0, LC_FADE_STAP);
		stateOut = true;
	}
	
	/// 毎回呼び出すなり
	override void onMove(Screen screen) {
		if (tl == null) return;
		
		// アルファカウンタ
		alphaCounter++;
		
		if ( stateOut && alphaCounter.isEnd() ) {
			stateOut = false;
			sumMoveX = 0.0f;
			sumMoveY = 0.0f;
			if ( rand.get(2) ) {
				moveX *= -1.0f;
			} 
			if (rand.get(2) ) {
				moveY *= -1.0f;
			}
			
			t = tl.get( getNextRand() );
			alphaCounter.set(0, LC_ALPHA_MAX, LC_FADE_STAP);
		}
		
		++movecounter;
		
		sumMoveX += moveX;
		sumMoveY += moveY;
	}
	
	/// 毎回呼び出すなり
	override void onDraw(Screen screen) {
		if (t == null) return;
		
		Color4ub colorOrg = screen.getColor4ub();
		screen.setColor(255, 255, 255, alphaCounter.get() );
		screen.bltRotate(t,posx + cast(int) sumMoveX, posy + cast(int) sumMoveY, 0, rate, 4);
		
		screen.setColor( colorOrg );
	}
	
private:
	static const int LC_FADE_STAP = 1;
	static const int LC_ALPHA_MAX = 96;

	float moveX;	// 移動量
	float moveY;	// 移動量
	float sumMoveX;	// 移動量加算
	float sumMoveY;	// 移動量加算
	
	RootCounterS alphaCounter;

	bool stateOut;	// フェードアウト中か？
	bool fadeInOut;
}
