package me.loganb1max.minionsplus.model.minions;

import me.loganb1max.minionsplus.MinionsPlus;
import me.loganb1max.minionsplus.model.Minion;
import me.loganb1max.minionsplus.util.ItemBuilder;
import me.loganb1max.minionsplus.util.Replacer;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;

public class FisherMinion extends Minion {

	public FisherMinion(final UUID owner, final String ownerName) {
		super(
				MinionsPlus.getInstance().getConfig().getConfigurationSection("Fisher"),
				owner,
				ownerName
		);
	}

	public FisherMinion(final UUID owner, final String ownerName, final Location location, final double energy, final int level, final Set<Block> linkedBlocks) {
		this(owner, ownerName);
		setLocation(location);
		setEnergy(energy);
		setLevel(level);
		setLinkedBlocks(linkedBlocks);
		findStand();
	}

	public double getChancePerBlockPerSecond(final int level) {
		return getSection().getDouble("Levels." + level + ".ChancePerBlockPerSecond", 0.0);
	}

	public int getRadius(final int level) {
		return getSection().getInt("Levels." + level + ".Radius", 1);
	}

	@Override
	public void tick() {
		if (getEnergy() < getEnergyPerUse(getLevel())) return;
		final int radius = getRadius(getLevel());
		final List<ItemStack> drops = new ArrayList<>();
		for (int x = getLocation().getBlockX() - radius; x < getLocation().getBlockX() + radius; x++) {
			for (int y = getLocation().getBlockY() - radius; y < getLocation().getBlockY() + radius; y++) {
				for (int z = getLocation().getBlockZ() - radius; z < getLocation().getBlockZ() + radius; z++) {
					final Block block = getLocation().getWorld().getBlockAt(x, y, z);
					if (block.getType() != Material.WATER && block.getType() != Material.STATIONARY_WATER) continue;
					if (ThreadLocalRandom.current().nextDouble(0.000000, 100.000000) > getChancePerBlockPerSecond(getLevel())) continue;
					drops.add(ItemBuilder.of(Material.RAW_FISH).build());
				}
			}
		}
		if (!drops.isEmpty()) consumeEnergy(getEnergyPerUse(getLevel()));
		getLinkedBlocks().stream().filter(b -> b.getState() instanceof InventoryHolder).forEachOrdered(b -> {
			InventoryHolder inv = (InventoryHolder) b.getState();
			final Collection<ItemStack> remaining = inv.getInventory().addItem(drops.toArray(new ItemStack[] {})).values();
			drops.clear();
			drops.addAll(remaining);
		});
		if (!drops.isEmpty()) {
			drops.forEach(item -> getLocation().getWorld().dropItemNaturally(getLocation(), item));
		}
	}

	@Override
	public Replacer getReplacer() {
		final DecimalFormat format = new DecimalFormat("#.#");
		return Replacer.create()
				.add("%level%", String.valueOf(getLevel()))
				.add("%energy%", format.format(getEnergy()))
				.add("%owner%", getOwnerName())
				.add("%radius%", String.valueOf(getRadius(getLevel())))
				.add("%chanceperblockpersecond%", String.valueOf(getChancePerBlockPerSecond(getLevel())));
	}

}
