package studio.halbear.hem.procedures;

import studio.halbear.hem.HemModVariables;
import studio.halbear.hem.HemMod;

import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.event.TickEvent;

import net.minecraft.world.World;
import net.minecraft.world.IWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.entity.Entity;
import net.minecraft.block.Blocks;

import java.util.Map;
import java.util.HashMap;

public class SpeedCalculationProcedure {
	@Mod.EventBusSubscriber
	private static class GlobalTrigger {
		@SubscribeEvent
		public static void onPlayerTick(TickEvent.PlayerTickEvent event) {
			if (event.phase == TickEvent.Phase.END) {
				Entity entity = event.player;
				World world = entity.world;
				double i = entity.getPosX();
				double j = entity.getPosY();
				double k = entity.getPosZ();
				Map<String, Object> dependencies = new HashMap<>();
				dependencies.put("x", i);
				dependencies.put("y", j);
				dependencies.put("z", k);
				dependencies.put("world", world);
				dependencies.put("entity", entity);
				dependencies.put("event", event);
				executeProcedure(dependencies);
			}
		}
	}

	public static void executeProcedure(Map<String, Object> dependencies) {
		if (dependencies.get("world") == null) {
			if (!dependencies.containsKey("world"))
				HemMod.LOGGER.warn("Failed to load dependency world for procedure SpeedCalculation!");
			return;
		}
		if (dependencies.get("x") == null) {
			if (!dependencies.containsKey("x"))
				HemMod.LOGGER.warn("Failed to load dependency x for procedure SpeedCalculation!");
			return;
		}
		if (dependencies.get("z") == null) {
			if (!dependencies.containsKey("z"))
				HemMod.LOGGER.warn("Failed to load dependency z for procedure SpeedCalculation!");
			return;
		}
		if (dependencies.get("entity") == null) {
			if (!dependencies.containsKey("entity"))
				HemMod.LOGGER.warn("Failed to load dependency entity for procedure SpeedCalculation!");
			return;
		}
		IWorld world = (IWorld) dependencies.get("world");
		double x = dependencies.get("x") instanceof Integer ? (int) dependencies.get("x") : (double) dependencies.get("x");
		double z = dependencies.get("z") instanceof Integer ? (int) dependencies.get("z") : (double) dependencies.get("z");
		Entity entity = (Entity) dependencies.get("entity");
		double TPS = 0;
		double Dx = 0;
		double Dy = 0;
		double Ylevel = 0;
		double Iterations = 0;
		if (entity.ticksExisted % 10 == 0) {
			Ylevel = (entity.getPosY());
			Iterations = 0;
			for (int index0 = 0; index0 < (int) (300); index0++) {
				Iterations = (Iterations + 1);
				Ylevel = (Ylevel - 1);
				if (!((world.getBlockState(new BlockPos(x, Ylevel, z))).getBlock() == Blocks.AIR)) {
					break;
				}
			}
			if (Iterations >= 300) {
				{
					double _setval = 9999.9;
					entity.getCapability(HemModVariables.PLAYER_VARIABLES_CAPABILITY, null).ifPresent(capability -> {
						capability.Altimeter = _setval;
						capability.syncPlayerVariables(entity);
					});
				}
			} else {
				{
					double _setval = ((entity.getPosY() - Ylevel) * 3.28084);
					entity.getCapability(HemModVariables.PLAYER_VARIABLES_CAPABILITY, null).ifPresent(capability -> {
						capability.Altimeter = _setval;
						capability.syncPlayerVariables(entity);
					});
				}
			}
		}
		if (entity.ticksExisted % 5 == 0) {
			net.minecraft.server.MinecraftServer server = net.minecraftforge.fml.LogicalSidedProvider.INSTANCE
					.get(net.minecraftforge.fml.LogicalSide.SERVER);
			double meanTickTime = java.util.Arrays.stream(server.tickTimeArray).average().orElse(0.0) * 1.0E-6D;
			Dx = (entity.getPosX() - (entity.getCapability(HemModVariables.PLAYER_VARIABLES_CAPABILITY, null)
					.orElse(new HemModVariables.PlayerVariables())).LastPosX);
			Dy = (entity.getPosZ() - (entity.getCapability(HemModVariables.PLAYER_VARIABLES_CAPABILITY, null)
					.orElse(new HemModVariables.PlayerVariables())).LastPosZ);
			{
				double _setval = ((entity.getCapability(HemModVariables.PLAYER_VARIABLES_CAPABILITY, null)
						.orElse(new HemModVariables.PlayerVariables())).VehicleOdometerMetres * 0.000621371);
				entity.getCapability(HemModVariables.PLAYER_VARIABLES_CAPABILITY, null).ifPresent(capability -> {
					capability.VehicleOdometer = _setval;
					capability.syncPlayerVariables(entity);
				});
			}
			{
				double _setval = (entity.getPosX());
				entity.getCapability(HemModVariables.PLAYER_VARIABLES_CAPABILITY, null).ifPresent(capability -> {
					capability.LastPosX = _setval;
					capability.syncPlayerVariables(entity);
				});
			}
			{
				double _setval = (entity.getPosZ());
				entity.getCapability(HemModVariables.PLAYER_VARIABLES_CAPABILITY, null).ifPresent(capability -> {
					capability.LastPosZ = _setval;
					capability.syncPlayerVariables(entity);
				});
			}
			TPS = Math.min(20.0, 1000.0 / Math.max(1.0, meanTickTime));;
			{
				double _setval = Math.round(((Math.abs(Dx) + Math.abs(Dy)) / (20.0 / TPS)) * 4 * 2.23694);
				entity.getCapability(HemModVariables.PLAYER_VARIABLES_CAPABILITY, null).ifPresent(capability -> {
					capability.GoalMPH = _setval;
					capability.syncPlayerVariables(entity);
				});
			}
		}
		if ((entity.getCapability(HemModVariables.PLAYER_VARIABLES_CAPABILITY, null).orElse(new HemModVariables.PlayerVariables())).MPH != (entity
				.getCapability(HemModVariables.PLAYER_VARIABLES_CAPABILITY, null).orElse(new HemModVariables.PlayerVariables())).GoalMPH) {
			if ((entity.getCapability(HemModVariables.PLAYER_VARIABLES_CAPABILITY, null).orElse(new HemModVariables.PlayerVariables())).MPH > (entity
					.getCapability(HemModVariables.PLAYER_VARIABLES_CAPABILITY, null).orElse(new HemModVariables.PlayerVariables())).GoalMPH) {
				{
					double _setval = ((entity.getCapability(HemModVariables.PLAYER_VARIABLES_CAPABILITY, null)
							.orElse(new HemModVariables.PlayerVariables())).MPH - 1);
					entity.getCapability(HemModVariables.PLAYER_VARIABLES_CAPABILITY, null).ifPresent(capability -> {
						capability.MPH = _setval;
						capability.syncPlayerVariables(entity);
					});
				}
			} else if ((entity.getCapability(HemModVariables.PLAYER_VARIABLES_CAPABILITY, null)
					.orElse(new HemModVariables.PlayerVariables())).MPH < (entity.getCapability(HemModVariables.PLAYER_VARIABLES_CAPABILITY, null)
							.orElse(new HemModVariables.PlayerVariables())).GoalMPH) {
				{
					double _setval = ((entity.getCapability(HemModVariables.PLAYER_VARIABLES_CAPABILITY, null)
							.orElse(new HemModVariables.PlayerVariables())).MPH + 1);
					entity.getCapability(HemModVariables.PLAYER_VARIABLES_CAPABILITY, null).ifPresent(capability -> {
						capability.MPH = _setval;
						capability.syncPlayerVariables(entity);
					});
				}
			}
		}
	}
}
