package levelElements;

import java.util.HashMap;
import java.util.Iterator;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
import com.ld57.game.ddd;

import Global.Global;
import effects.Ballpit;
import effects.HealthBar;
import entities.Ball;
import entities.EvilShip;
import u.UsefulMethods;

public class Gun extends Sprite {// this is a very simple, non animated sprite. Is this the lightest thing I have?
	private TextureRegion main;
	private TextureRegion broken;
	private Texture t1;
	public Color color;
	public Rectangle rect;
	public boolean isBroken;
	private int _sw;// sprite width
	private int _sh;// sprite height
	public HealthBar healthBar;
	public Array<Ball> balls;
	private Ballpit ballpit;
	private int timer;
	public Vector2 sp = new Vector2(0, 0);
	public Vector2 ep = new Vector2(0, 0);
	Vector2 dir = new Vector2();
	private int ammo;
	private float targetX;
	private float targetY;

	public Gun(float _x, float _y) {
		rect = new Rectangle();
		rect.x = (int) _x;
		rect.y = (int) _y;
		rect.width = 25;
		rect.height = 25;
		_sw = 25;
		_sh = 25;
		healthBar = new HealthBar(_x, _y, _sw, 2);
		balls = new Array<Ball>();
		ballpit = new Ballpit();
		// still frames
		t1 = new Texture(Gdx.files.internal("gun.png"));
		main = new TextureRegion(t1, (0 * _sw), (0 * _sh), _sw, _sh);
		broken = new TextureRegion(t1, (1 * _sw), (0 * _sh), _sw, _sh);
		color = Color.WHITE;
		setBounds(0, 0, _sw, _sh);
		setOriginCenter();
		setRegion(main);
	}

	private void update(OrthographicCamera camera, Array<EvilShip> evilShips) {
		rect.x = Global.P.x - 50;
		rect.y = Global.P.y + 70;
		if (!isBroken) {
			// this gets rid of balls that exploded?
			for (Iterator<Ball> iter = balls.iterator(); iter.hasNext();) {
				Ball b = iter.next();
//			System.out.println("b: " + b);
//			System.out.println("balls.size: " + balls.size);
//			System.out.println("ammo: " + ammo);
//			System.out.println("timer: " + timer);
				if (b.explosion.isDead) {
					if (ammo > 0)
						ammo--;
					balls.removeValue(b, true);
					ballpit.free(b);
				}
			}
			if (timer <= 0) {
				timer = Global.fireDelay;
				fireballstuff(camera, evilShips);
			}
			if (timer > 0)
				timer--;
		}
	}

	private void fireballstuff(OrthographicCamera camera, Array<EvilShip> enemyShips) {
		if (balls.size > 0)
			ammo++;
		getClosestEnemy(enemyShips/* player , player2, player3, player4, player5, player6 */);
		sp = new Vector2(rect.x, rect.y);
		ep = new Vector2(targetX, targetY);
		Ball ball = ballpit.obtain();
		ball.sp.x = rect.x;
		ball.sp.y = rect.y;
		ball.ep.x = ep.x;
		ball.ep.y = ep.y;
		balls.add(ball);
		balls.get(ammo).dir = u.UsefulMethods.GetDirection(sp, ep);
		balls.get(ammo).rect.x = sp.x;
		balls.get(ammo).rect.y = sp.y;
		balls.get(ammo).fired = true;
		balls.get(ammo).ballLife = Global.gunFiringDistance;// was 300
		balls.get(ammo).isDead = false;
		balls.get(ammo).canHit = true;
		balls.get(ammo).explosion.isDead = false;
		// System.out.println("ammo: " + ammo);
	}

	public Vector2 GetDirection(Vector2 sp, Vector2 ep) {
		return ep.sub(sp).nor();
	}

	/**
	 * array of whoever is closest
	 */
	private Vector2 getClosestEnemy(Array<EvilShip> enemyShips
	/* Player player , Player2 player2, Player3 player3, Player4 player4, Player5 player5, Player6 player6 */) {
		float closestDistance = 1000000;
		Vector2 _sp = new Vector2(rect.x, rect.y);// starting point is always this initial 'living point'.
		Vector2 _ep = new Vector2(ep.x, ep.y);// we don't actually know this. This is what we are determining.
		HashMap<Float, Vector2> _distances = new HashMap<Float, Vector2>();
		for (Iterator<EvilShip> iter2 = enemyShips.iterator(); iter2.hasNext();) {
			EvilShip w = iter2.next();
			if (!w.isDead) {
				ep = new Vector2(w.rect.x, w.rect.y);
				float dist = UsefulMethods.GetDistance(_sp, ep);
				if (dist < closestDistance && !w.isDead) {
					closestDistance = dist;
					_ep = ep;
				}
				_distances.put(closestDistance, _ep);
			}
		}
		// player1
//		ep = new Vector2(player.rect.x, player.rect.y);
//		float dist = UsefulMethods.GetDistance(_sp, ep);
//		if (dist < closestDistance) {
//			closestDistance = dist;
//			_ep = ep;
//		}
//		_distances.put(closestDistance, _ep);
//		// player2
//		ep = new Vector2(player2.rect.x, player2.rect.y);
//		float dist2 = UsefulMethods.GetDistance(_sp, ep);
//		if (dist2 < closestDistance) {
//			closestDistance = dist2;
//			_ep = ep;
//		}
//		_distances.put(closestDistance, _ep);
//		// player3
//		ep = new Vector2(player3.rect.x, player3.rect.y);
//		float dist3 = UsefulMethods.GetDistance(_sp, ep);
//		if (dist3 < closestDistance) {
//			closestDistance = dist3;
//			_ep = ep;
//		}
//		_distances.put(closestDistance, _ep);
//		// player4
//		ep = new Vector2(player4.rect.x, player4.rect.y);
//		float dist4 = UsefulMethods.GetDistance(_sp, ep);
//		if (dist4 < closestDistance) {
//			closestDistance = dist4;
//			_ep = ep;
//		}
//		_distances.put(closestDistance, _ep);
//		// player5
//		ep = new Vector2(player5.rect.x, player5.rect.y);
//		float dist5 = UsefulMethods.GetDistance(_sp, ep);
//		if (dist5 < closestDistance) {
//			closestDistance = dist5;
//			_ep = ep;
//		}
//		_distances.put(closestDistance, _ep);
//		// player6
//		ep = new Vector2(player6.rect.x, player6.rect.y);
//		float dist6 = UsefulMethods.GetDistance(_sp, ep);
//		if (dist6 < closestDistance) {
//			closestDistance = dist6;
//			_ep = ep;
//		}
//		_distances.put(closestDistance, _ep);
		// check all of them.
		for (Float key : _distances.keySet()) {
			if (key < closestDistance)
				closestDistance = key;
		}
		Vector2 td = _distances.get(closestDistance);
		if (!isEmpty(td)) {
			setTargetToClosestItem(td.x, td.y);
		} else {
			Vector2 oopsNoOneIsLeft = new Vector2(rect.x, rect.y);// was player.rect.x and y
			td = oopsNoOneIsLeft;
		}
		return td;
	}

	private boolean isEmpty(Vector2 v) {
		if (v == null)
			return true;
		else
			return false;
	}

	private void setTargetToClosestItem(float _x, float _y) {
		targetX = _x;
		targetY = _y;
	}

	public TextureRegion getFrame(OrthographicCamera camera, float dt, Array<EvilShip> evilShips) {
		update(camera, evilShips);
		return getTextureRegion();
	}

	public TextureRegion getTextureRegion() {
		if (isBroken)
			return broken;
		else
			return main;
	}

	public void render(ddd game, OrthographicCamera camera, float dt, Array<EvilShip> evilShips) {// hmmm i think it just needs placed before? it gets here.
		game.batch.setColor(color);
		game.batch.draw(getFrame(camera, dt, evilShips), rect.x, rect.y);
	}

	public void dispose() {
	}
}
