package me.loganb1max.minions.model;

import com.google.common.collect.ImmutableSet;
import lombok.Getter;
import me.loganb1max.minions.MinionsPlugin;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.Set;
import java.util.UUID;

@Getter
public abstract class AbstractMinion implements Minion {

	private final UUID owner;
	private final String ownerName;
	private Location location;
	private double energy;
	private int level;
	private Set<Block> linkedBlocks;
	private ArmorStand stand;

	private double offset = 0.1;

	public AbstractMinion(final Player owner) {
		this.owner = owner.getUniqueId();
		this.ownerName = owner.getName();
	}

	public void spawn(final Location location) {
		this.location = location;
		if (this.stand == null) {
			this.stand = (ArmorStand) location.getWorld().spawnEntity(location, EntityType.ARMOR_STAND);
			this.stand.setSmall(true);
			this.stand.setBasePlate(false);
			this.stand.setGravity(false);
			this.stand.setCanPickupItems(false);
			this.stand.setRemoveWhenFarAway(false);
			this.stand.setMarker(false);
			this.equipEquipment(this.stand);
			MinionsPlugin.getInstance().getMinionManager().getMinions().add(this);
		} else {
			this.stand.teleport(location);
		}
	}

	public void despawn(final Player player) {
		if (this.stand == null) return;
		this.location = null;
		this.stand.remove();
		this.stand = null;
		this.linkedBlocks.clear();
		player.getInventory().addItem(this.toItemStack()).forEach((integer, itemStack) -> player.getWorld().dropItemNaturally(player.getLocation(), itemStack));
	}

	@Override
	public void pickup(Player player) {
		this.despawn(player);
		MinionsPlugin.getInstance().getMinionManager().getMinions().remove(this);
	}

	@Override
	public Set<Block> getLinkedBlocks() {
		return ImmutableSet.copyOf(this.linkedBlocks);
	}

	@Override
	public double gainEnergy(final double amount) {
		return this.energy += amount;
	}

	@Override
	public double consumeEnergy(final double amount) {
		return this.energy -= amount;
	}

	@Override
	public UUID getId() {
		if (this.stand == null) return null;
		return this.stand.getUniqueId();
	}

	@Override
	public void tick() {
		if (this.stand == null) return;
		if (this.stand.getRightArmPose().getX() > 300) offset = -0.1;
		if (this.stand.getRightArmPose().getX() < 230) offset = 0.1;
		this.stand.setRightArmPose(this.stand.getRightArmPose().add(offset, 0, 0));
		this.stand.setFireTicks(0);
	}

	public abstract ItemStack toItemStack();

	public abstract void equipEquipment(final ArmorStand stand);

}
