/**
 *  Triangles
 *  Copyright (C) 2016 POSITIVE MENTAL ATTITUDE
 *
 *  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, version 3 of the License.
 *
 *  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, see <http://www.gnu.org/licenses/>.
 */

#include "Bullet.hpp"
#include "Utility.hpp"
#include "cmath"

Bullet::Bullet(float rotation, sf::Vector2f initialPosition, sf::SoundBuffer& buffer1, sf::SoundBuffer& buffer2, Foreground* foreground): _texture(nullptr), _foreground(foreground), _hit(false), _dead(false)
{
	setRotation(rotation);
	setPosition(initialPosition);
	_vertex[0].position = sf::Vector2f(-3.f, 40.f);
	_vertex[1].position = sf::Vector2f(3.f, 40.f);
	_vertex[2].position = sf::Vector2f(3.f, -40.f);
	_vertex[3].position = sf::Vector2f(-3.f, -40.f);
	_sound.setBuffer(buffer1);
	_explosion.setBuffer(buffer2);
	_sound.setPlayingOffset(sf::Time::Zero);
	_sound.play();
	genCollisionBox("data/hitbox/Bullet.png", sf::Vector2f(3.f, 40.f));
}

void Bullet::setTexture(sf::Texture& texture)
{
	_texture = &texture;
	sf::Vector2u size = texture.getSize();
	_vertex[0].texCoords = sf::Vector2f(0, size.y);
	_vertex[1].texCoords = sf::Vector2f(size.x, size.y);
	_vertex[2].texCoords = sf::Vector2f(size.x / 2.f, 0);
	_vertex[3].texCoords = sf::Vector2f(size.x / 2.f, size.y / 2.f);
}

void Bullet::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
	if(_hit)
		return;

	states.transform *= getTransform();

	if(_texture != nullptr)
		states.texture = (_texture);
    
	target.draw(_vertex, 4, sf::Quads, states);
}

void Bullet::destroyPixels(int& k, int x, int y)
{
	int plus = 1;
	int dir = 0;
	int curr = 0;
	bool q[4] = {false, false, false, false};
	while(k <= 6400) {
		if(_foreground->destroy(x, y))
		{
			q[dir] = true;
			++k;
		}
		switch(dir)
		{
			case 0: ++x; break;
			case 1: ++y; break;
			case 2: --x; break;
			case 3: --y; break;
			default: break;
		}
		++curr;
		if(curr >= plus)
		{
			curr = 0;
			++dir;
			if(dir == 4)
			{
				dir = 0;
				/*
				 * This prevents destroying remote islands of foreground.
				 */
				bool exit = true;
				for(int i = 0; i < 4; ++i)
				{
					if(q[i])
						exit = false;
					q[i] = false;
				}
				if(exit)
					break;
			}
			if(dir == 0 or dir == 2)
				++plus;
		}
	}
}

void Bullet::update(sf::Time delta, sf::Vector2f position)
{
	float seconds = delta.asSeconds();
	const double degree = 3.14159265358 / 180.;
	sf::Vector2f movement;
	movement.x = std::sin(getRotation() * degree) * 1080.f * seconds;
	movement.y = -std::cos(getRotation() * degree) * 1080.f * seconds;
	move(movement);
	
	Collidable::updateTransform(getTransform());
	if(!_hit)
	{
		int k = pixelPerfect(*_foreground);
		if(k != -1)
			{
				sf::Vector2i vec = (sf::Vector2i)getTransform().transformPoint(_cmap[k]);
				int n = vec.x, m = vec.y;
				int k = 0;
				destroyPixels(k, n, m);
				_foreground->reloadFromPixel(vec.x, vec.y, true);
				_explosion.play();
				_hit = true;
			}
	}
	if(_hit && _sound.getStatus() == sf::Sound::Status::Stopped && _sound.getPlayingOffset() == sf::Time::Zero && _explosion.getStatus() == sf::Sound::Status::Stopped)
		_dead = true;
}

const bool Bullet::isDead() const
{
	return _dead && _hit ? true : false;
}