/*
 *  Context.cpp
 *  iphone-gl-app
 *
 *  Created by John Ryland on 14/06/09.
 *  Copyright 2009 InvertedLogic. All rights reserved.
 *
 */

#include "Debug.h"
#include <stdlib.h>
#include <OpenGLES/ES1/gl.h>
#include <OpenGLES/ES1/glext.h>
#include "Context.h"
#include "Sprite.h"
#include "Image.h"


#define RESOURCE_FILE	"ResourceList.h"
#include "Resources.h"
#undef RESOURCE_FILE


// Not really needed, except to trick xcode/gcc of the dependancy and
// need to recompile this file if ResourceList.h changes.
#define ADD_SOUND(x,y)
#define ADD_TEXTURE(x,y,z)
#define ADD_SPRITE(a,b,c,d,e,f,g,h,i,j,k,l,m)
#include "ResourceList.h"
#undef ADD_SOUND
#undef ADD_TEXTURE
#undef ADD_SPRITE


Context::Context()
{
	frame = 0;
	message = false;
	accelerometerLocation.x = 0;
	accelerometerLocation.y = 0;

	// Start music
	music.playMusic("music.mp3");

	// Load textures
	for (int i = 0; i < TextureCount; i++)
		textures += new Texture(textureFiles[i], textureSmooth[i]);

	// Load sound effects
	for (int i = 0; i < SoundCount; i++)
		sounds += new Sound(soundFiles[i]);

	// Load sprites
	for (int i = 0; i < SpriteCount; i++)
		sprites += new Sprite(spriteItems[i].verts, textures[spriteItems[i].textureId],
								spriteItems[i].texX, spriteItems[i].texY,
								spriteItems[i].texW, spriteItems[i].texH, spriteItems[i].texAdvX,
													spriteItems[i].texAdvY, spriteItems[i].frames);	

	sprites[Loading]->translate(128, 246);
	sprites[Load0]->translate(96, 156);
	sprites[StatusSprite]->setAlpha(0.7);
	sprites[OptionsSprite]->setAlpha(0.7);
	sprites[MsgBoxSprite]->setAlpha(0.7);
}


Context::~Context()
{
	foreach (Texture *item, textures)
		delete item;

	foreach (Sound *item, sounds)
		delete item;

	foreach (Sprite *item, sprites)
		delete item;
}


void Context::updateAcceleration(float x, float y)
{
	if ( !message ) {
		y = 5.0 * -y - 2.5;	// Scale to screen coordinate system
		x = 2.0 * x;
		const float kFilteringFactor = 0.1;
		if ( frame >= 138 ) {
			accelerometerLocation.x = x * kFilteringFactor + accelerometerLocation.x * (1.0 - kFilteringFactor);
			accelerometerLocation.y = y * kFilteringFactor + accelerometerLocation.y * (1.0 - kFilteringFactor);
		}
	}
}


void Context::draw()
{	
	//Set up OpenGL projection matrix
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	if ( !message )
		frame++;

	if ( frame < 18 ) {
		// Load textures
//		if ( frame > 1 && frame < 15 )
//			textures[frame] = new Texture(textureFiles[frame]);
		glOrthof(0, 319, 459, 0, -1, 1);
		glMatrixMode(GL_MODELVIEW);
		glClear(GL_COLOR_BUFFER_BIT);
		sprites[Load0]->draw();
		sprites[Loading]->advance();
		return;		
	}
	
	glOrthof(-2.0f, 2.0f, 3.0f, -3.0f, -2.0f, 2.0f);
    glMatrixMode(GL_MODELVIEW);
	glEnable(GL_BLEND);
	glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    glClear(GL_COLOR_BUFFER_BIT);

	static float scale1 = 10.0;
	static float scale2 = 12.0;
	static float scale3 = 14.0;

	const GLfloat backgroundVerts[4] = { -2.0f, -3.0f, 2.0f, 3.0f };
	const GLfloat backgroundVerts2[4] = { -5.0f, -3.0f, 3.0f, 3.0f };
	textures[Bg1]->setExtents(0,-256*3,2048,512+256*3);//,65536);

	Sprite bg(backgroundVerts2, textures[Bg1]);
	static float ab1x = 0;//160;
	static float ab1y = 0;//240;
	if ( !message )
		ab1x -= accelerometerLocation.x / 500.0;
	bg.translate(ab1x, ab1y);
	bg.rotate(0.0 - accelerometerLocation.x/2.0);
	if ( !message )
		scale1 -= (accelerometerLocation.y*240 + 90) * (scale1 / 150000.0);
	bg.scale( scale1 );
	bg.draw();
	
	Sprite bg1(backgroundVerts, textures[Bg2]);
	static float ab2x = 0;//160;
	static float ab2y = 0;//240;
	if ( !message )
		ab2x -= accelerometerLocation.x / 100.0;
	ab2y = 144.0 / (scale2 * scale2 * 240.0);
	bg1.translate(ab2x, ab2y);
	bg1.rotate(0.0 - accelerometerLocation.x/2.0);
	if ( !message )
		scale2 -= (accelerometerLocation.y*240 + 90) * (scale2 / 50000.0);
	bg1.scale( scale2 );
	bg1.setAlpha( scale2 / 6.0 );
	bg1.draw();

	Sprite bg2(backgroundVerts, textures[Bg3]);
	bg2.translate(ab2x, ab2y);
	bg2.rotate(0.0 - accelerometerLocation.x/2.0);
	if ( !message )
		scale3 -= (accelerometerLocation.y*240.0 + 90.0) * (scale3 / 50000.0);
	bg2.scale( scale3 );
	bg2.setAlpha( scale3 / 6.0 );
	bg2.draw();

	/*
	 Sprite bg3(backgroundVerts, background, 3);
	 bg3.translate(ab3x, ab3y);
	 bg3.rotate((160.0 - spriteLocation.x) / 320.0);
	 //	scale -= (spriteLocation.y - 150.0) / 10000.0;
	 scale4 -= (spriteLocation.y - 150.0) * (scale4 / 50000.0);
	 bg3.scale( scale3 );
	 bg3.setFrame(2);
	 bg3.draw();
	 */

	float startupAlpha = 1.0;
	if ( frame > 18 && frame < 138 ) {
		int j = (frame - 18) % 60;
		startupAlpha = (abs(j-30)+5) / 35.0;
	}

	static float posX[6];
	static float posY[6];
	static float scale[6];

	for (int i = 0; i < 6; i++) {
		sprites[Smoke]->reset();
		sprites[Smoke]->scale(scale[i]);
		sprites[Smoke]->translate(posX[i],posY[i]);			
		sprites[Smoke]->setAlpha(float(i*5) * startupAlpha / 15.0);
		sprites[Smoke]->advance();
		posX[i] -= 0.0;
		posY[i] -= 0.07;
		scale[i] -= 0.02;
	}
	if ( frame % 4 == 0 ) {
		for (int i = 0; i < 6; i++) {
			posX[i] = posX[i+1];
			posY[i] = posY[i+1];
			scale[i] = scale[i+1];
		}
		posX[5] = accelerometerLocation.x + 0.16;
		posY[5] = accelerometerLocation.y + 1.08;
		scale[5] = 1.0;
	}
	
	if ( frame > 18 && frame < 138 ) {
		sprites[BodySprite]->setAlpha(startupAlpha);
		sprites[BootsSprite]->setAlpha(startupAlpha);
	}

	sprites[BodySprite]->reset();
	sprites[BodySprite]->translate(accelerometerLocation.x, accelerometerLocation.y);
	sprites[BodySprite]->advance(frame % 2);

	sprites[BootsSprite]->reset();
	sprites[BootsSprite]->translate(accelerometerLocation.x, accelerometerLocation.y);
	sprites[BootsSprite]->advance();

	sprites[StatusSprite]->draw();
	sprites[OptionsSprite]->draw();

	static float turnXY1X = -0.375;
	static float turnXY1Y = -1.166;
	static float turnXY2X = 0.403;
	static float turnXY2Y = 2.333;
	int x = frame % 32;
	if ( x < 24 ) {
		sprites[ArrowSprite]->reset();
		sprites[ArrowSprite]->translate(turnXY1X, turnXY1Y);
		sprites[ArrowSprite]->scale(0.8 + (x / 100.0));
		sprites[ArrowSprite]->translate(turnXY2X, turnXY2Y);
		sprites[ArrowSprite]->setAlpha(x / 30.0);
		sprites[ArrowSprite]->setFrame(frame);
		sprites[ArrowSprite]->draw();
	}

/*
	sprites[DuckSprit1 + (frame%32)/8]->setFrame(frame%8);
	sprites[DuckSprit1 + (frame%32)/8]->draw();
*/

	if ( frame > 18 && frame < 138 ) {
		int i = (frame - 18) / 30;
		int j = (frame - 18) % 30;
		if ( i < 3 ) {
			sprites[_321Sprite]->reset();
			sprites[_321Sprite]->scale(j*1.5 / 30.0);
			sprites[_321Sprite]->setFrame(i);
			sprites[_321Sprite]->draw();
		} else {
			sprites[GoSprite]->reset();
			sprites[GoSprite]->scale(j*1.5 / 30.0);
			sprites[GoSprite]->setFrame(i);
			sprites[GoSprite]->draw();
		}
	}

	if ( message )
		sprites[MsgBoxSprite]->draw();


	static int duckFrame = 0;
	duckFrame++;
	int duckSprite = (duckFrame * 1) % 34;
	if ( duckSprite == 31 )
		duckFrame = 0, duckSprite = 0;
//	if ( duckSprite < 2 )
//		duckFrame++, duckSprite++;
	int duckSpriteRow = duckSprite / 8;
	int duckSpriteLUT[5] = { DuckSprite1, DuckSprite2, DuckSprite3, DuckSprite4, DuckSprite5 };
	Sprite *duck = sprites[duckSpriteLUT[duckSpriteRow]];
	duck->reset();
	duck->scale(0.75,0.75);
	duck->scale(3.0);
	if ( duckSprite < 7 )
		duck->scale(0.93 + duckSprite * 0.01);

	if ( duckSprite < 10 ) {
//		duck->translate(0.0, -0.035 + duckSprite * 0.005);
		duck->translate(0.0, -0.10 + duckSprite * 0.01);
//		duck->translate(0.0, -0.035 + duckSprite * 0.005);
	}

//	duck->translate(0.0, 0.0 - (17 - duckSprite) * 0.005);

//	duck->rotate( (duckSprite - 17) / (17.0 / 3.14) );
//	duck->translate(1.3, -2.3);
	duck->translate(0, -0.6);

//		duckSprite = 3;
	duck->setFrame(duckSprite % 8);
	duck->draw();


//	sprites[DuckSpriteX]->reset();
//	sprites[DuckSpriteX]->setFrame(frame);//duckSprite % 8);
//	sprites[DuckSpriteX]->draw();

/*
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrthof(0, 319, 459, 0, -1, 1);
	glMatrixMode(GL_MODELVIEW);
	sprites[Load0]->draw();
*/
}


void Context::mouseDown(int x, int y)
{
	sounds[BassSlap]->play();

	/*	
	 //Play start sound
	 SoundEngine_SetEffectPosition(_sounds[kSound_Failure], 2.0 * (_position.x / bounds.size.width) - 1.0, 0.0, 0.0);
	 SoundEngine_StartEffect(_sounds[kSound_Start]);
	 SoundEngine_StartEffect(_sounds[kSound_Failure]);	 
	 SoundEngine_StopEffect(_sounds[kSound_Thrust], false);
	 SoundEngine_Vibrate();
	*/

	if ( y > 64 && y < 400 ) {
		if ( message ) {
			message = false;
		} else {
			accelerometerLocation.x = (x - 160.0) / 160.0;
			accelerometerLocation.y = ((y*2+50) - 240.0) / 240.0;
		}
	} else {
		message = true;
	}
}


void Context::mouseMove(int x, int y)
{	
	if ( y > 64 && y < 400 )
		if ( !message ) {
			accelerometerLocation.x = (x - 160.0) / 160.0;
			accelerometerLocation.y = ((y*2+50) - 240.0) / 240.0;
		}	
}


void Context::mouseUp(int x, int y)
{
	if ( y > 64 && y < 400 )
		if ( !message ) {
			accelerometerLocation.x = (x - 160.0) / 160.0;
			accelerometerLocation.y = ((y*2+50) - 240.0) / 240.0;
		}
}

