/*
 * Copyright  2014 - 2017 | Wurst-Imperium | All rights reserved.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
package tk.wurst_client.features.mods;

import net.minecraft.client.entity.EntityOtherPlayerMP;
import net.minecraft.entity.Entity;
import tk.wurst_client.events.listeners.UpdateListener;
import tk.wurst_client.utils.ChatUtils;
import tk.wurst_client.utils.EntityUtils;
import tk.wurst_client.utils.EntityUtils.TargetSettings;

@Mod.Info(
	description = "Allows you to see the world as someone else.\n"
		+ "Use the .rv command to make it target a specific entity.",
	name = "RemoteView",
	tags = "remote view",
	help = "Mods/RemoteView")
@Mod.Bypasses
public class RemoteViewMod extends Mod implements UpdateListener
{
	private Entity entity = null;
	
	private double oldX;
	private double oldY;
	private double oldZ;
	private float oldYaw;
	private float oldPitch;
	private boolean wasInvisible;
	
	private TargetSettings targetSettingsFind = new TargetSettings()
	{
		@Override
		public boolean targetFriends()
		{
			return true;
		}
		
		@Override
		public boolean targetBehindWalls()
		{
			return true;
		};
	};
	
	private TargetSettings targetSettingsKeep = new TargetSettings()
	{
		@Override
		public boolean targetFriends()
		{
			return true;
		}
		
		@Override
		public boolean targetBehindWalls()
		{
			return true;
		};
		
		@Override
		public boolean targetInvisiblePlayers()
		{
			return true;
		}
		
		@Override
		public boolean targetInvisibleMobs()
		{
			return true;
		}
	};
	
	@Override
	public void onEnable()
	{
		// find entity if not already set
		if(entity == null)
		{
			entity = EntityUtils.getClosestEntity(targetSettingsFind);
			
			// check if entity was found
			if(entity == null)
			{
				ChatUtils.message("There is no nearby entity.");
				setEnabled(false);
				return;
			}
		}
		
		// save old data
		oldX = mc.player.posX;
		oldY = mc.player.posY;
		oldZ = mc.player.posZ;
		oldYaw = mc.player.rotationYaw;
		oldPitch = mc.player.rotationPitch;
		wasInvisible = entity.isInvisibleToPlayer(mc.player);
		
		// activate NoClip
		mc.player.noClip = true;
		
		// spawn fake player
		EntityOtherPlayerMP fakePlayer =
			new EntityOtherPlayerMP(mc.world, mc.player.getGameProfile());
		fakePlayer.clonePlayer(mc.player, true);
		fakePlayer.copyLocationAndAnglesFrom(mc.player);
		fakePlayer.rotationYawHead = mc.player.rotationYawHead;
		mc.world.addEntityToWorld(-69, fakePlayer);
		
		// success message
		ChatUtils.message("Now viewing " + entity.getName() + ".");
		
		// add listener
		wurst.events.add(UpdateListener.class, this);
	}
	
	@Override
	public void onDisable()
	{
		// remove listener
		wurst.events.remove(UpdateListener.class, this);
		
		// reset entity
		if(entity != null)
		{
			ChatUtils.message("No longer viewing " + entity.getName() + ".");
			entity.setInvisible(wasInvisible);
			entity = null;
		}
		
		// reset player
		mc.player.noClip = false;
		mc.player.setPositionAndRotation(oldX, oldY, oldZ, oldYaw, oldPitch);
		
		// remove fake player
		mc.world.removeEntityFromWorld(-69);
	}
	
	public void onToggledByCommand(String viewName)
	{
		// set entity
		if(!isEnabled() && viewName != null && !viewName.isEmpty())
			entity =
				EntityUtils.getEntityWithName(viewName, targetSettingsFind);
		
		// toggle RemoteView
		toggle();
	}
	
	@Override
	public void onUpdate()
	{
		// validate entity
		if(!EntityUtils.isCorrectEntity(entity, targetSettingsKeep))
		{
			setEnabled(false);
			return;
		}
		
		// update position, rotation, etc.
		mc.player.copyLocationAndAnglesFrom(entity);
		mc.player.motionX = 0;
		mc.player.motionY = 0;
		mc.player.motionZ = 0;
		
		// set entity invisible
		entity.setInvisible(true);
	}
}

@@ -315,64 +315,8 @@
 s;%0A%0A
-import net.minecraft.client.entity.EntityOtherPlayerMP;%0A
 impo
@@ -439,24 +439,71 @@
 .ChatUtils;%0A
+import tk.wurst_client.utils.EntityFakePlayer;%0A
 import tk.wu
@@ -913,18 +913,16 @@
 = null;%0A
-%09%0A
 %09private
@@ -926,142 +926,68 @@
 ate 
-double oldX;%0A%09private double oldY;%0A%09private double oldZ;%0A%09private float oldYaw;%0A%09private float oldPitch;%0A%09private boolean wasInvisible
+boolean wasInvisible;%0A%09%0A%09private EntityFakePlayer fakePlayer
 ;%0A%09%0A
@@ -1199,17 +1199,16 @@
 rue;%0A%09%09%7D
-;
 %0A%09%7D;%0A%09%0A%09
@@ -1419,17 +1419,16 @@
 rue;%0A%09%09%7D
-;
 %0A%09%09%0A%09%09@O
@@ -1932,155 +1932,8 @@
 ata%0A
-%09%09oldX = mc.player.posX;%0A%09%09oldY = mc.player.posY;%0A%09%09oldZ = mc.player.posZ;%0A%09%09oldYaw = mc.player.rotationYaw;%0A%09%09oldPitch = mc.player.rotationPitch;%0A
 %09%09wa
@@ -1996,15 +1996,13 @@
 %09// 
-activat
+enabl
 e No
@@ -2065,28 +2065,8 @@
 r%0A%09%09
-EntityOtherPlayerMP 
 fake
@@ -2073,20 +2073,17 @@
 Player =
-%0A%09%09%09
+ 
 new Enti
@@ -2088,256 +2088,19 @@
 tity
-OtherPlayerMP(mc.world, mc.player.getGameProfile());%0A%09%09fakePlayer.clonePlayer(mc.player, true);%0A%09%09fakePlayer.copyLocationAndAnglesFrom(mc.player);%0A%09%09fakePlayer.rotationYawHead = mc.player.rotationYawHead;%0A%09%09mc.world.addEntityToWorld(-69, fakePlayer
+FakePlayer(
 );%0A%09
@@ -2556,20 +2556,22 @@
 %09// 
-reset player
+disable NoClip
 %0A%09%09m
@@ -2601,141 +2601,90 @@
 ;%0A%09%09
-mc.player.setPositionAndRotation(oldX, oldY, oldZ, oldYaw, oldPitch);%0A%09%09%0A%09%09// remove fake player%0A%09%09mc.world.removeEntityFromWorld(-69
+%0A%09%09// remove fake player%0A%09%09fakePlayer.resetPlayerPosition();%0A%09%09fakePlayer.despawn(
 );%0A%09

Update RemoteViewMod