package net.geforcemods.securitycraft.entity.ai;

import java.util.Collections;
import java.util.List;

import net.geforcemods.securitycraft.entity.SentryEntity;
import net.geforcemods.securitycraft.entity.SentryEntity.SentryMode;
import net.geforcemods.securitycraft.util.EntityUtils;
import net.minecraft.entity.Entity;
import net.minecraft.entity.FlyingEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.goal.NearestAttackableTargetGoal;
import net.minecraft.entity.boss.dragon.EnderDragonEntity;
import net.minecraft.entity.monster.MonsterEntity;
import net.minecraft.entity.monster.ShulkerEntity;
import net.minecraft.entity.monster.SlimeEntity;
import net.minecraft.entity.player.PlayerEntity;

/**
 * Attacks any player who is not the owner, or any mob
 */
public class TargetNearestPlayerOrMobGoal extends NearestAttackableTargetGoal<LivingEntity>
{
	private SentryEntity sentry;

	public TargetNearestPlayerOrMobGoal(SentryEntity sentry)
	{
		super(sentry, LivingEntity.class, true);

		this.sentry = sentry;
	}

	@Override
	public boolean shouldExecute()
	{
		List<LivingEntity> list = goalOwner.world.<LivingEntity>getEntitiesWithinAABB(targetClass, getTargetableArea(getTargetDistance()), e -> !EntityUtils.isInvisible(e));

		if(list.isEmpty())
			return false;
		else
		{
			SentryMode mode = sentry.getMode();
			LivingEntity potentialTarget = null;

			Collections.sort(list, (e1, e2) -> {
				double distTo1 = goalOwner.getDistanceSq(e1);
				double distTo2 = goalOwner.getDistanceSq(e2);

				if(distTo1 < distTo2)
					return -1;
				else return distTo1 > distTo2 ? 1 : 0;
			});

			//get the nearest target that is either a mob or a player
			for(int i = 0; i < list.size(); i++)
			{
				potentialTarget = list.get(i);

				if(potentialTarget.isInvulnerable())
					continue;

				if(mode.attacksPlayers())
				{
					if(potentialTarget instanceof PlayerEntity
							&& !((PlayerEntity)potentialTarget).isSpectator()
							&& !((PlayerEntity)potentialTarget).isCreative()
							&& !((SentryEntity)goalOwner).getOwner().isOwner(((PlayerEntity)potentialTarget))
							&& !sentry.isTargetingWhitelistedPlayer(potentialTarget)
							&& !EntityUtils.isInvisible(potentialTarget))
						break;
				}

				if(mode.attacksHostile() && isSupportedTarget(potentialTarget))
					break;
			}

			if(potentialTarget != null && isCloseEnough(potentialTarget))
			{
				nearestTarget = potentialTarget;
				goalOwner.setAttackTarget(nearestTarget);
				return true;
			}

			return false;
		}
	}

	@Override
	public boolean shouldContinueExecuting()
	{
		return (isSupportedTarget(nearestTarget) || nearestTarget instanceof PlayerEntity) && isCloseEnough(nearestTarget) && shouldExecute() && !sentry.isTargetingWhitelistedPlayer(target) && super.shouldContinueExecuting();
	}

	public boolean isCloseEnough(Entity entity)
	{
		return entity != null && goalOwner.getDistanceSq(entity) <= getTargetDistance() * getTargetDistance();
	}

	public boolean isSupportedTarget(LivingEntity potentialTarget)
	{
		return (potentialTarget instanceof MonsterEntity || potentialTarget instanceof FlyingEntity || potentialTarget instanceof SlimeEntity || potentialTarget instanceof ShulkerEntity || potentialTarget instanceof EnderDragonEntity) && potentialTarget.deathTime == 0;
	}

	@Override
	protected double getTargetDistance()
	{
		return SentryEntity.MAX_TARGET_DISTANCE;
	}
}

@@ -1397,43 +1397,13 @@
 %0A%09%09%09
-LivingEntity potentialTarget = null
+int i
 ;%0D%0A%0D
@@ -1715,20 +1715,16 @@
 %0A%09%09%09for(
-int 
 i = 0; i
@@ -1755,16 +1755,29 @@
 %09%7B%0D%0A%09%09%09%09
+LivingEntity 
 potentia
@@ -2396,35 +2396,39 @@
 %09if(
-potentialTarget != null && 
+i %3C list.size())%0D%0A%09%09%09%7B%0D%0A%09%09%09%09if(
 isCl
@@ -2441,33 +2441,31 @@
 ugh(
-potentialTar
+list.
 get
+(i
 ))
+)
 %0D%0A
+%09
 %09%09%09%7B%0D%0A
+%09
 %09%09%09%09
@@ -2484,26 +2484,23 @@
 t = 
-potentialTarget
+list.get(i)
 ;%0D%0A
+%09
 %09%09%09%09
@@ -2542,24 +2542,25 @@
 rget);%0D%0A%09%09%09%09
+%09
 return true;
@@ -2561,16 +2561,23 @@
  true;%0D%0A
+%09%09%09%09%7D%0D%0A
 %09%09%09%7D%0D%0A%0D%0A

Revert "code improvement"