package com.straice.smoothdoors.mixin;

import com.straice.smoothdoors.config.SddConfigManager;
import com.straice.smoothdoors.util.ConnectedUtil;
import com.straice.smoothdoors.util.SyncGuard;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.FenceGateBlock;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.state.property.Properties;
import net.minecraft.util.ActionResult;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.block.WireOrientation;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(FenceGateBlock.class)
public class FenceGateBlockMixin {

    @Inject(method = "onUse", at = @At("TAIL"))
    private void sdd$onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit,
                           CallbackInfoReturnable<ActionResult> cir) {
        if (world.isClient) return;
        if (!SddConfigManager.get().connectFenceGates) return;
        if (SyncGuard.isIn()) return;

        BlockState now = world.getBlockState(pos);
        if (!now.contains(Properties.OPEN)) return;

        boolean openNow = now.get(Properties.OPEN);
        BlockPos mate = ConnectedUtil.findPairedFenceGate(world, pos, now);
        if (mate == null) return;

        SyncGuard.run(() -> ConnectedUtil.setFenceGateOpen(world, mate, openNow));
    }

    // 1.21.8+: neighborUpdate(..., @Nullable WireOrientation wireOrientation, boolean notify)
    @Inject(method = "neighborUpdate", at = @At("TAIL"))
    private void sdd$neighborUpdate(BlockState state, World world, BlockPos pos, Block block,
                                    @Nullable WireOrientation wireOrientation, boolean notify, CallbackInfo ci) {
        if (world.isClient) return;
        if (!SddConfigManager.get().connectFenceGates) return;
        if (!SddConfigManager.get().redstoneDoubleFenceGates) return;
        if (SyncGuard.isIn()) return;

        BlockState now = world.getBlockState(pos);
        if (!now.contains(Properties.OPEN)) return;

        boolean openNow = now.get(Properties.OPEN);
        BlockPos mate = ConnectedUtil.findPairedFenceGate(world, pos, now);
        if (mate == null) return;

        SyncGuard.run(() -> ConnectedUtil.setFenceGateOpen(world, mate, openNow));
    }
}
