package entities;

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

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.audio.Sound;
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.MathUtils;
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.HealthBar;
import u.UsefulMethods;
import unearthables.Amethyst;
import unearthables.Copper;
import unearthables.Diamond;
import unearthables.Food;
import unearthables.Gold;
import unearthables.Platinum;
import unearthables.Ruby;
import unearthables.Sapphire;
import unearthables.Silver;
import unearthables.Topaz;

public class EvilShip extends Sprite {
	public int health = 100;
	public int healthMax = 100;
	// private TextureAtlas atlas;
	private Texture t1;
	private TextureRegion main;
	public Color color;
	public Float speed = 100f;// was 400
	public Rectangle rect;
	public boolean rmove;
	public boolean lmove;
	public boolean umove;
	public boolean dmove;
	public boolean isDying;
	public static boolean r;
	public static boolean l;
	public static boolean u;
	public static boolean d;
	private int _sw;// sprite width
	private int _sh;// sprite height
	protected int MoveBufferX = 0, MoveBufferY = 0;
	// sfx
	private Sound sfx_death;
	private Sound hurt;
	private Sound hurt2;
	private Sound eat;
	private Sound eat2;
	private Sound eat3;
	private Sound eat4;
	private Sound eat5;
	private Sound eat6;
	private Sound eat7;
	private Sound eat8;
	private Sound eat9;
	private Sound eat10;
	private Sound eat11;
	private Sound roar;
	private Sound roar2;
	private Sound roar3;
	private Sound roar4;
	private Sound roar5;
	public int SpeedScale = 20;
	public boolean isJumping = false;
	// testing vectors
	Vector2 position = new Vector2();
	Vector2 velocity = new Vector2();
	Vector2 movement = new Vector2();
	Vector2 touch = new Vector2();
	Vector2 dir = new Vector2();
	// private Float duckSpeed = speed / 2;
	public Vector2 sp = new Vector2(0, 0);
	public Vector2 ep = new Vector2(0, 0);
	public boolean isWait = true;
	public boolean getDir;
	public boolean isDead;
	public boolean isEating;
	public boolean isFat;
	private int isDyingTimer;
	private boolean playOnce;
	private float targetX;
	private float targetY;
	private int walkTimer;
	private int walkTimerMax = MathUtils.random(10, 200);
	private boolean isChosen;
	public boolean canHit = true;
	private boolean isOneEatSound;
	public EnemyGun enemyGun;
	public EnemyEngine enemyEngine;
	public HealthBar healthBar;
	public int amethystStockpile;
	public int copperStockpile;
	public int diamondStockpile;
	public int goldStockpile;
	public int platinumStockpile;
	public int rubyStockpile;
	public int sapphireStockpile;
	public int silverStockpile;
	public int topazStockpile;

	public EvilShip(int _x, int _y) {
		rect = new Rectangle();
		rect.x = _x;
		rect.y = _y;
		rect.width = 100;
		rect.height = 100;

		_sw = 100;
		_sh = 100;
		healthBar = new HealthBar(_x, _y, 100, 2);
		enemyGun = new EnemyGun(_x, _y);
		enemyEngine = new EnemyEngine(_x, _y);

		if (MathUtils.random(1, 2) == 1)
			isChosen = true;
		// _level = level;

		// set location and intial velocities?
		position.set(rect.getX(), rect.getY());
		// sounds
		sfx_death = Gdx.audio.newSound(Gdx.files.internal("sfx/death.ogg"));
		hurt = Gdx.audio.newSound(Gdx.files.internal("sfx/hurt.ogg"));
		hurt2 = Gdx.audio.newSound(Gdx.files.internal("sfx/hurt2.ogg"));
		eat = Gdx.audio.newSound(Gdx.files.internal("sfx/eat.ogg"));
		eat2 = Gdx.audio.newSound(Gdx.files.internal("sfx/eat2.ogg"));
		eat3 = Gdx.audio.newSound(Gdx.files.internal("sfx/eat3.ogg"));
		eat4 = Gdx.audio.newSound(Gdx.files.internal("sfx/eat4.ogg"));
		eat5 = Gdx.audio.newSound(Gdx.files.internal("sfx/eat5.ogg"));
		eat6 = Gdx.audio.newSound(Gdx.files.internal("sfx/eat6.ogg"));
		eat7 = Gdx.audio.newSound(Gdx.files.internal("sfx/eat7.ogg"));
		eat8 = Gdx.audio.newSound(Gdx.files.internal("sfx/eat8.ogg"));
		eat9 = Gdx.audio.newSound(Gdx.files.internal("sfx/eat9.ogg"));
		eat10 = Gdx.audio.newSound(Gdx.files.internal("sfx/eat10.ogg"));
		eat11 = Gdx.audio.newSound(Gdx.files.internal("sfx/eat11.ogg"));
		roar = Gdx.audio.newSound(Gdx.files.internal("sfx/roar.ogg"));
		roar2 = Gdx.audio.newSound(Gdx.files.internal("sfx/roar2.ogg"));
		roar3 = Gdx.audio.newSound(Gdx.files.internal("sfx/roar3.ogg"));
		roar4 = Gdx.audio.newSound(Gdx.files.internal("sfx/roar4.ogg"));
		roar5 = Gdx.audio.newSound(Gdx.files.internal("sfx/roar5.ogg"));

		t1 = new Texture(Gdx.files.internal("shipv1.png"));
		main = new TextureRegion(t1, (0 * _sw), (0 * _sh), _sw, _sh);
		color = new Color(MathUtils.random(.5f, 1f), MathUtils.random(.5f, 1f), MathUtils.random(.5f, 1f), 1);
		setBounds(0, 0, _sw, _sh);
		setRegion(main);
		r = true;
	}

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

	// for all the animations: //this isn't even updated unless i call it from the
	// other screen oh bother. *facepalm*
	public void update(float dt, OrthographicCamera camera, Array<Amethyst> amethystGems, Array<Copper> copperMetals, Array<Diamond> diamondGems,
			Array<Food> foodHealth, Array<Gold> goldMetals, Array<Platinum> platinumMetals, Array<Ruby> rubyGems, Array<Sapphire> sapphireGems,
			Array<Silver> silverMetals, Array<Topaz> topazGems) {
		// none of this stuff applies to digging ships. This will all need refactoring into a ship that goes towards gems/money and starts collecting them.
		// the guns on the ship shoot the player(s) ships and engines, guns, drills, etc.
		// set your guns position
		enemyGun.rect.x = rect.x - 5;
		enemyGun.rect.y = rect.y + 100;
		enemyGun.color = color;
		// set your engine position
		enemyEngine.rect.x = rect.x + 100;
		enemyEngine.rect.y = rect.y + 50;
		enemyEngine.color = color;

		if (isDying && isDyingTimer > 0) {
			if (!Global.SetVolumeToZero && !playOnce) {
				playOnce = true;
				sfx_death.play(1f);
			}
			isDyingTimer--;
		} else {
			if (isDying && isDyingTimer <= 0) {
				isDead = true;
			}
			if (isDead) {
				rect.x += 0;
				rect.y += 0;
				playOnce = false;
			} else {
				if (walkTimer <= 0) {
					walkTimer = walkTimerMax;
					sp = new Vector2(rect.x, rect.y);
					if (!isFat) {// go towards the closest gem or money wait till the player has his gun working, them mimic it here. :P
						getClosestEnemy(amethystGems, copperMetals, diamondGems, foodHealth, goldMetals, platinumMetals, rubyGems, sapphireGems, silverMetals,
								topazGems);
						ep = new Vector2(targetX, targetY);
						dir = GetDirection(sp, ep);
					} else {// go to the corner. bye bye
						// System.out.println("rectX: " + rect.x + "rectY: " + rect.y);
						ep = new Vector2(0, 0 + MathUtils.random(-20, 20));
						// System.out.println("sp: " + sp + "ep: " + ep);
						dir = GetDirection(sp, ep);
					}
				}
				if (walkTimer > 0)
					walkTimer--;
				// System.out.println("sp: " + sp + "ep: " + ep);
				rect.x += dir.x * speed * dt;
				rect.y += dir.y * speed * dt;
			}
		}
		checkIfAnimationsAreDone();
		getCorrectWalkingAnimation(dt);
	}// end of update

	private void checkIfAnimationsAreDone() {
		if (isEating) {
			if (!isOneEatSound) {
				isOneEatSound = true;
				if (!Global.SetVolumeToZero)
					playRandomEatSound(5);
			}
//			if (currentState == State.EATING) {
//				if (eating.isAnimationFinished(_stateTimer)) {
//					isEating = false;
//					isOneEatSound = false;
//					isjumpAtPlayer = false;
//					isFat = true;
//				}
//			}
		}
	}

	/**
	 * array of whoever is closest
	 */
	private Vector2 getClosestEnemy(Array<Amethyst> amethystGems, Array<Copper> copperMetals, Array<Diamond> diamondGems, Array<Food> foodHealth,
			Array<Gold> goldMetals, Array<Platinum> platinumMetals, Array<Ruby> rubyGems, Array<Sapphire> sapphireGems, Array<Silver> silverMetals,
			Array<Topaz> topazGems) {
		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>();
		// amethystGems
		for (Iterator<Amethyst> iter = amethystGems.iterator(); iter.hasNext();) {
			Amethyst am = iter.next();
			ep = new Vector2(am.rect.x, am.rect.y);
			float dist = UsefulMethods.GetDistance(_sp, ep);
			if (dist < closestDistance && !am.isDead) {
				closestDistance = dist;
				_ep = ep;
			}
			_distances.put(closestDistance, _ep);
		}
		// copperMetals
		for (Iterator<Copper> iter = copperMetals.iterator(); iter.hasNext();) {
			Copper cp = iter.next();
			ep = new Vector2(cp.rect.x, cp.rect.y);
			float dist = UsefulMethods.GetDistance(_sp, ep);
			if (dist < closestDistance && !cp.isDead) {
				closestDistance = dist;
				_ep = ep;
			}
			_distances.put(closestDistance, _ep);
		}
		// diamondGems
		for (Iterator<Diamond> iter = diamondGems.iterator(); iter.hasNext();) {
			Diamond cp = iter.next();
			ep = new Vector2(cp.rect.x, cp.rect.y);
			float dist = UsefulMethods.GetDistance(_sp, ep);
			if (dist < closestDistance && !cp.isDead) {
				closestDistance = dist;
				_ep = ep;
			}
			_distances.put(closestDistance, _ep);
		}
		// foodHealth
		for (Iterator<Food> iter = foodHealth.iterator(); iter.hasNext();) {
			Food cp = iter.next();
			ep = new Vector2(cp.rect.x, cp.rect.y);
			float dist = UsefulMethods.GetDistance(_sp, ep);
			if (dist < closestDistance && !cp.isDead) {
				closestDistance = dist;
				_ep = ep;
			}
			_distances.put(closestDistance, _ep);
		}
		// goldMetals
		for (Iterator<Gold> iter = goldMetals.iterator(); iter.hasNext();) {
			Gold cp = iter.next();
			ep = new Vector2(cp.rect.x, cp.rect.y);
			float dist = UsefulMethods.GetDistance(_sp, ep);
			if (dist < closestDistance && !cp.isDead) {
				closestDistance = dist;
				_ep = ep;
			}
			_distances.put(closestDistance, _ep);
		}
		// platinumMetals
		for (Iterator<Platinum> iter = platinumMetals.iterator(); iter.hasNext();) {
			Platinum cp = iter.next();
			ep = new Vector2(cp.rect.x, cp.rect.y);
			float dist = UsefulMethods.GetDistance(_sp, ep);
			if (dist < closestDistance && !cp.isDead) {
				closestDistance = dist;
				_ep = ep;
			}
			_distances.put(closestDistance, _ep);
		}
		// rubyGems
		for (Iterator<Ruby> iter = rubyGems.iterator(); iter.hasNext();) {
			Ruby cp = iter.next();
			ep = new Vector2(cp.rect.x, cp.rect.y);
			float dist = UsefulMethods.GetDistance(_sp, ep);
			if (dist < closestDistance && !cp.isDead) {
				closestDistance = dist;
				_ep = ep;
			}
			_distances.put(closestDistance, _ep);
		}
		// sapphireGems
		for (Iterator<Sapphire> iter = sapphireGems.iterator(); iter.hasNext();) {
			Sapphire cp = iter.next();
			ep = new Vector2(cp.rect.x, cp.rect.y);
			float dist = UsefulMethods.GetDistance(_sp, ep);
			if (dist < closestDistance && !cp.isDead) {
				closestDistance = dist;
				_ep = ep;
			}
			_distances.put(closestDistance, _ep);
		}
		// silverMetals
		for (Iterator<Silver> iter = silverMetals.iterator(); iter.hasNext();) {
			Silver cp = iter.next();
			ep = new Vector2(cp.rect.x, cp.rect.y);
			float dist = UsefulMethods.GetDistance(_sp, ep);
			if (dist < closestDistance && !cp.isDead) {
				closestDistance = dist;
				_ep = ep;
			}
			_distances.put(closestDistance, _ep);
		}
		// silverMetals
		for (Iterator<Silver> iter = silverMetals.iterator(); iter.hasNext();) {
			Silver cp = iter.next();
			ep = new Vector2(cp.rect.x, cp.rect.y);
			float dist = UsefulMethods.GetDistance(_sp, ep);
			if (dist < closestDistance && !cp.isDead) {
				closestDistance = dist;
				_ep = ep;
			}
			_distances.put(closestDistance, _ep);
		}
		// topazGems
		for (Iterator<Topaz> iter = topazGems.iterator(); iter.hasNext();) {
			Topaz cp = iter.next();
			ep = new Vector2(cp.rect.x, cp.rect.y);
			float dist = UsefulMethods.GetDistance(_sp, ep);
			if (dist < closestDistance && !cp.isDead) {
				closestDistance = dist;
				_ep = ep;
			}
			_distances.put(closestDistance, _ep);
		}
		// center of the map
		ep = new Vector2(ddd.MW / 2, ddd.MH / 2);// for testing
		float dist = UsefulMethods.GetDistance(_sp, ep);
		if (dist < closestDistance) {
			closestDistance = dist;
			_ep = ep;
		}
		_distances.put(closestDistance, _ep);
		// player1
//		ep = new Vector2(shipv1.rect.x, shipv1.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);
		// check all of them.
		for (Float key : _distances.keySet()) {
			if (key < closestDistance)
				closestDistance = key;
		}
		Vector2 td = _distances.get(closestDistance);
		// System.out.println("distance?: " + td);
		if (!isEmpty(td))
			setTargetToClosestItem(td.x, td.y);
		else {
			Vector2 oopsNoOneIsLeft = new Vector2(ddd.MW / 2, ddd.MH / 2);
			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;
	}

	private void getCorrectWalkingAnimation(float dt) {
		if (isChosen) {
			if (targetX > rect.x) {
				rmove = true;
				lmove = false;
				r = true;
				l = false;
				u = false;
				d = false;
			} else if (targetX <= rect.x) {
				lmove = true;
				rmove = false;
				l = true;
				r = false;
				u = false;
				d = false;
			}
		} else {
			if (targetY > rect.y) {
				umove = true;
				dmove = false;
				u = true;
				d = false;
				l = false;
				r = false;
			} else if (targetY <= rect.y) {
				dmove = true;
				umove = false;
				d = true;
				u = false;
				l = false;
				r = false;
			}
		}
	}

	public TextureRegion getFrame(OrthographicCamera camera, float dt, Array<Amethyst> amethystGems, Array<Copper> copperMetals, Array<Diamond> diamondGems,
			Array<Food> foodHealth, Array<Gold> goldMetals, Array<Platinum> platinumMetals, Array<Ruby> rubyGems, Array<Sapphire> sapphireGems,
			Array<Silver> silverMetals, Array<Topaz> topazGems) {
		// System.out.println("getting frame: " + getState(player));
		// System.out.println("_stateTimer: " + _stateTimer);
		// System.out.println("animation Index: " + walkLeft.getKeyFrame(_stateTimer));
		update(dt, camera, amethystGems, copperMetals, diamondGems, foodHealth, goldMetals, platinumMetals, rubyGems, sapphireGems, silverMetals, topazGems);
		return main;
	}

	public void playRandomHurtSound(int numberOfSounds) {
		int randomSound = MathUtils.random(1, numberOfSounds);
		if (!Global.SetVolumeToZero) {
			if (randomSound == 1)
				hurt.play();
			else if (randomSound == 2)
				hurt2.play();
		}
	}

	public void playRandomEatSound(int numberOfSounds) {
		int randomSound = MathUtils.random(1, numberOfSounds);
		if (!Global.SetVolumeToZero) {
			if (randomSound == 1)
				eat.play();
			else if (randomSound == 2)
				eat2.play();
			else if (randomSound == 3)
				eat3.play();
			else if (randomSound == 4)
				eat4.play();
			else if (randomSound == 5)
				eat5.play();
			else if (randomSound == 6)
				eat6.play();
			else if (randomSound == 7)
				eat7.play();
			else if (randomSound == 8)
				eat8.play();
			else if (randomSound == 9)
				eat9.play();
			else if (randomSound == 10)
				eat10.play();
			else if (randomSound == 11)
				eat11.play();
		}
	}

	public void playRandomRoarSound(int numberOfSounds) {
		int randomSound = MathUtils.random(1, numberOfSounds);
		if (!Global.SetVolumeToZero) {
			if (randomSound == 1)
				roar.play();
			else if (randomSound == 2)
				roar2.play();
			else if (randomSound == 3)
				roar3.play();
			else if (randomSound == 4)
				roar4.play();
			else if (randomSound == 5)
				roar5.play();
		}
	}

	public void dispose() {
		sfx_death.dispose();
		hurt.dispose();
		hurt2.dispose();
		eat.dispose();
		eat2.dispose();
		eat3.dispose();
		eat4.dispose();
		eat5.dispose();
		eat6.dispose();
		eat7.dispose();
		eat8.dispose();
		eat9.dispose();
		eat10.dispose();
		eat11.dispose();
		roar.dispose();
		roar2.dispose();
		roar3.dispose();
		roar4.dispose();
		roar5.dispose();
	}

	public void render(ddd game, OrthographicCamera camera, float dt, Array<Amethyst> amethystGems, Array<Copper> copperMetals, Array<Diamond> diamondGems,
			Array<Food> foodHealth, Array<Gold> goldMetals, Array<Platinum> platinumMetals, Array<Ruby> rubyGems, Array<Sapphire> sapphireGems,
			Array<Silver> silverMetals, Array<Topaz> topazGems) {
		game.batch.draw(getFrame(camera, dt, amethystGems, copperMetals, diamondGems, foodHealth, goldMetals, platinumMetals, rubyGems, sapphireGems, silverMetals,
				topazGems), rect.x, rect.y);
	}
}
