// Jason Brillante "Damdoshi"
// Hanged Bunny Studio 2014-2015
//
// KoBang!

#include		<stdio.h>
#include		<math.h>
#include		<string.h>
#include		<iostream>
#include		"kobang.hpp"

static double		_cos(double			deg,
			     double			coef,
			     double			off)
{
  return (cosf((deg + off) * (M_PI / 180.0)) * coef);
}

static double		_sin(double			deg,
			     double			coef,
			     double			off)
{
  return (sinf((deg + off) * (M_PI / 180.0)) * coef);
}

typedef double		(*trigoptr)(double		deg,
				    double		coef,
				    double		off);

static double		project(trigoptr		ptr,
				double			norm,
				double			angle,
				double			size,
				double			coef,
				double			off)
{
  return (ptr(angle, coef, off) * norm + size / 2);
}

static void		line(sf::RenderWindow		&win,
			     Point			&p0,
			     Point			&p1,
			     double			coefx,
			     double			coefy,
			     double			angle)
{
  sf::Vertex		line[2] =
    {
      sf::Vertex
      (sf::Vector2f
       (project(_cos, 1.8 * p0.n, p0.a, win.getSize().x, coefx, angle),
	project(_sin, p0.n, p0.a, win.getSize().y, coefy, angle)),
       p0.c),
      sf::Vertex
      (sf::Vector2f
       (project(_cos, 1.8 * p1.n, p1.a, win.getSize().x, coefx, angle),
	project(_sin, p1.n, p1.a, win.getSize().y, coefy, angle)),
       p1.c)
    };

  win.draw(line, 2, sf::Lines);
}

static void		random_color(sf::Color		&col)
{
  col.r = rand();
  col.g = rand();
  col.b = rand();
}

static void		set_color(sf::Color		&col,
				  unsigned char		r,
				  unsigned char		g,
				  unsigned char		b)
{
  col.r = r;
  col.g = g;
  col.b = b;
}

void			kobang::display_struct(Point	&p0,
					       Point	&p1,
					       Point	&p2,
					       Point	&p3,
					       int	cline)
{
  double		coef_norm0;
  double		coef_norm1;
  double		i;

  coef_norm0 = (p1.n - p0.n) / deepness;
  coef_norm1 = (p3.n - p2.n) / deepness;
  for (i = 0; i <= deepness; ++i)
    if (i == 0 || i == deepness || currentdiscotype(i))
      {
	Point		np0;
	Point		np1;

	np0.n = i * coef_norm0 + p0.n;
	np0.a = p0.a;
	if (randomize)
	  random_color(np0.c);
	else
	  set_color(np0.c, rcolor, gcolor, bcolor);
	np0.c.a = 255;

	np1.n = i * coef_norm1 + p2.n;
	np1.a = p2.a;
	if (randomize)
	  random_color(np1.c);
	else
	  set_color(np1.c, rcolor, gcolor, bcolor);
	np1.c.a = 255;

	line(win, np0, np1, coefx, coefy, angle);

	if (cline == heropos)
	  {
	    np0.a -= (360.0 / width) / 2.0;
	    np1.a -= (360.0 / width) / 2.0;
	    np0.c = sf::Color(255, 255, 255, i / deepness * 255);
	    np1.c = sf::Color(255, 255, 255, i / deepness * 255);
	    line(win, np0, np1, coefx, coefy, angle);
	    if (i == deepness)
	      {
		double	c;
		int	j;

		c =  cos(color_var * M_PI / 180.0) * 80 + 128;
		for (j = 0; j < 3; ++j)
		  {
		    np0.n += rand() % 10 - 5;
		    np1.n += rand() % 10 - 5;
		    np0.c = sf::Color(255, 255, 255, c);
		    np1.c = sf::Color(255, 255, 255, c);
		    line(win, np0, np1, coefx, coefy, angle);
		  }
	      }
	  }
      }
}

void			kobang::display_map(void)
{
  double		coef_norm;
  double		coef_angle;
  int			i;

  coef_norm = 40.0 / width;
  coef_angle = 360.0 / width;
  for (i = 0; i < width; ++i)
    {
      Point		p0;
      Point		p1;
      Point		p2;
      Point		p3;

      p0.n = eye_size;
      p0.a = i * coef_angle;
      if (randomize)
	random_color(p0.c);
      else
	set_color(p0.c, rcolor, gcolor, bcolor);
      p0.c.a = 32;

      p1.n = depth[(int)(i * coef_norm) % 40] * 10;
      p1.a = i * coef_angle;
      if (randomize)
	random_color(p1.c);
      else
	set_color(p0.c, rcolor, gcolor, bcolor);
      p1.c.a = 255;

      line(win, p0, p1, coefx, coefy, angle);

      p2.n = eye_size;
      p2.a = (i + 1) * coef_angle;
      p3.n = depth[(int)((i + 1) * coef_norm) % 40] * 10;
      p3.a = (i + 1) * coef_angle;
      display_struct(p0, p1, p2, p3, i);
    }
}

void			kobang::display_bomber(void)
{
  sf::CircleShape	shape;
  double		coef_angle;
  sf::Vector2f		pos;

  coef_angle = 360.0 / width;
  shape.setRadius(10);
  shape.setOutlineThickness(1);
  shape.setOutlineColor(sf::Color(255, 0, 0));
  shape.setFillColor(sf::Color(0, 0, 0, 0));
  pos.x = project(_cos, 1.8 * eye_size, coef_angle * bomberpos, win.getSize().x, coefx, angle) - 10;
  pos.y = project(_sin, eye_size, coef_angle * bomberpos, win.getSize().y, coefy, angle) - 10;
  shape.setPosition(pos);
  win.draw(shape);
}

void			kobang::display_bomb(void)
{
  std::list<sf::Vector2f>::iterator	it;
  double		coef_angle;
  double		coef_norm;
  Point			p2;
  Point			p3;

  coef_angle = 360.0 / width;
  coef_norm = 40.0 / width;
  for (it = bombs.begin(); it != bombs.end(); ++it)
    {
      /// x is norm, y is angle
      sf::Vector2f	&bomb = *it;
      sf::CircleShape	shape;
      double		coef_final_norm;
      sf::Vector2f	pos;

      shape.setRadius(5);
      shape.setOutlineThickness(1);
      shape.setOutlineColor(sf::Color(220 + cos(color_var * M_PI / 180.0) * 30, 0, 0));
      shape.setFillColor(sf::Color(0, 0, 0, 0));

      p2.n = eye_size;
      p3.n = depth[(int)(bomb.y * coef_norm) % 40] * 10.0;
      p2.a = bomb.y * coef_angle;
      coef_final_norm = (p3.n - p2.n) / deepness;
      pos.x = project(_cos, 1.8 * bomb.x * coef_final_norm + p2.n, p2.a, win.getSize().x, coefx, angle) - 5;
      pos.y = project(_sin,       bomb.x * coef_final_norm + p2.n, p2.a, win.getSize().y, coefy, angle) - 5;

      shape.setPosition(pos);
      win.draw(shape);
    }
}

void			kobang::display_stats(void)
{
  char			buffer[128];

  snprintf(&buffer[0], sizeof(buffer), "score %d", heroscore);
  write(&buffer[0], 10, 10, sf::Color::White);

  snprintf(&buffer[0], sizeof(buffer), "life %d", herolife);
  write(&buffer[0], 10, 35, sf::Color::Red);

  snprintf(&buffer[0], sizeof(buffer), "shield %d", heroshield);
  write(&buffer[0], 10, 60, sf::Color::Blue);

  snprintf(&buffer[0], sizeof(buffer), "regen %d", shield_regen * 2);
  write(&buffer[0], 10, 85, sf::Color::Cyan);

  snprintf(&buffer[0], sizeof(buffer), "level %d", serie_cnt);
  write(&buffer[0], win.getSize().x - strlen(&buffer[0]) * 20, win.getSize().y - 20, sf::Color::White);

  write("hanged bunny studio", 10, win.getSize().y - 25, sf::Color(128, 128, 128));

  if (catch_serie)
    {
      snprintf(&buffer[0], sizeof(buffer), "combo x%d", catch_serie);
      write(&buffer[0], win.getSize().x - strlen(&buffer[0]) * 20, 10,
	    sf::Color(rand() % 255, rand() % 255, rand() % 255));
    }
  if (msg_timer)
    {
      write(msg,
	    (win.getSize().x - msg.size() * 20) / 2,
	    (win.getSize().y - 20) / 2 + cos(msg_timer * 33 * M_PI / 180.0) * 10,
	    sf::Color(rand() % 255, rand() % 255, rand() % 255));
      write(msg,
	    (win.getSize().x - msg.size() * 20) / 2,
	    (win.getSize().y - 20) / 2 + cos(msg_timer * 33 * M_PI / 180.0) * 5,
	    sf::Color(rand() % 255, rand() % 255, rand() % 255));
      write(msg,
	    (win.getSize().x - msg.size() * 20) / 2,
	    (win.getSize().y - 20) / 2,
	    sf::Color(rand() % 255, rand() % 255, rand() % 255));
    }
}

void			kobang::display(void)
{
  sf::RectangleShape	shape(sf::Vector2f(win.getSize().x, win.getSize().y));

  shape.setFillColor(sf::Color(0, 0, 0, backtransparency));
  win.draw(shape);
  display_map();
  display_bomber();
  display_bomb();
  display_stats();
  if (!started)
    {
      sf::Color		c(rand() % 255, rand() % 255, rand() % 255);

      write("kobang !", (win.getSize().x - 8 * 20) / 2, 20, c);
      write("click or press space to start",
	    (win.getSize().x - 29 * 20) / 2, (win.getSize().y - 20) / 2, c);
    }
  win.display();
  color_var += 10;
}
