/* 
    This file handles those balls that devide when they smack into other ones

    Copyright, 2003 Caleb Moore
    
    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 "splitball.h"
#include "graphics.h"
#include "game.h"
#include <cmath>
#include <iostream>
using namespace std;

static unsigned int splitballbmp;
static bool splitballbmpassigned;

unsigned int splitball::getradius()
{
  if (level == 4)
    return 15;
  if (level == 3)
    return 15;
  if (level == 2)
    return 15;
  return 5;
}

float splitball::getmass()
{
  if (level == 4)
    return 1;
  if (level == 3)
    return 0.666667;
  if (level == 2)
    return 0.5;
  return 0.25;
}

void splitball::specialcollide(ball * other)
{
  if (react(other))
    other->specialcollideb(package);
}

void splitball::specialcollideb(ball * other)
{
  react(other);
}

int splitball::react(ball * other)
{
  splitball * splitother;
  if ((splitother = dynamic_cast<splitball *>(other->data)))
    {
      floatpoint temppoint;
      floatpoint tempvel;
      splitball * tempball;
      ball * tempholder;
      if (level + splitother->level < 5)
	{
	  tempholder = new ball('s');
	  if ((tempball = (dynamic_cast<splitball *>(tempholder->data))))
	    {
	      tempball->package = tempholder;
	      tempball->level = level + splitother->level;
	      temppoint = (getcenter() * level + 
			   other->getcenter() * splitother->level)
		* (1.0 / float(level + splitother->level));
	      tempvel = (getvelocity() * level + 
			 other->getvelocity() * splitother->level)
		* (1.0 / float(level + splitother->level));; 
	      tempholder->setboundary(boundary);
	      tempholder->setcenter(temppoint);
	      tempholder->setvelocity(tempvel);
	      
	      addball(*tempholder);
	      
	      eraseball(other->getserial());
	      eraseball(package->getserial());
	    }
	}
      return 0;
    }
  
  if (level == 4)
    {
      clone(4, 12);
      eraseball(package->getserial());
      return 1;
    }
  if (level == 3)
    {
      clone(3, 12);
      eraseball(package->getserial());
      return 1;
    }
  if (level == 2)
    {
      clone(2, 10);
      eraseball(package->getserial());
      return 1;
    }
  other->specialcollideb(package);
  return 1;
}

splitball::splitball(ball * pack)
{
  package = pack;
  level = 4;
}

void splitball::clone(int number, float radius)
{
  floatpoint temppoint;
  floatpoint tempvel;
  splitball * tempball;
  ball * tempholder;

  float distance = 6.2830 / float(number);


  for (int i = 0; i < number; i++)
    {
      tempholder = new ball('s');
      if ((tempball = dynamic_cast<splitball *>(tempholder->data)))
	{
	  tempball->package = tempholder;
	  tempball->level = 1;

	  temppoint.polar(radius, i * distance);
	  temppoint = temppoint + center;
	  tempvel.polar(1, i * distance);
	  tempvel = tempvel + getvelocity();
	  tempholder->setcenter(temppoint);	  
	  tempball->velocity = (tempvel);
	  tempholder->setboundary(boundary);
	  addball(*tempholder);
	}
    }
}

void splitball::display()
{
  if (splitballbmpassigned == 0)
    {
      splitballbmp = load_bmps("splitball",1,4);
      splitballbmpassigned = 1;
    }


  int pic;
  pic = splitballbmp + 4 - int(level);

  display_bmp(pic, int(center.x) - bmp_size(pic).x / 2,
	      int (center.y) - bmp_size(pic).y / 2); 
}

ball_base * splitball::duplicate(ball * pack)
{
  splitball * output = new splitball(pack);

  output->level = level;
  output->center = center;
  output->velocity = velocity;
  output->boundary = boundary;

  return output;
}

