/***************************************************************************
 *   Copyright (C) 2004-2005 by                                            *
 *     Paolo Sacconier   <axa1981@tin.it>                                  *
 *     Francesco Tamagni <minchiahead@hacari.org>                          *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "simpleball.h"

namespace gillo {

const sgVec4 SimpleBall::p1[3] = { {0.3, 0.0, 0.0, 1.0}, {1.0, 0.0, 0.0, 1.0}, {1.0, 0.4, 0.4, 1.0} };
const sgVec4 SimpleBall::ne[3] = { {0.0, 0.0, 0.0, 1}, {0.6, 0.6, 0.6, 1}, {1.0, 1.0, 1.0, 1} };
const sgVec4 SimpleBall::p2[3] = { {0.0, 0.0, 0.3, 1}, {0.0, 0.0, 1.0, 1}, {0.4, 0.4, 1.0, 1} };

SimpleBall::SimpleBall(Context& c)
: Entity(c), ballEffectPtr(NULL), possessionIncrement(0), targetSize(2*radius), currentSize(2*radius)
{
	this->state = this->context.getState(STA_BALL);
	this->Init("SimpleBall");
}

SimpleBall::SimpleBall(Context& c, float size, ssgSimpleState* state)
: Entity(c), ballEffectPtr(NULL), possessionIncrement(0), targetSize(size), currentSize(2*radius)
{
	this->state = state;
	this->Init("SimpleOddBall");
	this->charge = 25;
}

ssgEntity* SimpleBall::createEffect(char* s, int stateId)
{
	sgVec3 center = { 0, 0, 0};
	sgVec3 dim = { 1.0, 0, 1.0 };
	ssgEntity* e = this->context.searchInPool(s);
	if (e == NULL) {
		ssgaCube * e_obj =  new ssgaCube     () ;
		e_obj -> setSize          ( dim ) ;
		e_obj -> setCenter        ( center ) ;
		e_obj -> setKidState      ( this->context.getState(stateId) ) ;
		e_obj -> regenerate       () ;
		e_obj->setName(s);
		e = (ssgEntity*) e_obj;
		this->context.addToPool(e);
	}
	
	return e;
}

void SimpleBall::Init(char* s) {
	sgVec3 center = { 0, 0, 0};
	type = BALL;
	bid = dBodyCreate(this->context.getWid());
	gid = dCreateSphere (this->context.getSid(), radius);
	Entity::Init();
	
	ssgEntity* e = this->context.searchInPool(s);
	if (e == NULL) {
		ssgaSphere* e_obj =  new ssgaSphere     () ;
		e_obj -> setSize          ( 2*radius ) ;
		e_obj -> setCenter        ( center ) ;
		e_obj -> setKidState      ( state ) ;
		e_obj -> regenerate       () ;
		e_obj -> setName          (s) ;
		e = (ssgEntity*) e_obj;
		this->context.addToPool(e);
	}
	trans.addKid( e );
	
// 	this->fire_obj =  new ssgaFire ( 200 ) ;
// 	ssgTransform* t = new ssgTransform();
// 	t->addKid(fire_obj);
// 	this->context.getAlphaScenePtr()->addKid(t);

	dMassSetSphereTotal(&mass, weight, radius);
	dBodySetMass(bid, &mass);
	dBodySetPosition(bid, 0, 0, 0);
	
	this->setScore(0.0);
}

void SimpleBall::update(float dt)
{
	Entity::update(dt);
	Entity::odeTrans2ssgTrans(this->bid, this->trans);
// 	fire_obj -> update ( dt ) ;

	static float i = 0;
	sgMat4 scalm;

	if (ballEffectPtr != NULL) {
		i += 10*dt;
		float ci = (0.3*cos(i)+1.0)*2*currentSize;
		Entity::transform((ssgTransform*) (this->ballEffectPtr)->getKid(0), 0, ci);
		sgMat4 xform;
		trans.getTransform(xform);
		alphaTrans.setTransform(xform);
	}
	this->setScore(score +this->possessionIncrement*dt);
	this->possessionIncrement = this->score > 0 ? -0.005 : 0.005;
	
	if (this->currentSize != this->targetSize) {
		this->currentSize += (this->targetSize - this->currentSize) * dt;
		((ssgaSphere*)trans.getKid(0)) -> setSize(this->currentSize);
		dGeomSphereSetRadius (gid, this->currentSize/2.0);
	}
}

void SimpleBall::setSize(float size) {
	if (size)
		this->targetSize = size;
	else
		this->targetSize = 2*radius;
}


void SimpleBall::setScore(float s)
{
	float abss = sgAbs(s);
	if (abss >= 1) {
		this->score = s > 0 ? 1 : -1;
		abss = 1;
		if (this->ballEffectPtr == NULL) {
			ssgTransform* tr = new ssgTransform();
			if (s > 0)
				tr->addKid(createEffect("SimpleBallEffectRed", STA_BALLEFFECT_RED));
			else
				tr->addKid(createEffect("SimpleBallEffectBlue", STA_BALLEFFECT_BLUE));
			this->ballEffectPtr = new ssgCutout(true);
			this->ballEffectPtr->addKid(tr);
			alphaTrans.addKid(this->ballEffectPtr);
			this->update(0);
		}
	} else {
		this->score = s;
		if (this->ballEffectPtr != NULL) {
			alphaTrans.removeKid(this->ballEffectPtr);
			this->ballEffectPtr = NULL;
		}
	}

// 	printf("possession %f(%f %f) of ball %s\n", this->score, s, abss, this->toString());
			
	sgVec4 color[3];
	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 4; j++)
			color[i][j] = abss*(this->score > 0 ? p1[i][j] : p2[i][j]) +(1 -abss)*ne[i][j];

	state -> setMaterial       ( GL_EMISSION, color[0] ) ;
	state -> setMaterial       ( GL_DIFFUSE , color[1] ) ;
	state -> setMaterial       ( GL_SPECULAR, color[2] ) ;
}

};
