#include "surfaces.hpp"

SDL_Surface* load_image( std::string filename ){

	SDL_Surface* temp = NULL;
	SDL_Surface* rpic = NULL;

	temp = IMG_Load( filename.c_str() );

	if( temp ){

		rpic = SDL_DisplayFormat( temp );
		SDL_FreeSurface( temp );

	}

	SDL_SetColorKey( rpic, SDL_SRCCOLORKEY, SDL_MapRGB( rpic->format, 0, 0xFF, 0xFF ) );

	return rpic;
}

void apply_surface( int x, int y, SDL_Surface* src, SDL_Surface* dest, SDL_Rect* clip ){

	SDL_Rect offset;
	offset.x = x;
	offset.y = y;

	SDL_BlitSurface( src, clip, dest, &offset );

}

Uint32 get_pixel32( SDL_Surface* surface, int x, int y ){

	Uint32* pixels = (Uint32*)surface->pixels;

	return pixels[ ( surface->w * y ) + x ];

}

void put_pixel32( SDL_Surface* surface, int x, int y, Uint32 pixel ){

	Uint32* pixels = (Uint32*)surface->pixels;

	pixels[ ( surface->w * y ) + x ] = pixel;

}

SDL_Surface* flip_surface( SDL_Surface* surface, int flags ){

	SDL_Surface* flipped = NULL;

	flipped = SDL_CreateRGBSurface( surface->flags, surface->w, surface->h, surface->format->BitsPerPixel,
						            surface->format->Rmask, surface->format->Gmask, surface->format->Bmask,
			                        surface->flags & SDL_SRCCOLORKEY ? 0 : surface->format->Amask );

	if( SDL_MUSTLOCK( surface ) ){
		SDL_LockSurface( surface );
	}

	for( int x = 0; x < flipped->w; x++ )
		for( int y = 0; y < flipped->h; y++ ){

			Uint32 pixel = get_pixel32( surface, x, y );

			if( ( flags & FLIP_HORIZONTAL ) && ( flags & FLIP_VERTICAL ) ){

				put_pixel32( flipped, ( flipped->w - x - 1 ), ( flipped->h - y - 1 ), pixel );

			}
			else if( flags & FLIP_HORIZONTAL ){

				put_pixel32( flipped, ( flipped->w - x - 1 ), y, pixel );

			}
			else if( flags & FLIP_VERTICAL ){

				put_pixel32( flipped, x, ( flipped->h - y - 1 ), pixel );

			}
		}

	if( SDL_MUSTLOCK( surface ) ){
		SDL_UnlockSurface( surface );
	}

	if( surface->flags & SDL_SRCCOLORKEY ){
		SDL_SetColorKey( flipped, SDL_RLEACCEL | SDL_SRCCOLORKEY, surface->format->colorkey );
	}

	return flipped;
}

void flip_surface_self( SDL_Surface* &surface, int flags ){

	SDL_Surface* temp = surface;

	surface = flip_surface( temp, flags );

	SDL_FreeSurface( temp );

}

SDL_Surface* rotate_surface90( SDL_Surface* surface, int flags ){

	SDL_Surface* rotated = NULL;

	rotated = SDL_CreateRGBSurface( surface->flags, surface->h, surface->w, surface->format->BitsPerPixel,
			                        surface->format->Rmask, surface->format->Gmask, surface->format->Bmask,
			                        surface->flags & SDL_SRCCOLORKEY ? 0 : surface->format->Amask );

	if( SDL_MUSTLOCK( surface ) )
		SDL_LockSurface( surface );

	for( int x = 0; x < surface->w; x++ )
		for( int y = 0; y < surface->h; y++ ){

			Uint32 pixel = get_pixel32( surface, x, y );

			if( flags & ROTATE_RIGHT ){

				put_pixel32( rotated, ( rotated->w - y - 1 ), x, pixel );

			}
			if( flags & ROTATE_LEFT ){

				put_pixel32( rotated, y, ( rotated->h - x - 1 ), pixel );

			}

		}


	if( SDL_MUSTLOCK( surface ) )
		SDL_UnlockSurface( surface );

	if( surface->flags & SDL_SRCCOLORKEY )
		SDL_SetColorKey( rotated, SDL_RLEACCEL | SDL_SRCCOLORKEY, surface->format->colorkey );

	return rotated;

}

void rotate_surface90_self( SDL_Surface* &surface, int flags ){

	SDL_Surface* temp = surface;

	surface = rotate_surface90( temp, flags );

	SDL_FreeSurface( temp );

}

SDL_Surface* rotate_surface180( SDL_Surface* surface ){

	SDL_Surface* rotated;

	rotated = SDL_CreateRGBSurface( surface->flags, surface->w, surface->h,
			                        surface->format->BitsPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask,
			                        surface->flags & SDL_SRCCOLORKEY ? 0 : surface->format->Amask );

	if( SDL_MUSTLOCK( surface ) )
		SDL_LockSurface( surface );

	for( int x = 0; x < rotated->w; x++ )
		for( int y = 0; y < rotated->h; y++ ){

			Uint32 pixel = get_pixel32( surface, x, y );

			put_pixel32( rotated, ( rotated->w - x - 1 ), ( rotated->h - y - 1 ), pixel );

		}


	if( SDL_MUSTLOCK( surface ) )
		SDL_UnlockSurface( surface );

	if( surface->flags & SDL_SRCCOLORKEY )
		SDL_SetColorKey( rotated, SDL_RLEACCEL | SDL_SRCCOLORKEY, surface->format->colorkey );

	return rotated;

}

void rotate_surface180_self( SDL_Surface* &surface ){

	SDL_Surface* temp = surface;

	surface = rotate_surface180( temp );

	SDL_FreeSurface( temp );

}

SDL_Surface* resize_surface( SDL_Surface* surface, int xp, int yp ){

	SDL_Surface* resized = NULL;

	resized = SDL_CreateRGBSurface( surface->flags, xp, yp, surface->format->BitsPerPixel,
									surface->format->Rmask, surface->format->Gmask, surface->format->Bmask,
									surface->flags & SDL_SRCCOLORKEY ? 0 : surface->format->Amask );

	if( SDL_MUSTLOCK( surface ) )
		SDL_LockSurface( surface );


	for( int x = 0; x < resized->w; x++ )
		for( int y = 0; y < resized->h; y++ ){

			Uint32 pixel = get_pixel32( surface, (int)( x / (float)( (float)resized->w / (float)surface->w ) ),
					                             (int)( y / (float)( (float)resized->h / (float)surface->h ) ));

			put_pixel32( resized, x, y, pixel );

		}

	if( SDL_MUSTLOCK( surface ) )
		SDL_UnlockSurface( surface );

	if( surface->flags & SDL_SRCCOLORKEY )
		SDL_SetColorKey( resized, SDL_RLEACCEL | SDL_SRCCOLORKEY, surface->format->colorkey );

	return resized;

}

void resize_surface_self( SDL_Surface* &surface, int xp, int yp ){

	SDL_Surface* temp = surface;

	surface = resize_surface( temp, xp, yp );

	SDL_FreeSurface( temp );
}

SDL_Surface* resize_surface( SDL_Surface* surface, int degree ){

	return resize_surface( surface, (int)( surface->w * (float)( (float)degree / (float)100 ) ),
									(int)( surface->h * (float)( (float)degree / (float)100 ) ) );

}

void resize_surface_self( SDL_Surface* &surface, int degree ){

	SDL_Surface* temp = surface;

	surface = resize_surface( temp, degree );

	SDL_FreeSurface( temp );

}

SDL_Surface* smooth_surface( SDL_Surface* surface, int level ){

	SDL_Surface* smoothed = NULL;

	smoothed = SDL_CreateRGBSurface( surface->flags, surface->w, surface->h, surface->format->BitsPerPixel,
									 surface->format->Rmask, surface->format->Gmask, surface->format->Bmask,
									 surface->flags & SDL_SRCCOLORKEY ? 0 : surface->format->Amask );

	if( SDL_MUSTLOCK( surface ) )
		SDL_LockSurface( surface );

	for( int x = 0; x < smoothed->w; x++ ){

		Uint32 pixel = get_pixel32( surface, x, 0 );
		put_pixel32( smoothed, x, 0, pixel );
		pixel = get_pixel32( surface, x, surface->h - 1 );
		put_pixel32( smoothed, x, surface->h - 1, pixel );
	}

	for( int y = 0; y < smoothed->h; y++ ){

		Uint32 pixel = get_pixel32( surface, 0, y );
		put_pixel32( smoothed, 0, y, pixel );
		pixel = get_pixel32( surface, surface->w - 1, y );
		put_pixel32( smoothed, surface->w - 1, y, pixel );
	}

	for( int x = 1; x < smoothed->w - 1; x++ ){
		for( int y = 1; y < smoothed->h - 1; y++ ){

			pix32 color1 = ((pix32*)surface->pixels)[ ( y * surface->w ) + x ];
			pix32 color2 = ((pix32*)surface->pixels)[ ( ( y + 1 ) * surface->w ) + x ];
			pix32 color3 = ((pix32*)surface->pixels)[ ( y * surface->w ) + x + 1 ];
			pix32 color4 = ((pix32*)surface->pixels)[ ( ( y + 1 )* surface->w ) + x + 1 ];
			pix32 color5 = ((pix32*)surface->pixels)[ ( ( y - 1 ) * surface->w ) + x + 1 ];
			pix32 color6 = ((pix32*)surface->pixels)[ ( ( y - 1 ) * surface->w ) + x ];
			pix32 color7 = ((pix32*)surface->pixels)[ ( ( y - 1 ) * surface->w ) + x - 1 ];
			pix32 color8 = ((pix32*)surface->pixels)[ ( y * surface->w ) + x - 1 ];
			pix32 color9 = ((pix32*)surface->pixels)[ ( ( y + 1 )* surface->w ) + x - 1 ];

			if( (color1.r != 0xFF && color1.g != 0xFF && color1.b != 0) &&
				(color2.r != 0xFF && color2.g != 0xFF && color2.b != 0) &&
				(color3.r != 0xFF && color3.g != 0xFF && color3.b != 0) &&
				(color4.r != 0xFF && color4.g != 0xFF && color4.b != 0) &&
				(color5.r != 0xFF && color5.g != 0xFF && color5.b != 0) &&
				(color6.r != 0xFF && color6.g != 0xFF && color6.b != 0) &&
				(color7.r != 0xFF && color7.g != 0xFF && color7.b != 0) &&
				(color8.r != 0xFF && color8.g != 0xFF && color8.b != 0) &&
				(color9.r != 0xFF && color9.g != 0xFF && color9.b != 0)
			){

				color1.r = ( color1.r + color2.r + color3.r + color4.r + color5.r + color6.r + color7.r + color8.r + color9.r ) / 9;
				color1.g = ( color1.g + color2.g + color3.g + color4.g + color5.g + color6.g + color7.g + color8.g + color9.g ) / 9;
				color1.b = ( color1.b + color2.b + color3.b + color4.b + color5.b + color6.b + color7.b + color8.b + color9.b ) / 9;

			}
				Uint32 pixel = SDL_MapRGB( surface->format, color1.b, color1.g, color1.r );

				put_pixel32( smoothed, x, y, pixel );

		}
	}

	if( SDL_MUSTLOCK( surface ) )
		SDL_UnlockSurface( surface );

	if( surface->flags & SDL_SRCCOLORKEY )
		SDL_SetColorKey( smoothed, SDL_RLEACCEL | SDL_SRCCOLORKEY, surface->format->colorkey );

	return smoothed;

}

void smooth_surface_self( SDL_Surface* &surface, int level ){

	SDL_Surface* temp = surface;

	surface = smooth_surface( temp, level );

	SDL_FreeSurface( temp );

}

