package net.moonleay.gimble.mixin;

import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.network.ClientPlayerInteractionManager;
import net.minecraft.client.particle.ParticleManager;
import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.moonleay.gimble.client.editor.ClientEditor;
import net.moonleay.gimble.editor.state.mode.Capability;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

@Mixin(MinecraftClient.class)
public abstract class ReplaceModeMixin {


    @Shadow protected abstract void handleBlockBreaking(boolean breaking);

    @Shadow @Nullable public ClientPlayerInteractionManager interactionManager;

    @Shadow @Final public ParticleManager particleManager;

    @Shadow @Nullable public ClientPlayerEntity player;

    @Shadow @Nullable public HitResult crosshairTarget;

    @Inject(method = "doItemUse", at = @At("HEAD"))
    private void replaceBlock(CallbackInfo ci) {
        assert this.player != null;
        if (!this.player.isCreative())
            return;
        // Check if should run
        if (!ClientEditor.INSTANCE.shouldClient(Capability.REPLACE))
            return; // Mode is not REPLACE, ignore
        MinecraftClient client = MinecraftClient.getInstance();
        assert this.interactionManager != null;
        if (!this.interactionManager.getCurrentGameMode().isCreative())
            return;
        if (!(this.crosshairTarget instanceof BlockHitResult blockHitResult))
            return;
        if (blockHitResult == null)
            return;

        // Gather data
        BlockPos pos = blockHitResult.getBlockPos();
        Direction direction = blockHitResult.getSide();
        BlockState blockState = client.world.getBlockState(pos);

        // Start sending shit
        client.getTutorialManager().onBlockBreaking(client.world, pos, blockState, 1.0F);
        this.interactionManager.sendSequencedPacket(client.world, sequence -> {
            this.interactionManager.breakBlock(pos);
            return new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, pos, direction, sequence);
        });
        this.player.swingHand(Hand.MAIN_HAND);
    }

}
