#include "Salamander.h"
#include "SDLTexture.h"

#include "SDLInclude.h"
#include "SDLFormatMapping.h"

namespace Salamander
{

defineUniqueId(SDLTexture);
SDLTexture::SDLTexture() :
	boundTexture_(0)
{
	
}

SDLTexture::~SDLTexture()
{
	// clean up memory
	if(boundTexture_)
	{
		glDeleteTextures(1, &boundTexture_);
		delete[] pixels_;
	}
}

bool SDLTexture::load(const std::string& name)
{
	// The texture can only be bound once
	if(boundTexture_)
		return false;

	// First, load an SDL image and populate our texture members
	SDL_Surface* surface = IMG_Load(name.c_str());
	if(!surface)
		return false;

    // Get the number of channels in the SDL surface
	bool reverseBytes = (surface->format->Rmask == 0x000000ff) ? false : true;
	switch(surface->format->BytesPerPixel)
	{
		case 1:
			pixelFormat_.contentType_ = PixelFormat::Luminance;
			pixelFormat_.byteMask_ = PixelFormat::Unsigned8;
			break;
		case 2:
			pixelFormat_.contentType_ = PixelFormat::LuminanceAlpha;
			pixelFormat_.byteMask_ = PixelFormat::Unsigned16;
			break;
		case 3:
			pixelFormat_.contentType_ = PixelFormat::Colour;
			pixelFormat_.byteMask_ = reverseBytes ? PixelFormat::B8G8R8 : 
													PixelFormat::R8G8B8;
			break;
		case 4:
			pixelFormat_.contentType_ = PixelFormat::ColourAlpha;
			pixelFormat_.byteMask_ = reverseBytes ? PixelFormat::B8G8R8A8 : 
													PixelFormat::R8G8B8A8;
			break;
		default:
			return false;
	}

	// Set up the size
	size_.x_ = surface->w;
	size_.y_ = surface->h;

	// Copy pixel data into our texture and free the surface
	//unsigned long bytes = surface->h * surface->pitch;
	//pixels_ = new unsigned char[bytes];
	//memcpy((void*)pixels_, surface->pixels, bytes);
	//SDL_FreeSurface(surface);

	// Convert internal formats to GL formats
	unsigned long format = SDLPixelContentMapping(pixelFormat_.contentType_);
	unsigned long type = SDLPixelMaskMapping(pixelFormat_.byteMask_);
	unsigned long internalFormat = GL_RGBA8;

	// Generate a new Id for our texture    
	glGenTextures(1, &boundTexture_);

    // Set up the GL properties for the texture
    glBindTexture(GL_TEXTURE_2D, boundTexture_);

	glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // TODO:huh?

    // Set the texture's stretching properties
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

	// Modulate with colour
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	int bpp = pixelFormat_.bytesPerPixel();
	glTexImage2D(GL_TEXTURE_2D, 0, bpp, int(size_.x_), int(size_.y_), 0,
                      format, GL_UNSIGNED_BYTE, surface->pixels);

	// TODO : int type for vector - store sizes?

	// Successful
	return true;
}


/*
bool SDLTexture::generateTexture()
{
	// The texture can only be bound once
	if(boundTexture_)
		return false;

	// Convert internal formats to GL formats
	unsigned long format = SDLPixelContentMapping(pixelFormat_.contentType_);
	unsigned long type = SDLPixelMaskMapping(pixelFormat_.byteMask_);
	//unsigned long internalFormat

	// Generate a new Id for our texture
    glGenTextures(1, &boundTexture_);

    // Set up the GL properties for the texture
    glBindTexture(GL_TEXTURE_2D, boundTexture_);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, colours, surface->w, surface->h, 0,
                      texture_format, GL_UNSIGNED_BYTE, surface->pixels);

	// Successful
	return true;
}*/

}