module yamalib.draw.tiletexture;

private import y4d_draw.screen;
private import y4d_draw.texture;
private import y4d_draw.sprite;
private import y4d_draw.drawbase;

private import ytl.y4d_result;

private import yamalib.log.log;

/// タイル画像用にTextureクラスをラップしたもの
class TileTexture {
	/// 行ID
	enum ROW : int {
		TOP=0,MIDDLE=3,BOTTOM=6
	};
	/// 列ID
	enum COL : int {
		LEFT=0, CENTER=1, RIGHT=2
	};
	/// タイルの繰り返しパターン
	enum TILE_TYPE : int {
		SQUARE4,	// 四角で、４パターンのもの
		SQUARE9,	// ４角で、９パターンで実装されているもの
		V_LINE3,	// 垂直タイルの一列３パターン
		H_LINE3,	// 水平タイルの一列３パターン
	}

	/// スプライト定義の読込
	void load(char[] filename) {
		if (!filename) {
			Log.printError("%s#load : filename is null!");
			return;
		}

		if ( y4d_result.no_error != m_spriteLoader.load( filename ) ) {
			Log.printError("%s#load : Sprite load Error!");
		}
		m_sprite.setSprite(m_spriteLoader.getSprite());
	}
	
	/// 行と列より当該スプライトの取得
	SimpleSprite* getSprite(ROW row, COL column) {
		m_sprite.setDirection( row +  column );
		return m_sprite.getSprite();
	}

	/// 行と列より当該スプライトの取得
	SimpleSprite* getSprite(int no) {
		m_sprite.setDirection( no );
		return m_sprite.getSprite();
	}
	
	/// このタイルを、x,yの位置に、幅sx、高さsyで描画する
	void blt(Screen screen, int x, int y, int sx, int sy) {
		switch(this.m_type) {
		case TILE_TYPE.SQUARE4:
			// todo
			assert(false);
			break;
		case TILE_TYPE.SQUARE9:
			bltSquare9(screen,x,y,sx,sy);
			break;
		case TILE_TYPE.V_LINE3:
			// todo
			assert(false);
			break;
		case TILE_TYPE.H_LINE3:
			bltHLine3(screen,x,y,sx,sy);
			break;
		default :
			assert(false);
		}
	}	
	
	/// コンストラクタ
	this(TILE_TYPE type_) {
		m_spriteLoader = new SpriteLoader();
		m_sprite = new SpriteEx();
		m_type = type_;
	}
	
private:
	/// 描画
	static void drawSprite(Screen screen, SimpleSprite* sprite, int x, int y) {
		screen.blt(sprite.texture, x, y, &sprite.rcRect);
	}

	/// 描画
	static void drawSpriteWidth(Screen screen, SimpleSprite* sprite, int x, int y, int width) {
		Rect rc = sprite.rcRect; // copy
		rc.right -= (sprite.rcRect.getWidth() - width);
		screen.blt(sprite.texture, x, y, &rc);
	}

	/// 描画
	static void drawSpriteHeight(Screen screen, SimpleSprite* sprite, int x, int y, int height) {
		Rect rc = sprite.rcRect; // copy
		rc.bottom -= (sprite.rcRect.getHeight() - height);
		screen.blt(sprite.texture, x, y, &rc);
	}

	/// 描画サイズ指定
	static void drawSprite(Screen screen, SimpleSprite* sprite, int x, int y, int width, int height) {
		Rect rc = sprite.rcRect; // copy
		rc.right -= (sprite.rcRect.getWidth() - width);
		rc.bottom -= (sprite.rcRect.getHeight() - height);
		screen.blt(sprite.texture, x, y, &rc);
	}
	
	SimpleSprite* lt() {
		return getSprite(ROW.TOP, COL.LEFT);	
	}
	SimpleSprite* ct() {
		return getSprite(ROW.TOP, COL.CENTER);	
	}
	SimpleSprite* rt() {
		return getSprite(ROW.TOP, COL.RIGHT);	
	}

	SimpleSprite* lb() {
		return getSprite(ROW.BOTTOM, COL.LEFT);	
	}
	SimpleSprite* cb() {
		return getSprite(ROW.BOTTOM, COL.CENTER);	
	}
	SimpleSprite* rb() {
		return getSprite(ROW.BOTTOM, COL.RIGHT);	
	}
	
	SimpleSprite* cl() {
		return getSprite(ROW.MIDDLE, COL.LEFT);
	}
	
	SimpleSprite* cr() {
		return getSprite(ROW.MIDDLE, COL.RIGHT);
	}
	
	SimpleSprite* base() {
		return getSprite(ROW.MIDDLE, COL.CENTER);
	}
	
	/// 四角９パターン描画
	void bltSquare9(Screen screen, int x, int y, int sx, int sy) {
		int ltWidth = cast(int) this.lt.rcRect.getWidth();
		int ltHeight = cast(int) this.lt.rcRect.getHeight();
		
		int lbWidth = cast(int) this.lb.rcRect.getWidth();
		int lbHeight = cast(int) this.lb.rcRect.getHeight();
		
		int rtWidth = cast(int) this.rt.rcRect.getWidth();
		
		int crWidth = cast(int) this.cr.rcRect.getWidth();
		int crHeight = cast(int) this.cr.rcRect.getHeight();
		
		int baseWidth = cast(int) this.base.rcRect.getWidth();
		int baseHeight = cast(int) this.base.rcRect.getHeight();
		
		int ctWidth = cast(int) this.ct.rcRect.getWidth();
		int ctHeight = cast(int) this.ct.rcRect.getHeight();
		
		int rbWidth = cast(int) this.rb.rcRect.getWidth();
		int rbHeight = cast(int) this.rb.rcRect.getHeight();
		
		int clHeight = cast(int) this.cl.rcRect.getHeight();
		int leftx =  (x + sx) - rtWidth;
		
		int cbWidth = cast(int) this.cb.rcRect.getWidth();
		
		// トップ描画
		drawSprite(screen, this.lt, x, y);
		// 中央繰り返し
		for (int i = ltWidth; i < sx - rtWidth; i += ctWidth) {
			if ( i + ctWidth > (sx - rtWidth) ) {
				drawSpriteWidth(screen, this.ct, x + i, y, (sx - rtWidth) - i);
			} else {
				drawSprite(screen, this.ct, x + i, y);
			}
		}
		// 右上
		drawSprite(screen, this.rt, leftx, y);
		
		// 内部描画
		for (int i = ltHeight; i < sy - lbHeight; i += baseHeight) {
			for (int j = ltWidth; j < sx - crWidth; j += baseWidth) {
				int width = (sx - crWidth) - j;
				int height = (sy - lbHeight) - i;
				
				if ( width > baseWidth ) {
					width = baseWidth;
				} 
				
				if ( height > baseHeight ) {
					height = baseHeight;
				}
				 
				drawSprite(screen, this.base, x + j, i + y, width, height);
			}
		}
		
		// 左枠
		for (int i = ltHeight; i < sy - lbHeight; i += clHeight) {
			if ( i + clHeight > (sy - lbHeight)) {
				drawSpriteHeight(screen, this.cl, x, i + y, (sy - lbHeight) - i);
			} else {
				drawSprite(screen, this.cl, x, i + y);
			}
		}
		
		// 右枠
		leftx = (x + sx) - crWidth;
		for (int i = ltHeight; i < sy- rbHeight; i += clHeight) {
			if ( i + crHeight > (sy - rbHeight)) {
				drawSpriteHeight(screen, this.cr, leftx, i + y, (sy - rbHeight) - i);
			} else {
				drawSprite(screen, this.cr, leftx, i + y);
			}
		}
		
		// 下枠
		int bottomy = (sy - lbHeight) + y;
		drawSprite(screen, this.lb, x, bottomy);
		// 中央繰り返し
		for (int i = lbWidth; i < sx - rbWidth; i += cbWidth) {
			if ( i + cbWidth > (sx - rbWidth) ) {
				drawSpriteWidth(screen, this.cb, x + i, bottomy, (sx - rbWidth) - i);
			} else {
				drawSprite(screen, this.cb, x + i, bottomy );
			}
		}
		// 右下
		leftx = (x + sx) - rbWidth;
		bottomy =  (y + sy) - rbHeight;
		drawSprite(screen, this.rb, leftx, bottomy);
	}
	
	/// 一行３パターンタイルの描画
	void bltHLine3(Screen screen, int x, int y, int sx, int sy) {
		int lWidth = cast(int) getSprite(0).rcRect.getWidth();
		int cWidth = cast(int) getSprite(1).rcRect.getWidth();
		int rWidth = cast(int) getSprite(2).rcRect.getWidth();
		
		// 左
		screen.blt(getSprite(0).texture, x, y, &(getSprite(0).rcRect) );

		// 中央
		int ox;
		for (ox = lWidth; ox < sx - rWidth - cWidth; ox += cWidth) {
			screen.blt(getSprite(1).texture, x + ox, y, &(getSprite(1).rcRect));
		}
		// 中央余り
		Rect rc = getSprite(1).rcRect; // copy
		rc.right = rc.left + ((sx - rWidth) - ox);
		screen.blt(getSprite(1).texture, x + ox, y, &rc);
		
		// 右
		screen.blt(getSprite(2).texture, x + sx - rWidth, y, &(getSprite(2).rcRect));
	}
	

private:
	TILE_TYPE m_type;
	SpriteLoader m_spriteLoader;
	SpriteEx	m_sprite;
}