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

#include "Debug.h"
#include <math.h>
#include <OpenGLES/ES1/gl.h>
#include <OpenGLES/ES1/glext.h>
#include "Sprite.h"
#include "PointArray.h"


class SpritePrivate
{
public:
	PointArray initVerts;
	PointArray vertices;
	float alpha;
	int frame, frameCount;
	Texture *frames;
	int x, y, x1, y1, w, h, xAdv, yAdv;
};


Sprite::Sprite(const float verts[4], Texture *tex, int _x, int _y, int _w, int _h, int _xAdv, int _yAdv, int _frames)
{
	SpritePrivate *d = new SpritePrivate;
	dptr = (void *)d;

	d->alpha = 1.0f;
	d->frame = 0;
	d->frames = tex;

	d->initVerts += PointF(verts[0], verts[1]);
	d->initVerts += PointF(verts[2], verts[1]);
	d->initVerts += PointF(verts[0], verts[3]);
	d->initVerts += PointF(verts[2], verts[3]);
	reset();

	d->x1 = d->x = _x;
	d->y1 = d->y = _y;
	d->w = _w;
	d->h = _h;
	d->xAdv = _xAdv;
	d->yAdv = _yAdv;
	d->frameCount = _frames;
	if ( _frames != -1 )
		setTextureRect(_x, _y, _w, _h);
}


Sprite::~Sprite()
{
	delete (SpritePrivate *)dptr;
}


void Sprite::reset()
{
	SpritePrivate *d = (SpritePrivate *)dptr;
	d->vertices = d->initVerts;
}


void Sprite::translate(float x, float y)
{
	((SpritePrivate *)dptr)->vertices.translate(x, y);
}


void Sprite::rotate(float r)
{
	((SpritePrivate *)dptr)->vertices.rotate(r);
/*
	SpritePrivate *d = (SpritePrivate *)dptr;
	float s = ::sin(r);
	float c = ::cos(r);
	for (int i = 0; i < 4; i++) {
		float x = d->vertices[i].x;
		float y = d->vertices[i].y;
		d->vertices[i].x = (x * c) - (y * s);
		d->vertices[i].y = (x * s) + (y * c);
	}
*/
/*
	for (int i = 0; i < 4; i++)
		d->vertices[i].rotate(r);
 */
}


void Sprite::scale(float s)
{
	((SpritePrivate *)dptr)->vertices.scale(s, s);
/*
	SpritePrivate *d = (SpritePrivate *)dptr;
	for (int i = 0; i < 4; i++)
		d->vertices[i].scale(s);
*/
}


void Sprite::scale(float x, float y)
{
	((SpritePrivate *)dptr)->vertices.scale(x, y);
}


void Sprite::advance(int f)
{
	SpritePrivate *d = (SpritePrivate *)dptr;
	setFrame(d->frame + f);
	draw();
}


void Sprite::setFrame(int f)
{
	SpritePrivate *d = (SpritePrivate *)dptr;
	d->frame = f;
	if ( d->frameCount != -1 ) {
		d->x = d->x1 + (d->frame % d->frameCount) * d->xAdv;
		d->y = d->y1 + (d->frame % d->frameCount) * d->yAdv;
	}
}


void Sprite::setAlpha(float a)
{
	SpritePrivate *d = (SpritePrivate *)dptr;
	d->alpha = a;
}


void Sprite::setTextureRect(int x, int y, int w, int h)
{
	SpritePrivate *d = (SpritePrivate *)dptr;
	if (d->frames)
		d->frames->setExtents(x, y, w, h);
}


void Sprite::draw()
{
	SpritePrivate *d = (SpritePrivate *)dptr;
	if (d->frames)
		d->frames->bind();

	setTextureRect(d->x, d->y, d->w, d->h);

	float alpha = d->alpha;
	if ( alpha != 1.0f ) {
		glColor4f(alpha, alpha, alpha, alpha);
		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
		glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); // GL_ADD);
		//		GLfloat blendColor[4] = {0.0, 0.0, 0.0, 0.0};//alpha};
		//		glColor4f(1.0, 1.0, 1.0, 0.5);//alpha);
		//		glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, blendColor);
		//		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ALPHA);
		//		glTexEnvf(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
		//		glTexEnvf(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE);
		//		glTexEnvf(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE);
		//		glTexEnvf(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
		//		glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_ALPHA);
		//		glTexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1.0);
		//		glTexEnvf(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_CONSTANT);
	} else {
//		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
		glColor4f(alpha, alpha, alpha, alpha);
		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
		glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); // GL_ADD);
	}

    glVertexPointer(2, GL_FLOAT, 0, (float *)(const PointF *)d->vertices);

	glEnableClientState(GL_VERTEX_ARRAY);
	//	glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
	glBlendFunc(GL_ONE, GL_ALPHA);
	glEnable(GL_BLEND);
	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

