
#include <stdlib.h>
#include <math.h>
#include "GL/glut.h"
#include "GL/freeglut_ext.h"

#include "png.h"
#include "Live2D.h"
#include "util/UtDebug.h"
#include "util/UtSystem.h"
#include "Live2DModelWinGL.h"

using namespace live2d;

Live2DModelWinGL* live2DModel;

void display(void)
{
	glClear(GL_COLOR_BUFFER_BIT);
	double t = (UtSystem::getUserTimeMSec()/1000.0) * 2 * 3.14 ;
	live2DModel->setParamFloat("PARAM_ANGLE_X", (float)(30 * sin( t/3.0 )) );
	
	live2DModel->update();
	live2DModel->draw();


	glFlush();
}

void timer(int value) {
	

	glutPostRedisplay();
	glutTimerFunc(30 , timer , 0);
}

int loadGLTexture(const char* path)
{
	unsigned int id; 

	FILE            *fp;
	png_structp     png_ptr;
	png_infop       info_ptr;
	unsigned int   width, height;
	int             bit_depth, color_type, interlace_type;
	unsigned char   *image;

	errno_t error;

	if ( (error = fopen_s(&fp,path,"rb")) != 0 ) {
		printf("file not exists!");
		return -1;
	}

	png_ptr = png_create_read_struct(                       
	                PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	info_ptr = png_create_info_struct(png_ptr);             

	png_init_io(png_ptr, fp);                              
	png_read_info(png_ptr, info_ptr);                      
	png_get_IHDR(png_ptr, info_ptr, &width, &height,      
	                &bit_depth, &color_type, &interlace_type,
	                NULL, NULL);
    int rb = png_get_rowbytes(png_ptr, info_ptr);
    image = new unsigned char[height * rb];
    unsigned char **recv = new unsigned char*[height];
    for (int i = 0; i < height; i++)
        recv[i] = &image[i * rb];
    png_read_image(png_ptr, recv);
    png_read_end(png_ptr, info_ptr);

	//premultiplied alpha
	

    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    fclose(fp);
    delete[] recv;


	glEnable(GL_TEXTURE_2D);
	glGenTextures(1 , &id);

	glBindTexture(GL_TEXTURE_2D, id);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    
	/*glTexImage2D(
		GL_TEXTURE_2D , 0 , GL_RGBA , width , height ,
		0 , GL_RGBA , GL_UNSIGNED_BYTE , image
	);*/
	gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, width, height, GL_RGBA, GL_UNSIGNED_BYTE, image);
	return id;
}

void init(void)
{
	glClearColor(0.0, 0.0, 1.0, 1.0);
	live2DModel = live2d::Live2DModelWinGL::loadModel("haru.moc") ;

	const char* TEXTURES[] = { 
		"texture_00.png" ,
		"texture_01.png" ,
		"texture_02.png" ,
		NULL ,
	} ;

	for( int i = 0 ; i < 1000 ; i++ ){
		if( ! TEXTURES[i] ) break ;

		int tex =loadGLTexture(TEXTURES[i]);

		if( tex < 0 ) printf("failed");
		live2DModel->setTexture( i , tex ) ;
	}
	live2DModel->setPremultipliedAlpha(false);
}

void resize(int w, int h)
{
  glViewport(0, 0, w, h);

  glLoadIdentity();

	float aspect=(float)w/h;
	float sx = 2.0 / live2DModel->getCanvasWidth() ;
	float sy = -2.0 / live2DModel->getCanvasWidth() * aspect;
	float x = -1 ;
	float y = 1 ;
	float matrix []= {
		sx , 0 , 0 , 0 ,
		0 , sy ,0 , 0 ,
		0 , 0 , 1 , 0 ,
		x , y , 0 , 1
	} ;
	

	live2DModel->setMatrix(matrix);
}


int main(int argc, char *argv[])
{
	Live2D::init();
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGBA);
	glutInitWindowSize(600,600);
	glutCreateWindow(argv[0]);
	init();
	glutDisplayFunc(display);
	glutReshapeFunc(resize);
	glutTimerFunc(100 , timer , 0);
	glutMainLoop();
	return 0;
}

