/**
 * @author Richard Eric M. Lope (Relminator)
 * http://rel.phatcode.net
 *
 */

package net.phatcode.rel.gameframework;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import net.phatcode.rel.assets.ImageTextureDataBullets;
import net.phatcode.rel.assets.ImageTextureDataDigiFont;
import net.phatcode.rel.assets.ImageTextureDataGlowImages;
import net.phatcode.rel.math.Utils;
import net.phatcode.rel.math.Vector2D;
import net.phatcode.rel.utils.ImageAtlas;
import net.phatcode.rel.utils.SpriteBatcher;
import net.phatcode.rel.utils.SpriteFont;
import net.phatcode.rel.utils.SpriteGL;
import android.content.Context;
import android.opengl.GLSurfaceView.Renderer;
import android.util.FloatMath;

public class RendererGL implements Renderer
{
	private final int SCREEN_WIDTH = 320;
	private final int SCREEN_HEIGHT = 480;
	private int frame;
	private Context 	context;
	private SpriteBatcher spriteBatchGlow = new SpriteBatcher(1024);
	private SpriteBatcher spriteBatchBullets = new SpriteBatcher(1024);
	private ImageAtlas glowImages;
	private ImageAtlas digiImages;
	private ImageAtlas bulletImages;
	private SpriteFont digiFont;
	private long oldTime;
	private long currentTime;
	private long FPS = 0;
	private long fpsFrames = 0;
	
	private int counter;
	private BulletFactory bullets = new BulletFactory(1020);
	private Animator animator1 = new Animator(19,3);
	private Animator animator2 = new Animator(54,3);
	
	
	private Vector2D pos1 = new Vector2D();
	private Vector2D pos2 = new Vector2D();
	private Vector2D pos3 = new Vector2D();
	private Vector2D pos4 = new Vector2D();
	private Vector2D gravity = new Vector2D();
	private Vector2D target = new Vector2D();
	private Behavior behavior = new BehaviorLinear(); 			// default behavior
	private Behavior nextBehavior = new BehaviorLinear(); 		// behavior after stopping
	
	
	
	public RendererGL(Context context) 
	{
		this.context = context;
		
		glowImages = new ImageAtlas();
		digiImages = new ImageAtlas();
		bulletImages = new ImageAtlas();
		digiFont = new SpriteFont();
		
	}

	@Override
	public void onDrawFrame( GL10 gl ) 
	{
		frame++;
		update();
		
		gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

		gl.glMatrixMode(GL10.GL_MODELVIEW);
		gl.glLoadIdentity();
		gl.glTranslatef( 0.375f, 0.375f, 0 );	// magic trick
		
		spriteBatchGlow.spriteOnLine( 30, 40, 
									  32 + Math.abs(FloatMath.sin(frame/30.0f)) * 120,
									  40,
									  30, 1, 1, 1, 1, glowImages.getSprite(3) );
		
		for( int i = 0; i < 5; i++ )
		{
			spriteBatchGlow.spriteOnLine( 30 + i * 50, 
										  460, 
										  30 + i * 50,
										  460 - (32 + Math.abs(FloatMath.sin(frame/(i * 10.0f))) * 120),
										  30, 1, 1, 1, 1, glowImages.getSprite(7) );
		}
		spriteBatchGlow.sprite(200, 100, SpriteGL.FLIP_NONE, glowImages.getSprite(6) );
		spriteBatchGlow.spriteStretch( 0, 100, 
									  32 + Math.abs(FloatMath.sin(frame/35.0f)) * 220,
									  32 + Math.abs(FloatMath.sin(frame/40.0f)) * 220,
									   1, 1, 1, 1, glowImages.getSprite(2) );
		
		for( int i = frame; i < (360+frame); i += 10 )
		{
			float px =  (float)(FloatMath.sin(frame/30.0f)  * 220 * FloatMath.cos( (i * (float)Math.PI) / 180.0f ));
			float py =  (float)(FloatMath.sin(frame/80.0f)  * 120 * FloatMath.sin( (i * (float)Math.PI) / 180.0f ));
			float px2 = (float)(FloatMath.sin(frame/130.0f)  * 170 * FloatMath.cos( ( (i+20) * (float)Math.PI ) / 180.0f ));
			float py2 =  (float)(FloatMath.sin(frame/40.0f)  * 160 * FloatMath.sin( ( (i+20) * (float)Math.PI ) / 180.0f ));
			float adder = (float)(Math.abs( 1 * FloatMath.sin( frame/ 20.0f) ));
			int j;
			for( j = 0; j < (1 + adder); j++ )
			{
				spriteBatchGlow.spriteOnLine( SCREEN_WIDTH/2 + px, SCREEN_HEIGHT/2 + py,
											  SCREEN_WIDTH/2 + px2, SCREEN_HEIGHT/2 + py2,
											  25-(adder*2),
											  (float)(Math.abs(FloatMath.sin(frame * 0.1f))), 
											  (float)(Math.abs(FloatMath.sin(frame * 0.2f))), 
											  (float)(Math.abs(FloatMath.sin(frame * 0.3f))), 
											  1f, 
											  glowImages.getSprite(0) );				
			}
		}
		
		
		
		bullets.renderBullets( spriteBatchBullets, bulletImages );
		
		digiFont.print(10,0,"RELMINATOR" );
		digiFont.print(10,20,"FPS = " + FPS );
		digiFont.print(10,40,"SPRITES = " + ( spriteBatchBullets.getNumSprites() + spriteBatchGlow.getNumSprites() + digiFont.getNumSprites() ) );
		digiFont.printCenter(0, Constants.SCREEN_HEIGHT - 30, Constants.SCREEN_WIDTH, "REL.PHATCODE.NET");
		digiFont.printCenter(0, Constants.SCREEN_HEIGHT - 80, Constants.SCREEN_WIDTH, "RICHARD ERIC M. LOPE");
		
		fpsFrames++;
		currentTime = System.nanoTime();
		if( currentTime - oldTime >= 1000000000 )
		{
			FPS = (fpsFrames * 1000000000)/(currentTime - oldTime);
			oldTime = currentTime;
			fpsFrames = 0;
		}
		
		
		
		gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
		spriteBatchBullets.render( gl, bulletImages.getTextureID() );
		
		gl.glBlendFunc( GL10.GL_ONE, GL10.GL_ONE );	
		spriteBatchGlow.render( gl, glowImages.getTextureID() );
		
		
		gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
		digiFont.render(gl);
		
		
		
	}

	@Override
	public void onSurfaceChanged(GL10 gl, int width, int height) 
	{
		if(height == 0) 
		{ 						
			height = 1;
		}

		gl.glViewport(0, 0, width, height); 	
		gl.glMatrixMode(GL10.GL_PROJECTION); 	
		gl.glLoadIdentity(); 					
		gl.glOrthof( 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 1, -1 );
		
		gl.glMatrixMode(GL10.GL_MODELVIEW); 	
		gl.glLoadIdentity(); 					
	}

	@Override
	public void onSurfaceCreated(GL10 gl, EGLConfig config) 
	{
		glowImages.loadTexture( gl, this.context, R.drawable.glow_sprites,
						     	new ImageTextureDataGlowImages(),
						     	32,
						     	32,
						     	GL10.GL_LINEAR );

		bulletImages.loadTexture( gl, this.context, R.drawable.bullet_sprites,
				  				  new ImageTextureDataBullets(), 
				  				  GL10.GL_LINEAR );


		digiImages.loadTexture( gl, this.context, R.drawable.font_tiles,
			    				new ImageTextureDataDigiFont(),
			    				16,
			    				16,
			    				GL10.GL_LINEAR );

		digiFont.loadAtlas( digiImages );
		
		gl.glEnable(GL10.GL_TEXTURE_2D);			
		gl.glShadeModel(GL10.GL_SMOOTH); 			
		gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 	
		gl.glClearDepthf(1.0f); 					
		gl.glDisable(GL10.GL_DEPTH_TEST); 			
		gl.glDepthFunc(GL10.GL_LEQUAL); 			
		//gl.glEnable(GL10.GL_ALPHA_TEST);
		//gl.glAlphaFunc(GL10.GL_GREATER, 0);
		gl.glEnable(GL10.GL_BLEND);			
		
		gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); 
		
	}
	
	public void update()
	{
		
		
		
		counter++;
		if( (counter & 1) == 0 )
		{
			
			float x = (FloatMath.cos(counter * 0.025f) + FloatMath.sin(counter * 0.075f)) * 100f;
			float y = (FloatMath.sin(counter * 0.015f) + FloatMath.sin(counter * 0.045f)) * 150f;
					 
			pos1.set( Constants.SCREEN_WIDTH/2.0f + x,
				      Constants.SCREEN_HEIGHT/2.0f + y );
			
			pos2.set( Constants.SCREEN_WIDTH/2.0f - x,
				      Constants.SCREEN_HEIGHT/2.0f - y );
			
			pos3.set( Constants.SCREEN_WIDTH/2.0f - x,
				      Constants.SCREEN_HEIGHT/2.0f + y );
			
			pos4.set( Constants.SCREEN_WIDTH/2.0f + x,
				      Constants.SCREEN_HEIGHT/2.0f - y );
			
			
			float angle = counter * Utils.DEG_TO_RAD;
			float speed = 2;
			
			bullets.spawnSpread( pos1,
							 	 gravity,
							 	 target,
								 angle, 
								 0, 
								 0.1f, 
								 -1,
								 -1,
								 false,
								 false,
								 animator1, 
								 Behaviors.behaviorAccelerated, 
								 nextBehavior, 
								 10, 
								 4, 
								 10, 
								 10  );

			bullets.spawnSpread( pos2,
							 	 gravity,
							 	 target,
								 -angle, 
								 speed, 
								 0, 
								 -1,
								 -1,
								 false,
								 false,
								 animator2, 
								 behavior, 
								 nextBehavior, 
								 10, 
								 4, 
								 10, 
								 10  );

			
			bullets.spawnSpread( pos3,
							 	 gravity,
							 	 target,
								 -angle, 
								 0, 
								 0.1f, 
								 -1,
								 -1,
								 false,
								 false,
								 animator1, 
								 Behaviors.behaviorAccelerated, 
								 nextBehavior, 
								 10, 
								 4, 
								 10, 
								 10  );

			bullets.spawnSpread( pos4,
							 	 gravity,
							 	 target,
								 angle, 
								 speed, 
								 0, 
								 -1,
								 -1,
								 false,
								 false,
								 animator2, 
								 behavior, 
								 nextBehavior, 
								 10, 
								 4, 
								 10, 
								 10  );

			
		}
		
		bullets.updateBullets(pos1);
		
			
	}
	
	
}
