/****************************************************************
 * Copyright (C) 2002  Joel Muzzerall
 *
 * 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.
 ******************************************************************/

/***********************************************
 * The paddle definitions are here, of course.
 * Not terrably much to say.
 ***********************************************/

#include <allegro.h>
#include "Ball.h"
#include "Paddle.h"
#include <math.h>

/****************************************************
 * The constructor creates a new, mediumsized paddle
 * and initializes the bitmaps of paddles if they
 * have not been
 ****************************************************/
Paddle::Paddle()
{
	if (Paddle_Init == 0)
		paddleInit();

	itsSize = 2;
	itsPos = SCN_WIDTH / 2;
}

/******************************************************
 * Draws the paddle to the screen based on the size
 * of it and the X coords of the mouse.  If the mouse
 * is too far too the right, it will...  'Adjust' it
 ******************************************************/
void Paddle::draw(BITMAP *buf)
{
	updatePosition();   
	masked_blit(paddlePics[itsSize], buf, 0, 0, itsPos, SCN_HEIGHT - 15, 40 + itsSize*20, 10);
}

/*******************************************************************************
 * Keeps the mouse pointer in the middle window so that it can't leave and do
 * weird stuff.  Also, updates the position of the paddle depending on how the
 * mouse has been moved since the last call to this method.
 ******************************************************************************/
void Paddle::updatePosition()
{
	int movement, throwaway;
	get_mouse_mickeys(&movement, &throwaway);
	itsPos = itsPos + movement;
	if (key[KEY_LEFT])
		itsPos = itsPos - PADDLE_SPEED;
	if (key[KEY_RIGHT])
		itsPos = itsPos + PADDLE_SPEED;
	if (itsPos < 0)
		itsPos = 0;
	if (itsPos > SCN_WIDTH - (40 + itsSize * 20))
		itsPos = SCN_WIDTH - (40 + itsSize * 20);

	position_mouse(SCN_WIDTH / 2, SCN_HEIGHT / 2);
}

/*********************************************************
 * The rebound uses an algorithm that has NOTHING to do
 * with a physics model to reflect the ball that is passed
 * to it.
 *********************************************************/
int Paddle::rebound(Ball *foo, int Speed)
{
	if (foo->x + 10 < itsPos || foo->x > (itsPos + 40 + itsSize*20))
		return 0;

	// Equations to find the new velocities of the ball after being
	// bounced off the padde.  Good luck dissecting this one.
	if (foo->yv > 0){
		double ballCPos = foo->x + 5;
		int sideWidth = 20 + 10*itsSize;
		int midPaddle = itsPos + sideWidth;
		int xMod = (ballCPos < midPaddle) ? -1 : 1;

		double ballPos = (ballCPos - midPaddle) * xMod;
		int angleS = (int)(((double)ballPos / (double)sideWidth) * 6);
		if (angleS > 6) angleS = 6;
		if (angleS < 0) angleS = 0;
		int angle = (7 - angleS) * 15 - 10;
		if (angle == 5) angle = 10;
		foo->yv = Speed * -(sin((double)(angle / 57.3)));
		foo->xv = Speed * xMod * (cos((double)(angle / 57.3)) + .2);
		return 1;
	}
	return 0;
}


/******************************************************
 * paddleInit loads the bitmaps for the paddles,
 * and also sets the range of the mouse
 ******************************************************/
void Paddle::paddleInit()
{
	Paddle_Init = 1;
	char filestring[128];

	// Load the graphic for each size of paddle
	for (int i = 0; i <= MAX_PADDLE_SIZE; i++){
		sprintf(filestring, "gfx/default/sprites/paddle_%d.bmp", i);
		paddlePics[i] = load_bitmap(filestring, NULL);
		if (paddlePics[i] == NULL){
			allegro_message("Could not load a paddle graphic.");
			allegro_exit();
		}
	}
}

/***********************************************
 * Grow and shrink methods change the size of
 * the paddle
 ***********************************************/
void Paddle::grow()
{
	itsSize++;
	if (itsSize > MAX_PADDLE_SIZE)
		itsSize = MAX_PADDLE_SIZE;
}

void Paddle::shrink()
{
	itsSize--;
	if (itsSize < 0)
		itsSize = 0;
}
