module yamalib.draw.effectsoft;

private import SDL;
private import y4d;

private import yamalib.log.log;


/// ぼかしエフェクトクラス
/**
　対象座標の近辺との色データの平均値をとるとぼかしなのだ
*/
class EffectSoft {
	
	/// ぼかし処理実行
	/**
		サーフェイスを段階的にぼかすには、画像をロードしたサーフェイスを
		渡す。
		それを任意のスケールで連続して行う。
		テクスチャにする場合は、テクスチャ置換メソッドを呼ぶ必要があるので、
		適当な画像をロードしてから、置換すればよい。
	*/
	static Surface excecute(Surface surface, int scale) {
		
		assert ( !(surface is null) );

		try {
			// サーフェイスの防御的コピー
	//		Surface surface = TextureKGA.copySurface( surface_ );
	
			int width = cast(int) surface.getWidth();
			int height = cast(int) surface.getHeight();
			
			if ( surface.checkRGB888() ) {
	
				// アルファ無効 24bitデータ
				Color24* pixels = cast(Color24*) surface.getPixels();
				for (int y; y < height; ++y) {
					for (int x; x < width; ++x) {
						
						// yだけでやってみっかー
						uint r,g,b,count;
						for ( int i = 1; i < scale; ++i ) {
							
							if ( y - i >= 0 ) {
								r += pixels[ ( (y-i) * width) + x  ].r;
								g += pixels[ ( (y-i) * width) + x  ].g;
								b += pixels[ ( (y-i) * width) + x  ].b;
								count++;
							}
							
							if ( y + i < height ) {
								r += pixels[ ( (y+i) * width) + x  ].r;
								g += pixels[ ( (y+i) * width) + x  ].g;
								b += pixels[ ( (y+i) * width) + x  ].b;
								count++;
							}
						}
						
						if (count != 0) {
							r /= count;
							g /= count;
							b /= count;
							
							pixels[(y * width) + x].r = cast(ubyte) r;
							pixels[(y * width) + x].g = cast(ubyte) g;
							pixels[(y * width) + x].b = cast(ubyte) b;
						}
									
					}
				}
			} else {
				
				// アルファ有効32bitデータ
				SDL_Color* pixels = cast(SDL_Color*) surface.getPixels();
				
				for (int y; y < height; ++y) {
					for (int x; x < width; ++x) {
						
						// yだけでやってみっかー
						uint r,g,b,a,count;
						for ( int i = 1; i < scale; ++i ) {
							int idx;
							if ( y - i >= 0 ) {
								idx = ( (y-i) * width) + x;
								r += pixels[ idx ].r;
								g += pixels[ idx ].g;
								b += pixels[ idx ].b;
								a += pixels[ idx ].unused;
								count++;
							}
							
							if ( y + i < height ) {
								idx = ( (y+i) * width) + x;
								r += pixels[ idx ].r;
								g += pixels[ idx ].g;
								b += pixels[ idx ].b;
								a += pixels[ idx ].unused;
								count++;
							}
							
							if (x - i >= 0) { 
								idx = y * width + (x-i);
								r += pixels[ idx ].r;
								g += pixels[ idx ].g;
								b += pixels[ idx ].b;
								a += pixels[ idx ].unused;
								count++;
							}

							if (x + i < width) { 
								idx = y * width + (x+i);
								r += pixels[ idx ].r;
								g += pixels[ idx ].g;
								b += pixels[ idx ].b;
								a += pixels[ idx ].unused;
								count++;
							}
						}
						
						if (count != 0) {
							r /= count;
							g /= count;
							b /= count;
							a /= count;
							int idx = (y * width) + x;
							pixels[ idx ].r = cast(ubyte) r;
							pixels[ idx ].g = cast(ubyte) g;
							pixels[ idx ].b = cast(ubyte) b;
							pixels[ idx ].unused = cast(ubyte) a;
						}
									
					}
				}
			}
		} catch (Exception e) {
			Log.printFatal("Exception EffectSoft#excecute : [%s]", e.toString());
		}
				
		return surface;
	}
	
	static Surface negaPosi(Surface surface) {
		
		assert ( !(surface is null) );

		try {
			int width = cast(int) surface.getWidth();
			int height = cast(int) surface.getHeight();
			
			Surface newSurface = copySurface(surface);
			int py;
			int indexXY;
			if ( surface.checkRGB888() ) {
	
				SDL_Color* pixels = cast(SDL_Color*) newSurface.getPixels();
				SDL_Color* srcPix = cast(SDL_Color*) surface.getPixels();
				
				for (int y; y < height; ++y) {
					py = width * y;
					for (int x; x < width; ++x) {
						indexXY = py + x;
						pixels[indexXY].r = 255 - srcPix[indexXY].r;
						pixels[indexXY].g = 255 - srcPix[indexXY].g;
						pixels[indexXY].b = 255 - srcPix[indexXY].b;
						pixels[indexXY].unused = srcPix[indexXY].unused;
					}
				}
			} else {
				
				Color24* srcPix = cast(Color24*) surface.getPixels();
				Color24* pixels = cast(Color24*) newSurface.getPixels();
	
				for (int y; y < height; ++y) {
					py = width * y;
					for (int x; x < width; ++x) {
						indexXY = py + x;
						pixels[indexXY].r = 255 - srcPix[indexXY].r;
						pixels[indexXY].g = 255 - srcPix[indexXY].g;
						pixels[indexXY].b = 255 - srcPix[indexXY].b;
					}
				}
			}
		} catch (Exception e) {
			Log.printFatal("Exception EffectSoft#excecute : [%s]", e.toString());
		}
				
		return surface;
	}
	
		/// サーフェイスをコピーする
	static Surface copySurface(Surface surface_) {
		
		int width = cast(int) surface_.getWidth();
		int height = cast(int) surface_.getHeight();
		bool alpha = cast(bool) (surface_.getSurface().format.BitsPerPixel==32);

		// createDIBして転送したほうがはやいんでないかな...
		Surface surface = new Surface();
		surface.createDIB( width, height, alpha );

		surface.blt( surface_, 0, 0 );
		return surface;
	}
	

}