// cRenderClass.cpp
// 
//////////////////////////////////////////////////////////////////////////////////////////
// includes 
//////////////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"

//////////////////////////////////////////////////////////////////////////////////////////
// Declarations 
//////////////////////////////////////////////////////////////////////////////////////////
cRenderClass graphics( SCREEN_WIDTH, SCREEN_HEIGHT );
Fireworks *fireworks = NULL;
//////////////////////////////////////////////////////////////////////////////////////////
// cRenderClass() - constructor 
//////////////////////////////////////////////////////////////////////////////////////////
cRenderClass::cRenderClass(const int w, const int h)
{
	m_sw = w;
	m_sh = h;

	int total_count = w*h*3;

	m_buffer = new float[total_count];

	for( int i=0; i<total_count; i++ )
	{
		m_buffer[i] = 0;
	}

	m_point_size = 1;
}

//////////////////////////////////////////////////////////////////////////////////////////
// cRenderClass() - destructor 
//////////////////////////////////////////////////////////////////////////////////////////
cRenderClass::~cRenderClass()
{
}

//////////////////////////////////////////////////////////////////////////////////////////
// loop() - enters game loop 
//////////////////////////////////////////////////////////////////////////////////////////
void cRenderClass::loop()
{
	glutMainLoop();
}

//////////////////////////////////////////////////////////////////////////////////////////
// initialize glut stuff
//////////////////////////////////////////////////////////////////////////////////////////
void cRenderClass::create(int argc, _TCHAR* argv[])
{
	// initialise the glut library
	glutInit(&argc, (char**)argv);

	// set up the initial display mode
	// need both double buffering and z-buffering 
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

	// set the initial window position 
	glutInitWindowPosition(100, 100);

	// set the initial window size 
	glutInitWindowSize(SCREEN_WIDTH, SCREEN_HEIGHT);

	// create and name the window 
	glutCreateWindow("Wow!  F1 start pause");

	// reshape callback for current window 
	glutReshapeFunc(winReshapeFunc);

	// set display callback for current window  
	glutDisplayFunc(renderScene);	

	// set up the global idle callback
	glutIdleFunc(update);
}

//////////////////////////////////////////////////////////////////////////////////////////
// clear() - clears out the render buffer
//////////////////////////////////////////////////////////////////////////////////////////
void cRenderClass::clear()
{

	for (int clr = 0; clr < SCREEN_WIDTH; clr++)
	{
		for (int j = 0; j < 2; j++)
		{
			int px1 = rand() % SCREEN_WIDTH;
			int py1 = rand() % SCREEN_HEIGHT;

			if (py1 < SCREEN_HEIGHT) {
				m_buffer[(((py1)*m_sw + (px1)) * 3) + 0] = m_buffer[(((py1)*m_sw + (px1)+1) * 3) + 0]=0;
				m_buffer[(((py1)*m_sw + (px1)) * 3) + 1] = m_buffer[(((py1)*m_sw + (px1)+1) * 3) + 1]=0;
				m_buffer[(((py1)*m_sw + (px1)) * 3) + 2] = m_buffer[(((py1)*m_sw + (px1 + 1)) * 3) + 2]=0;
				//m_buffer[py1 * 1200 + px1] = m_buffer[py1 * 1200 + px1 + 1] = BLACK;
			}

		}
	}
	//memset( m_buffer, 0, sizeof(float)*m_sw*m_sh*3 );
}

//////////////////////////////////////////////////////////////////////////////////////////
// setPointSize() - set the pixel size 
//////////////////////////////////////////////////////////////////////////////////////////
void cRenderClass::setPointSize(int size)
{
	m_point_size = size;
}

//////////////////////////////////////////////////////////////////////////////////////////
// drawPixel() 
//////////////////////////////////////////////////////////////////////////////////////////
void cRenderClass::drawPixel(int x, int y)
{/*
	int start, end;

	start = -(m_point_size/2);
	end	= (int)((m_point_size/2.0f) + 0.5);

	for( int i=start; i<end; i++ )
	{
		for( int j=start; j<end; j++ )
		{
			if( (x+j < 0) || (x+j >= m_sw) )
				continue;

			if( (y+i < 0) || (y+i >= m_sh) )
				continue;

			m_buffer[(((y+i)*m_sw+(x+j))*3) + 0] = m_colour.r;
			m_buffer[(((y+i)*m_sw+(x+j))*3) + 1] = m_colour.g;
			m_buffer[(((y+i)*m_sw+(x+j))*3) + 2] = m_colour.b;
		}
	}*/
	Fireworks *fireworks1 = fireworks;
	while (fireworks1 != NULL) {
		fireworks1->ShowFire(m_buffer, m_sw, m_sh);
		fireworks1 = fireworks1->fireworks;
	}

}

//////////////////////////////////////////////////////////////////////////////////////////
// render() - renders this buffer to screen  
//////////////////////////////////////////////////////////////////////////////////////////
void cRenderClass::render()
{

	// clear the back buffer 
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glDrawPixels( m_sw, m_sh, GL_RGB, GL_FLOAT, m_buffer );

	// swap the buffers of the current window 
	glutSwapBuffers();

	// clear out the buffer 
	clear(); 
}

//////////////////////////////////////////////////////////////////////////////////////////
// setColour() - sets the current colour  
//////////////////////////////////////////////////////////////////////////////////////////
void cRenderClass::setColour(float r, float g, float b)
{
	m_colour.r = r;
	m_colour.g = g;
	m_colour.b = b;
}

//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// winReshapeFunc() - gets called initially and whenever the window get resized
// resizing has been locked 
//////////////////////////////////////////////////////////////////////////////////////////
void winReshapeFunc(GLint w, GLint h)
{ 
	// specify current matrix 
	glMatrixMode(GL_PROJECTION);

	// load an identity matrix 
	glLoadIdentity();	

	// create a projection matrix... i.e. 2D projection onto xy plane 
	glOrtho( -SCREEN_WIDTH, SCREEN_WIDTH, -SCREEN_HEIGHT, SCREEN_HEIGHT, -100, 100);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	// set up the viewport 
	glViewport
	(
		0,				// lower left x position 
		0,				// lower left y position
		(GLsizei) SCREEN_WIDTH,	// viewport width
		(GLsizei) SCREEN_HEIGHT	// viewport height
	);
}


Fireworks::Fireworks() {
	Init();
	fireworks = NULL;
}
void Fireworks::Init() {
	int rand1 = rand() % 13;
	int r[] = { 120,120,155,123,130,147,138,138,130,135,140,132,155 };
	int x[] = { 120,120,110,117,110,93,102,102,110,105,100,108,110 };
	int y[] = { 120,120,85,118,120,103,105,110,110,120,120,104,85 };
	fire.width = 240;
	fire.height = 240;
	fire.cen_x = x[rand1];
	fire.cen_y = y[rand1];
	fire.maxr = r[rand1];
	fire.show = false;
	fire.dt = 5;
	fire.t1 = timeGetTime();
	fire.r = 0;

	jet.t1 = timeGetTime();
	jet.dt = rand() % 10;
	jet.n = 0;
	jet.shoot = false;
	Load();
}
void Fireworks::Load() {
	ifstream myfile("out.txt");
	int id = rand() % 6;
	int sum = 0;
	id = 240 * 240 * id;
	int get;
	while (myfile >> get)
	{
		if (sum > id) {
			break;
		}
		sum++;
	}
	for (int m = 0; m < 240; m++)
	{
		for (int n = 0; n < 240; n++) {
			myfile >> fire.xy[m][n];
		}
	}
	myfile.clear();

}

void Fireworks::Shoot() {
	jet.t2 = timeGetTime();
	if (jet.t2 - jet.t1 > jet.dt&& jet.shoot == true)
	{
		//putimage(jet[i].x, jet[i].y, &jet[i].img[jet[i].n], SRCINVERT);

		if (jet.y >= jet.hy)
		{
			jet.y -= 5;
			jet.n++;
		}
		//putimage(jet[i].x, jet[i].y, &jet[i].img[jet[i].n], SRCINVERT);
		//The higher the firework, the slower it goes
		if (jet.y - jet.hy * 4 < jet.height)
			jet.dt = rand() % 4 + 10;

		if (jet.y <= jet.hy)
		{
			//	putimage(jet[i].x, jet[i].y, &jet[i].img[jet[i].n], SRCINVERT);
			fire.x = jet.x;
			fire.y = jet.hy;
			fire.show = true;
			jet.shoot = false;
		}
		jet.t1 = jet.t2;
	}
}

void Fireworks::ShowFire(float m_buffer[], int m_sw,int m_sh)
{
	//dt 
	int  drt[16] = { 5, 5, 5, 5, 5, 6, 25, 25, 25, 25, 55, 55, 55, 55, 65, 65 };
	fire.t2 = timeGetTime();

	if (fire.t2 - fire.t1 > fire.dt&& fire.show == true)
	{
		if (fire.r < fire.maxr)
		{
			fire.r++;
			fire.dt = drt[fire.r / 10];
			fire.draw = true;
		}

		if (fire.r >= fire.maxr - 1)
		{
			fire.draw = false;
			Init();
		}
		fire.t1 = fire.t2;
	}

	//
	if (fire.draw)
	{
		for (double a = 0; a <= 6.28; a += 0.01)
		{
			int x1 = (int)(fire.cen_x + fire.r * cos(a));
			int y1 = (int)(fire.cen_y + fire.r * sin(a));

			if (x1 > 0 && x1 < fire.width && y1>0 && y1 < fire.height)
			{
				int b = fire.xy[x1][y1] & 0xff;   //blue
				int g = (fire.xy[x1][y1] >> 8) & 0xff;   //green
				int r = fire.xy[x1][y1] >> 16;   //red

				int xx = (int)(fire.x + fire.r * cos(a));
				int yy = (int)(fire.y - fire.r * sin(a));

				//
				if (r > 0x20 && g > 0x20 && b > 0x20 && xx < 1200 && xx>0 && yy > 0 && yy < 600)
				{

					//m_buffer[(((yy)*m_sw + (xx)) * 3) + 0] = (fire.xy[x1][y1] & 0xff0000) >> 16;
					//m_buffer[(((yy)*m_sw + (xx)) * 3) + 1] = (fire.xy[x1][y1] & 0xff00) >> 8;
					//m_buffer[(((yy)*m_sw + (xx)) * 3) + 2] = (fire.xy[x1][y1] & 0xff);

					if ((xx < 0) || (xx >= m_sw))
						continue;

					if ((yy < 0) || (yy >= m_sh))
						continue;
					int rbg1 = fire.xy[x1][y1], rbg[3];
					////graphics.setColour(1.0f, 0.5f, 0.1f);
					//m_buffer[(((xx)*m_sw + (yy)) * 3) + 0] = 0;
					//m_buffer[(((xx)*m_sw + (yy)) * 3) + 1] = 0;
					//m_buffer[(((xx)*m_sw + (yy)) * 3) + 2] = 2.55;
					
					m_buffer[(((xx)*m_sw + (yy)) * 3) + 0] = ((rbg1 & 0xff0000) >> 16)/100;
					m_buffer[(((xx)*m_sw + (yy)) * 3) + 1] = ((rbg1 & 0xff00) >> 8)/100;
					m_buffer[(((xx)*m_sw + (yy)) * 3) + 2] = ((rbg1 & 0xff))/100;
					rbg[0] = (rbg1 & 0xff0000) >> 16;
					rbg[1] = (rbg1 & 0xff00) >> 8;
					rbg[2] = (rbg1 & 0xff);

					//pmem[yy * 1200 + xx] = BGR(fire.xy[x1][y1]);
				}

			}
		}
		fire.draw = false;
	}
}


void Fireworks::ChoiseRelu() {
	if (jet.shoot == false && fire.show == false)
	{
		jet.x = rand() % 500;
		jet.y = rand() % 100 + 400;
		jet.hx = jet.x;
		jet.hy = rand() % 200;
		jet.height = jet.y - jet.hy;
		jet.shoot = true;
		//	putimage(jet[n].x, jet[n].y, &jet[n].img[jet[n].n], SRCINVERT);
	}
}

 Fireworks::~Fireworks() {

}