// Path: src/main/java/de/dosmike/sponge/vshop/systems/pluginfilter/FilterResolutionException.java
// public class FilterResolutionException extends Exception {
// 
//     public FilterResolutionException() {
//     }
// 
//     public FilterResolutionException(String message) {
//         super(message);
//     }
// 
//     public FilterResolutionException(String message, Throwable cause) {
//         super(message, cause);
//     }
// 
//     public FilterResolutionException(Throwable cause) {
//         super(cause);
//     }
// }


import com.flowpowered.math.TrigMath;
import com.flowpowered.math.vector.Vector3d;
import de.dosmike.sponge.megamenus.impl.RenderManager;
import de.dosmike.sponge.vshop.systems.pluginfilter.FilterResolutionException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.command.CommandSource;
import org.spongepowered.api.data.DataQuery;
import org.spongepowered.api.data.key.Keys;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.entity.living.player.User;
import org.spongepowered.api.item.inventory.ItemStack;
import org.spongepowered.api.item.inventory.ItemStackSnapshot;
import org.spongepowered.api.service.economy.Currency;
import org.spongepowered.api.world.Location;
import org.spongepowered.api.world.World;
import org.spongepowered.api.world.extent.Extent;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.*;
import java.util.stream.Collectors;
package de.dosmike.sponge.vshop;



public class Utilities {

	/**
	 * to prevent bugs from spamming actions, we'll use this to lock any actions
	 * until 1 tick after the inventory handler finished
	 */
	public static final Set<UUID> actionUnstack = new HashSet<>();

	/**
	 * remembers what player is viewing what shop as Player <-> Shop mapping
	 */
	static final Map<UUID, UUID> openShops = new HashMap<>();

	public static @Nullable UUID getOpenShopFor(Player player) {
		return openShops.get(player.getUniqueId());
	}

	public static void _openShops_remove(Player player) {
		openShops.remove(player.getUniqueId());
	}

	public static void _openShops_add(Player player, UUID shopID) {
		openShops.put(player.getUniqueId(), shopID);
	}

	public static void redrawAllShopMenus(@NotNull ItemStack withItem) {
		//get all shops that have the specified item in their listing
		// Im doing this first, because shops can be opened by multiple players
		// and I don't want to test shops twice for performance
		Set<UUID> prefilteredShops = openShops.values().stream()
				.unordered().distinct()
				.filter(uuid -> VillagerShops.getShopFromShopId(uuid)
						.map(se -> se.getMenu().getAllItems().stream().anyMatch(si -> {
							try {
								return si.test(withItem);
// Path: src/main/java/de/dosmike/sponge/vshop/systems/pluginfilter/FilterResolutionException.java
// public class FilterResolutionException extends Exception {
// 
//     public FilterResolutionException() {
//     }
// 
//     public FilterResolutionException(String message) {
//         super(message);
//     }
// 
//     public FilterResolutionException(String message, Throwable cause) {
//         super(message, cause);
//     }
// 
//     public FilterResolutionException(Throwable cause) {
//         super(cause);
//     }
// }


// Path: src/main/java/de/dosmike/sponge/vshop/Utilities.java
import com.flowpowered.math.TrigMath;
import com.flowpowered.math.vector.Vector3d;
import de.dosmike.sponge.megamenus.impl.RenderManager;
import de.dosmike.sponge.vshop.systems.pluginfilter.FilterResolutionException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.command.CommandSource;
import org.spongepowered.api.data.DataQuery;
import org.spongepowered.api.data.key.Keys;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.entity.living.player.User;
import org.spongepowered.api.item.inventory.ItemStack;
import org.spongepowered.api.item.inventory.ItemStackSnapshot;
import org.spongepowered.api.service.economy.Currency;
import org.spongepowered.api.world.Location;
import org.spongepowered.api.world.World;
import org.spongepowered.api.world.extent.Extent;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.*;
import java.util.stream.Collectors;

package de.dosmike.sponge.vshop;



public class Utilities {

	/**
	 * to prevent bugs from spamming actions, we'll use this to lock any actions
	 * until 1 tick after the inventory handler finished
	 */
	public static final Set<UUID> actionUnstack = new HashSet<>();

	/**
	 * remembers what player is viewing what shop as Player <-> Shop mapping
	 */
	static final Map<UUID, UUID> openShops = new HashMap<>();

	public static @Nullable UUID getOpenShopFor(Player player) {
		return openShops.get(player.getUniqueId());
	}

	public static void _openShops_remove(Player player) {
		openShops.remove(player.getUniqueId());
	}

	public static void _openShops_add(Player player, UUID shopID) {
		openShops.put(player.getUniqueId(), shopID);
	}

	public static void redrawAllShopMenus(@NotNull ItemStack withItem) {
		//get all shops that have the specified item in their listing
		// Im doing this first, because shops can be opened by multiple players
		// and I don't want to test shops twice for performance
		Set<UUID> prefilteredShops = openShops.values().stream()
				.unordered().distinct()
				.filter(uuid -> VillagerShops.getShopFromShopId(uuid)
						.map(se -> se.getMenu().getAllItems().stream().anyMatch(si -> {
							try {
								return si.test(withItem);
							} catch (FilterResolutionException e) {