/***************************************************************/
//
//
//		DirectX	[ textureglinterface.cpp ]
//
//											Author	kazuki tanaka
//											Date	2017 5/17
/*---------------------------------------------------------------
■Update : 2017/5/17
			textureglinterface.cppの作成

/*---------------------------------------------------------------
	Include File
---------------------------------------------------------------*/

#include "texturegl_interface.h"
#include "texture_manager.h"

#include "rendereropengl.h"

#include <stdio.h>
#include <Windows.h>

#ifdef _DEBUG
#pragma comment( lib, "dlibpng16.lib" )
#pragma comment( lib, "dzlib.lib" )
#else
#pragma comment( lib, "libpng16.lib" )
#pragma comment( lib, "zlib.lib" )
#endif // _DEBUG

#include "png.h"


/*---------------------------------------------------------------
	Macro Difinition
---------------------------------------------------------------*/


/*---------------------------------------------------------------
	Const Number Difinition
---------------------------------------------------------------*/


/*---------------------------------------------------------------
	static member variable Initialize 
----------------------------------------------------------------*/




// TextureGLInterface Constructor
TextureGLInterface::TextureGLInterface( )
	: data( 0 )
{

	// Menber Clear Process

}

// TextureGLInterface Destructor
TextureGLInterface::~TextureGLInterface( )
{

	// Do Nothing!!

}

// TextureGLInterface Create Instance 
TextureGLInterface* TextureGLInterface::Create( void )
{
	
	// Create Class Instance
	return new TextureGLInterface;
	
}

// TextureGLInterface Initialize
void TextureGLInterface::Release( void )
{

	// Release Process


}

// TextureGLInterface SetTexture
void TextureGLInterface::SetTexture( void )
{

	// TextureGLInterface SetTexture
	glBindTexture( GL_TEXTURE_2D, data );

	
}

// TextureGLInterface Load
bool TextureGLInterface::Load( const char* FILE_NAME )
{

	// texture format
	const int TEXTURE_FORMAT_MAX = 2;
	const char* TEXTURE_FORMAT[ ] = {
		//".jpg",
		".png",
		".tga",
		//".bmp",
		//".dds"
	};
	
	// Divide File Name
	char filename [256] = { };		// ファイルネーム
	char extension[256] = { };		// 拡張子
	char loadFile [256] = { };		// ロードファイルネーム

	// Split Path
	_splitpath( FILE_NAME, NULL, NULL, filename, extension );
	
	// Synthesis String < Load File Name >
	sprintf( loadFile, "%s%s", filename , extension );
	
	// Create Texture Interface Process

	if( strcmp( extension, ".png" ) == 0 ){
		
		data = GLTextureLoadFromPng( FILE_NAME );
		if( !data )
		{
			#ifdef _DEBUG
			MessageBox( NULL, loadFile , "Create Texture File ERROR!! : texturegl_interface.cpp", MB_OK | MB_ICONWARNING );
			#endif	// _DEBUG
			return false;
		}else{
			return true;	
		}
	}
	if( strcmp( extension, ".tga" ) == 0 ){
		
		
		data = GLTextureLoadFromTga( FILE_NAME );
		if( !data )
		{
			#ifdef _DEBUG
			MessageBox( NULL, loadFile , "Create Texture File ERROR!! : texturegl_interface.cpp", MB_OK | MB_ICONWARNING );
			#endif	// _DEBUG
			return false;
		}else{
			return true;	
		}
	}
	
	return false;	

}

// TextureGLInterface Load From Manager
TextureInterface* TextureGLInterface::LoadFromManager( const char* FILE_NAME )
{

	if( TextureManager::Load( FILE_NAME ) ){
	
		//static_cast<TextureInterface>(this) = TextureManager::Bind( FILE_NAME );
		return TextureManager::Bind( FILE_NAME );
	}

	return nullptr;

}

// CTecxtureGL Load Texture
unsigned int TextureGLInterface::GLTextureLoadFromTga( const std::string& fileName )
{	

	// file Load
	FILE* fp = fopen( fileName.data( ), "rb" );

	if( fp == NULL ){

		#ifdef _DEBUG
		MessageBox( NULL, "FILE_LOAD_ERROR", "ERROR!!", 0 );
		#endif // _DEBUG
		return 0;
	}

	// get header file
	unsigned char header[18];
	bool byteformat = false;
	bool vertical = false,horizonal = false;

	fread( header, sizeof(header), 1, fp );

	// pixel Stencil Value
	if( header[16] == 32 ){
		byteformat = true;
	}

	// check [ Header File ]
	/*
	if( (header[17] && 0x10) ){
		horizonal = true;
	}

	if( (header[17] && 0x20) ){
		vertical = true;
	}*/

	unsigned short width, height;

	// get Pixel Size
	width = *((unsigned short*)&header[12]);
	//width = header[13] * 256 + header[12];
	height = *((unsigned short*)&header[14]);

	BYTE byte = *(&header[16]);

	unsigned char* pImage
		= new unsigned char[ width * height * 4 ];

	/*
	if( horizonal && vertical ){
		for( unsigned short y = 0; y < height; y++ ){
			for( unsigned short x = 0; x < width; x++ ){

				pImage[ (y * width + ( width-1 - x ) ) *4 + 2 ] = fgetc(fp);
				pImage[ (y * width + ( width-1 - x ) ) *4 + 1 ] = fgetc(fp);
				pImage[ (y * width + ( width-1 - x ) ) *4 + 0 ] = fgetc(fp);
				pImage[ (y * width + ( width-1 - x ) ) *4 + 3 ] = fgetc(fp);

			}
		}
	}
	else if( vertical ){*/

		for( unsigned short y = 0; y < height; y++ ){
			for( unsigned short x = 0; x < width; x++ ){

				pImage[ (y * width + x ) *4 + 2 ] = fgetc(fp);
				pImage[ (y * width + x ) *4 + 1 ] = fgetc(fp);
				pImage[ (y * width + x ) *4 + 0 ] = fgetc(fp);
				pImage[ (y * width + x ) *4 + 3 ] = fgetc(fp);

			}
		}
	/*}
	else if( horizonal ){

		for( unsigned short y = 0; y < height; y++ ){
			for( unsigned short x = 0; x < width; x++ ){

				pImage[ ( (height-1 - y) * width + ( width-1 - x ) ) *4 + 2 ] = fgetc(fp);
				pImage[ ( (height-1 - y) * width + ( width-1 - x ) ) *4 + 1 ] = fgetc(fp);
				pImage[ ( (height-1 - y) * width + ( width-1 - x ) ) *4 + 0 ] = fgetc(fp);
				pImage[ ( (height-1 - y) * width + ( width-1 - x ) ) *4 + 3 ] = fgetc(fp);

			}
		}
	}
	else{
		for( unsigned short y = 0; y < height; y++ ){
			for( unsigned short x = 0; x < width; x++ ){

				pImage[ ( (height-1 - y) * width + x ) *4 + 2 ] = fgetc(fp);
				pImage[ ( (height-1 - y) * width + x ) *4 + 1 ] = fgetc(fp);
				pImage[ ( (height-1 - y) * width + x ) *4 + 0 ] = fgetc(fp);
				pImage[ ( (height-1 - y) * width + x ) *4 + 3 ] = fgetc(fp);

			}
		}
	}
	*/
	

	

	fclose(fp);

	unsigned int texture;
	glGenTextures( 1, &texture );

	glBindTexture( GL_TEXTURE_2D, texture );

	glPixelStorei( GL_PACK_ALIGNMENT, 1 );

	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );

	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );

	gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pImage );

	glBindTexture( GL_TEXTURE_2D, 0 );

	delete[] pImage;
	pImage = nullptr;

	return texture;

}

// CTecxtureGL Load Texture
unsigned int TextureGLInterface::GLTextureLoadFromPng( const std::string& fileName )
{

	
	// Signature Load Process
	FILE* fp = fopen( fileName.data( ), "rb" );

	if( fp == NULL ){

		#ifdef _DEBUG
		MessageBox( NULL, "FILE_LOAD_ERROR", "ERROR!!", 0 );
		#endif // _DEBUG
		return 0;
	}

	unsigned char header[8];

	// get Header Info
	fread( header, 1, 8, fp);
	
	if ( png_sig_cmp( header, 0, 8 ) )
		return (0);

		
	// png_struct 構造体の初期化
	png_structp png_ptr = png_create_read_struct (
					   PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr );
	if (!png_ptr) return (ERROR);

	// png_info 構造体の初期化（画像データの前にあるチャンク用）
	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr) {
		png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
		return (ERROR);
	}

	// png_info 構造体の初期化（画像データの後にあるチャンク用）
	png_infop end_info = png_create_info_struct(png_ptr);
	if (!end_info) {
		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
		return (ERROR);
	}

	// setjmp/longjmp
	if (setjmp(png_jmpbuf(png_ptr))) {
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		fclose(fp);
		return (ERROR);
	}

	// ファイル・ポインタのセット
	png_init_io( png_ptr, fp );

	// 事前にシグネチャを読込確認済なら、ファイル先頭から読み飛ばしているバイト数を知らせる
	png_set_sig_bytes( png_ptr, 8 );  

	// 高水準読込インタフェース
	png_read_png(
		png_ptr,
		info_ptr,
		0,//PNG_TRANSFORM_PACKING
		//| PNG_TRANSFORM_INVERT_ALPHA,
		NULL );

	unsigned int width  = png_get_image_width( png_ptr, info_ptr );
	unsigned int height = png_get_image_height( png_ptr, info_ptr );
	// Custom Load
	unsigned int depth = png_get_bit_depth( png_ptr, info_ptr );

	// 各行のピクセル・データのポインタ配列
	png_bytep* row_pointers;

	// Pixelフォーマット書き出し
	unsigned char* pImage
		= new unsigned char[ width * height * 4 ];

	row_pointers = png_get_rows( png_ptr, info_ptr );

	for( unsigned short y = 0; y < height; y++ ){
		for( unsigned int x = 0; x < width; x++ ){

			pImage[ (y * width + x) *4 + 0 ] = row_pointers[y][ x * 4 + 0 ];
			pImage[ (y * width + x) *4 + 1 ] = row_pointers[y][ x * 4 + 1 ];
			pImage[ (y * width + x) *4 + 2 ] = row_pointers[y][ x * 4 + 2 ];
			pImage[ (y * width + x) *4 + 3 ] = row_pointers[y][ x * 4 + 3 ];
		}
	}

	png_destroy_read_struct(
		&png_ptr,
		&info_ptr,
		&end_info );

	fclose(fp);
	
	
	unsigned int texture;
	glGenTextures( 1, &texture );

	glBindTexture( GL_TEXTURE_2D, texture );

	glPixelStorei( GL_PACK_ALIGNMENT, 1 );

	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );

	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );

	gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pImage );

	glBindTexture( GL_TEXTURE_2D, 0 );

	delete[] pImage;
	pImage = nullptr;

	return texture;

}





