module yamalib.draw.rring;

private import std.math;

private import y4d_draw.drawbase;
private import y4d_draw.screen;
private import y4d_draw.texture;
private import y4d_math.sintable;

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

/**
	多重構造をなす、輪の回転描画クラス
*/
class Rring {
	
	/// 表示中心位置の設定
	void setPos(int x_, int y_) {
		this.m_x = x_;
		this.m_y = y_;
	}
	
	/// 表示中心位置の取得
	void getPos(out int x_, out int y_) {
		x_ = this.m_x;
		y_ = this.m_y;
	}
	
	/// 輪の数の設定　デフォルトでは４
	void setRingNum(int n_) {
		this.m_num = n_;
	}
	
	/// 輪の数の取得
	int getRingNum() {
		return this.m_num;	
	}
	
	/// テクスチャを設定します
	/**
		描画の特性上、高さと幅が同じテクスチャでなければいけない
	*/
	void setTexture(Texture t_) {
		this.m_t = t_;	
	}

	/// 設定されているテクスチャの取得	
	Texture getTexture() {
		return this.m_t;
	}

	/// 角速度の設定	
	void setSpeed(int n) {
		this.m_rad.setStep(n);
	}
	
	/// 角速度の取得
	int getSpeed() {
		return m_rad.getStep();
	}
	
	
	/// 毎回呼び出すなり
	void onMove(Screen screen) {
		if ( m_t is null ) return;
		
		// テクスチャの幅
		int sw = cast(int) m_t.getWidth();
		int swHalf = sw / 2;
		
		// 角移動
		m_rad++;
		
		// 事前に求めておき、あとで使おう
		m_drawWidth = sin.cos(m_rad.get(), sw );
		
		// 最低限の厚みを保持させる
		if ( m_thickness >  m_drawWidth ) {
//			m_drawWidth = m_thickness;
		}
		
		int wHalf = m_drawWidth / 2;

		m_pts[0].x = m_x - wHalf;
		m_pts[0].y = m_y - swHalf;
		m_pts[1].x = m_x + wHalf;
		m_pts[1].y = m_y - swHalf;
		m_pts[2].x = m_x + wHalf;
		m_pts[2].y = m_y + swHalf;
		m_pts[3].x = m_x - wHalf;
		m_pts[3].y = m_y + swHalf;
		
	}
	
	/// 毎回呼び出すなり
	void onDraw(Screen screen) {
		if (m_t is null) return;
		
		// ローカル変数にコピーしとくと速いな
		int cx = m_x;
		int cy = m_y;
		Point[4] ptOrg = m_pts;
		Point[4] ptNxt;
		int[4] rads;
		int wHalf = m_drawWidth / 2;
		
		// 現在の対象画像の描画開始点までの距離を求める（距離はどの点でもかわらない）
		int r = cast(int) dist(m_x, m_y, ptOrg[0].x, ptOrg[0].y );
		
		// 開始オフセット角を求めておく
		for (int i = 0; i < 4; ++i) {
			rads[i] = 256 - (sin.atan( cast(int)(m_x-ptOrg[i].x), cast(int) (ptOrg[i].y-m_y) ) >> 7);
		}
		
		for (int i = 0; i < m_num; ++i) {
			
			int radadd = (255 / m_num) * i;
			int x,y;
			
			for (int j = 0; j < 4; ++j) {
				// 左上の点から順次移動計算をおこなう。
				ptNxt[j].x = cx + sin.cos( radadd + rads[j], r );
				ptNxt[j].y = cy + sin.sin( radadd + rads[j], r );
			}
			
			printPoints(ptNxt);
			
			// 描画実行
			screen.blt( m_t, null, ptNxt );
		}
		
	}
	
	/// コンストラクタ
	this() {
		m_rad = new RootCounter();
		m_rad.set(0,512,1);
		// デフォルトで４つ
		m_num = 4;
		m_thickness = 4;
	}
	
	/// 静的コンストラクタ
	static this() {
		sin = SinTable.get();
	}


private:
	/// 点のデバッグプリント
	static void printPoints(Point[4] pts) {
		foreach (int i,inout Point pt; pts) {
//			Log.print("%s: x - %s ", i, pt.x);
//			Log.print("%s: y - %s ", i, pt.y);
		}
//		Log.print("\n");
	}
	
	/// 2点間の距離を返す
    static double dist(double x1, double y1, double x2, double y2) {
        return .sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
    }

	static SinTable sin;

	RootCounter m_rad;	//!< 角度用カウンタ
	Point[4]		m_pts;	//!< 基本描画位置

	Texture m_t;	//!< テクスチャ
	int m_x;		//!< 描画中心位置
	int m_y;
	int m_thickness;	// ２Ｄ画像では厚みは存在しないので仮想厚みをユーザ設定で行う。
	
	
	int m_num;		//!< 輪っかの数
	
	int m_drawWidth;	//!< 描画するときの幅

}