#pragma once

#include <utility>
#include <cassert>

#include "../GlApiExt.h"
#include "../TextureTypes.h"



namespace lib_gl
{


//! SDLの画像バッファをOpneGLのカレントテクスチャにセットする
inline bool SetSDLTexture(const SDL_Surface* img, lib_gl::TEXTURE_MODE tex_mode, lib_gl::TEXTURE_COMPRESS compress_mode)
{
	bool is_compress = (compress_mode == TEXCOMP_ENABLE);

	GLint internal_format;
	GLint pixel_format;
	GLenum color_size;
	if( img->format->BitsPerPixel == 32 )
	{
		internal_format = (is_compress ? GL_COMPRESSED_RGBA : GL_RGBA);

		if( img->format->Bshift > img->format->Rshift )
			pixel_format = GL_RGBA;
		else
			pixel_format = GL_BGRA;

		color_size = GL_UNSIGNED_BYTE;
	}
	else if( img->format->BitsPerPixel == 24 )
	{
		internal_format = (is_compress ? GL_COMPRESSED_RGB : GL_RGB);

		if( img->format->Bshift > img->format->Rshift )
			pixel_format = GL_RGB;
		else
			pixel_format = GL_BGR;

		color_size = GL_UNSIGNED_BYTE;
	}
	else if( img->format->BitsPerPixel == 8 )
	{
		// TODO : 正しく動いていない
		assert(false);

		internal_format = (is_compress ? GL_COMPRESSED_RGB : GL_RGB);

		if( img->format->Bshift > img->format->Rshift )
			pixel_format = GL_RGB;
		else
			pixel_format = GL_BGR;

		// TODO : おそらくこの指定が間違えている
		color_size = GL_2_BYTES;
	}
	else
	{
		assert(false);
		return false;
	}

	bool IsNormal = (tex_mode == TEXTURE_NORMAL);
	bool IsMipmap = (tex_mode == TEXTURE_MIPMAP);
	if( !IsNormal && !IsMipmap )
	{
		assert( false );
		return false;
	}

	GLint line_pixels_buffer = img->pitch / img->format->BytesPerPixel;

	int Prev_GL_UNPACK_ALIGNMENT  = glGetInteger( GL_UNPACK_ALIGNMENT  );
	int Prev_GL_PACK_ALIGNMENT    = glGetInteger( GL_PACK_ALIGNMENT    );
	int Prev_GL_UNPACK_ROW_LENGTH = glGetInteger( GL_UNPACK_ROW_LENGTH );

	glPixelStorei( GL_UNPACK_ALIGNMENT , 4 );
	//glPixelStorei( GL_PACK_ALIGNMENT , 4 );
	//glPixelStorei(GL_UNPACK_ROW_LENGTH, line_pixels_buffer);

	if( IsNormal )
	{
		glTexImage2D( GL_TEXTURE_2D
		            , 0
		            , internal_format
		            , img->w , img->h
		            , 0
		            , pixel_format , color_size
		            , img->pixels
		            );
	}
	else
	{
		gluBuild2DMipmaps( GL_TEXTURE_2D
		                 , internal_format
		                 , img->w , img->h
		                 , pixel_format , color_size
		                 , img->pixels
		                 );
	}

	glPixelStorei( GL_UNPACK_ALIGNMENT  , Prev_GL_UNPACK_ALIGNMENT  );
	glPixelStorei( GL_PACK_ALIGNMENT    , Prev_GL_PACK_ALIGNMENT    );
	glPixelStorei( GL_UNPACK_ROW_LENGTH , Prev_GL_UNPACK_ROW_LENGTH );

	return true;
}

inline bool SetSDLTexture(const SDL_Surface* img, lib_gl::TEXTURE_MODE tex_mode)
{
	return SetSDLTexture( img , tex_mode , TEXCOMP_DISABLE );
}

inline bool SetSDLTexture(const SDL_Surface* img, lib_gl::TEXTURE_COMPRESS compress_mode)
{
	return SetSDLTexture( img , TEXTURE_NORMAL , compress_mode );
}

inline bool SetSDLTexture(const SDL_Surface* img)
{
	return SetSDLTexture( img , TEXTURE_NORMAL , TEXCOMP_DISABLE );
}


//! SDL画像の上下反転
inline void SDL_FlipY(SDL_Surface* surface)
{
	if( surface == NULL )
		return;

	int w = surface->w;
	int h = surface->h;
	int bps = surface->format->BytesPerPixel;
	int pitch_w = surface->pitch;
	unsigned char* bits = (unsigned char*)surface->pixels;

	for( int y = 0 ; y < h/2 ; ++y )
	{
		int yu = y;
		int yb = h - y - 1;

		for( int x = 0 ; x < w ; ++x )
		{
			for( int i = 0 ; i < bps ; ++i )
			{
				int iu = ( x * bps + yu * pitch_w ) + i;
				int ib = ( x * bps + yb * pitch_w ) + i;
				std::swap( bits[iu] , bits[ib] );
			}
		}
	}
}



}
