/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2009.
     ssss    gggg x   x         Steven Goodwin. All Rights Reserved.
    
This version has been released under the GNU Public License v2.0.

Please see the license files for details.

File: sgx/src/utils/imagelib/imageloader.cpp

*/

#include "sgx/core/core.hpp"
#include "sgx/filesystem/filesystem.hpp"
#include "domains/graphics/surface/surface.hpp"
#include "utils/imagelib/imagelib.hpp"

CImageLoader *CImageLoader::m_pSingleton = NULL;

CImageLoader *CImageLoader::create()
{
	m_pSingleton = new CImageLoader;
	if (m_pSingleton) {
		m_pSingleton->initialize();
	}
	return m_pSingleton;
}

CImageLoader *CImageLoader::get()
{
	if (!m_pSingleton) {
		return create();
	}
	return m_pSingleton;
}

CImageLoader::CImageLoader()
{
}

void 
CImageLoader::initialize()
{
}

tBOOL CImageLoader::registerObject(const CImageParser *pCls)
{
	m_Parsers.push_back(pCls);
	return TRUE;
}

tBOOL
CImageLoader::loadImageData(CImageData &data, const sgxString &filename)
{
	return loadImageData(data, filename.c_str());
}

tBOOL
CImageLoader::loadImageData(CImageData &data, const char *pFilename)
{
	CSGXFile file(pFilename);

	return loadImageData(data, file);
}

tBOOL
CImageLoader::loadImageData(CImageData &data, CSGXFile &file)
{
	if (!file.open()) {
		return FALSE;
	}

	// Find a suitable parser from the registerObjected list
	sgxVector<const CImageParser *>::const_iterator cit = m_Parsers.begin();
	tDISC_SIZE seek_pos = file.getSeekPos();

	for(;cit!=m_Parsers.end();++cit) {
		if ((*cit)->isRecognised(file)) {

			// rewind the file pointer because the recognition code
			// doesn't have to check the file extension.
			file.seek(seek_pos, CSGXDeviceBlockState::eSeekFromBegin);

			// We're ready to read the file.
			return (*cit)->open(file, data);
		}
		// rewind pointer so every parser has a chance
		file.seek(seek_pos, CSGXDeviceBlockState::eSeekFromBegin);
	}

	return FALSE;
}


CSGXSurface *
CImageLoader::loadSurface(const sgxString &name, const CImageData::Mask &mask)
{
	return loadSurface(name.c_str(), mask);
}

CSGXSurface *
CImageLoader::loadSurface(const char *pFilename, const CImageData::Mask &mask)
{
CSGXFile file(pFilename);
CSGXSurface *pSurface;

	if (!file.open()) {
		return NULL;
	}

	pSurface = loadSurface(file, mask);
	file.close();

	return pSurface;
}


CSGXSurface *
CImageLoader::loadSurface(CSGXFile &file, const CImageData::Mask &mask)
{
	CImageData data;

	if (loadImageData(data, file)) {
		if (mask.isValid()) {
			data.convertFormat(CImageData::eRGBA);
			data.applyMask(mask);
		}

		return new CSGXSurface(data);
	}

	return NULL;
}


CSGXSurface *
CImageLoader::loadSurface(const sgxString &name, const sgxString &alpha_name)
{
CSGXFile file(name);
CSGXFile alpha_file(alpha_name);

	if (file.open() && alpha_file.open()) {
		return loadSurface(file, alpha_file);
	}

	return NULL;
}

CSGXSurface *
CImageLoader::loadSurface(CSGXFile &file, CSGXFile &alpha_file)
{
	CImageData opaque_data;
	CImageData alpha_data;

	if (!loadImageData(opaque_data, file)) {
		return NULL;
	}

	if (!loadImageData(alpha_data, alpha_file)) {
		return NULL;
	}

	CImageData combined(opaque_data, alpha_data);
	return new CSGXSurface(combined);
}
