package com.minelittlepony.unicopia.item;

import org.jetbrains.annotations.Nullable;

import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
import com.minelittlepony.unicopia.util.SoundEmitter;

import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.stat.Stats;
import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult;
import net.minecraft.world.World;

abstract class ProjectileItem extends Item implements ProjectileDelegate {

    private final float projectileDamage;

    public ProjectileItem(Settings settings, float projectileDamage) {
        super(settings);
        this.projectileDamage = projectileDamage;
    }

    @Override
    public TypedActionResult<ItemStack> use(World world, PlayerEntity player, Hand hand) {

        if (isFood() && !player.isSneaking()) {
            return super.use(world, player, hand);
        }

        ItemStack stack = player.getStackInHand(hand);

        SoundEmitter.playSoundAt(player,
                getThrowSound(stack), SoundCategory.NEUTRAL,
                0.5F,
                0.4F / (world.random.nextFloat() * 0.4F + 0.8F));

        if (!world.isClient) {
            world.spawnEntity(createProjectile(stack, world, player));
        }

        player.incrementStat(Stats.USED.getOrCreateStat(this));

        if (!player.getAbilities().creativeMode) {
            stack.decrement(1);
        }

        return TypedActionResult.success(stack, world.isClient());
    }

    protected ProjectileEntity createProjectile(ItemStack stack, World world, @Nullable PlayerEntity player) {
        MagicProjectileEntity projectile = player == null ? new MagicProjectileEntity(world) : new MagicProjectileEntity(world, player);
        projectile.setItem(stack);
        projectile.setThrowDamage(getProjectileDamage(stack));
        if (player != null) {
            projectile.setVelocity(player, player.getPitch(), player.getYaw(), 0, 1.5F, 1);
        }
        return projectile;
    }

    protected abstract SoundEvent getThrowSound(ItemStack stack);

    protected float getProjectileDamage(ItemStack stack) {
        return projectileDamage;
    }

}
