/*
 *  Copyright 2025-2026 R3944Realms
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package top.r3944realms.eroticdungeongame.content.block.type;

import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.util.ParticleUtils;
import net.minecraft.util.RandomSource;
import net.minecraft.util.valueproviders.UniformInt;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.DirectionalBlock;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.SimpleWaterloggedBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityTicker;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import top.r3944realms.eroticdungeongame.client.gui.screens.OffsetConfigScreen;
import top.r3944realms.eroticdungeongame.content.block.ISeatBlock;
import top.r3944realms.eroticdungeongame.content.block.blockentity.LoveMachineBlockEntity;
import top.r3944realms.eroticdungeongame.core.register.EDGBlockEntities;
import top.r3944realms.lib39.util.shape.ShapeUtil;

import java.util.HashMap;
import java.util.Map;

@SuppressWarnings("deprecation")
public class LoveMachineBlock extends DirectionalBlock implements SimpleWaterloggedBlock, EntityBlock {
    public static final Map<Direction, VoxelShape> SHAPES ;
    public static final BooleanProperty POWERED = BooleanProperty.create("powered");
    public static final Map<String, SpecialAnimationAction> ACTIONS = new HashMap<>();
    public final String type;
    static {
        ACTIONS.put("end_rod", ((level, state, pos, random) -> {
            Direction direction = state.getValue(FACING);
            if(level.getBlockEntity(pos) instanceof LoveMachineBlockEntity be) {
                pos = LoveMachineBlockEntity.calculateOffsetPosition(pos, direction, be);
                double d0 = (double)pos.getX() + 0.55 - (double)(random.nextFloat() * 0.1F);
                double d1 = (double)pos.getY() + 0.55 - (double)(random.nextFloat() * 0.1F);
                double d2 = (double)pos.getZ() + 0.55 - (double)(random.nextFloat() * 0.1F);
                double d3 = 0.4F - (random.nextFloat() + random.nextFloat()) * 0.4F;
                if (random.nextInt(5) == 0) {
                    level.addParticle(ParticleTypes.END_ROD, d0 + (double) direction.getStepX() * d3, d1 + (double) direction.getStepY() * d3, d2 + (double) direction.getStepZ() * d3, random.nextGaussian() * 0.005, random.nextGaussian() * 0.005, random.nextGaussian() * 0.005);
                }
            }

        }));
        ACTIONS.put("lightning_rod", ((level, state, pos, random) -> {
            if (level.isThundering() && (long)level.random.nextInt(200) <= level.getGameTime() % 200L && pos.getY() == level.getHeight(Heightmap.Types.WORLD_SURFACE, pos.getX(), pos.getZ()) - 1) {
                if(level.getBlockEntity(pos) instanceof LoveMachineBlockEntity be) {
                    Direction direction = state.getValue(FACING);
                    pos = LoveMachineBlockEntity.calculateOffsetPosition(pos, direction, be);
                    ParticleUtils.spawnParticlesAlongAxis(state.getValue(FACING).getAxis(), level, pos, 0.125, ParticleTypes.ELECTRIC_SPARK, UniformInt.of(1, 2));
                }

            }
        }));
    }
    public LoveMachineBlock(Properties properties, String type) {
        super(properties);
        this.type = type;
        registerDefaultState(
                getStateDefinition().any()
                        .setValue(FACING, Direction.NORTH)
                        .setValue(BlockStateProperties.WATERLOGGED, Boolean.FALSE)
                        .setValue(POWERED, Boolean.FALSE)
        );
    }

    @Override
    protected void createBlockStateDefinition(StateDefinition.@NotNull Builder<Block, BlockState> builder) {
        super.createBlockStateDefinition(builder);
        builder.add(POWERED, FACING, BlockStateProperties.WATERLOGGED);
    }
    static {
        SHAPES = ShapeUtil.createUniformDirectionMap(
                ShapeUtil.builder()
                        .addPixelBox(3, 0, 3.075, 13, 10, 5.075)
                        .addPixelBox(3, 0, 5.075, 13, 10, 13.075)
                        .build()
        );
        VoxelShape shape = ShapeUtil.builder()
                .addPixelBox(3, 0, 3.0749999999999993, 13, 10, 5.074999999999999)
                .addPixelBox(3, 0, 5.074999999999999, 13, 10, 13.075)
                .build();
        SHAPES.put(Direction.UP, shape);
        shape = ShapeUtil.builder()
                .addPixelBox(3, 6, 3.0749999999999993, 13, 16, 5.074999999999999)
                .addPixelBox(3, 6, 5.074999999999999, 13, 16, 13.075)
                .build();
        SHAPES.put(Direction.DOWN, shape);
    }

    @Override
    public @NotNull InteractionResult use(@NotNull BlockState state, @NotNull Level level, @NotNull BlockPos pos, @NotNull Player player, @NotNull InteractionHand hand, @NotNull BlockHitResult hit) {
        if (!level.isClientSide) return InteractionResult.SUCCESS;

        // 潜行右键打开配置界面
        if (hand.equals(InteractionHand.MAIN_HAND) && player.getItemInHand(hand).is(Items.FEATHER)) {
            return useInClient(pos);
        }
        return InteractionResult.PASS;
    }
    @OnlyIn(Dist.CLIENT)
    public InteractionResult useInClient(BlockPos pos) {
        // 在客户端打开配置屏幕
        Minecraft.getInstance().setScreen(new OffsetConfigScreen(pos));
        return InteractionResult.SUCCESS;
    }

    @Override
    public @NotNull VoxelShape getShape(@NotNull BlockState state, @NotNull BlockGetter level, @NotNull BlockPos pos, @NotNull CollisionContext context) {
        VoxelShape baseShape = SHAPES.get(state.getValue(FACING));
        if (level.getBlockEntity(pos) instanceof LoveMachineBlockEntity blockEntity) {
            if (blockEntity.isOffsetEnabled()) {
                float offsetX = blockEntity.getRenderOffsetX();
                float offsetY = blockEntity.getRenderOffsetY();
                float offsetZ = blockEntity.getRenderOffsetZ();

                // 根据方向调整偏移
                Direction facing = state.getValue(FACING);
                Vec3 adjustedOffset = adjustOffsetByFacing(offsetX, offsetY, offsetZ, facing);

                // 应用偏移到碰撞箱
                return baseShape.move(adjustedOffset.x, adjustedOffset.y, adjustedOffset.z);
            }
        }

        return baseShape;

    }
    /**
     * 根据方块朝向调整偏移向量
     */
    public static @NotNull Vec3 adjustOffsetByFacing(float offsetX, float offsetY, float offsetZ, @NotNull Direction facing) {
        return switch (facing) {
            case DOWN -> new Vec3(-offsetX, -offsetZ, -offsetY);      // 向下：Y变Z，Z变Y
            case UP -> new Vec3(-offsetX, offsetZ, offsetY);          // 向上：Y变Z，Z变Y
            case SOUTH -> new Vec3(-offsetX, offsetY, -offsetZ);  // 180度旋转
            case WEST -> new Vec3(-offsetZ, offsetY, offsetX);    // 90度旋转
            case EAST -> new Vec3(offsetZ, offsetY, -offsetX);    // 270度旋转
            default -> new Vec3(offsetX, offsetY, offsetZ);       // NORTH或默认
        };
    }
    /**
     * 当周围方块变化时检测红石信号（电平触发）
     */
    @SuppressWarnings("deprecation")
    @Override
    public void neighborChanged(@NotNull BlockState state, @NotNull Level level, @NotNull BlockPos pos, @NotNull Block neighborBlock, @NotNull BlockPos fromPos, boolean movedByPiston) {
        if (!level.isClientSide) {
            boolean isPowered = level.hasNeighborSignal(pos);
            boolean wasPowered = state.getValue(POWERED);

            // 获取方块实体
            BlockEntity blockEntity = level.getBlockEntity(pos);
            if (blockEntity instanceof LoveMachineBlockEntity loveMachineBlockEntity) {

                if (isPowered && !wasPowered) {
                    // 红石激活
                    level.setBlock(pos, state.setValue(POWERED, true), UPDATE_ALL);
                    loveMachineBlockEntity.setActive(true);
                    loveMachineBlockEntity.setChanged();
                    // 播放激活音效
                    level.playSound(null, pos,
                            net.minecraft.sounds.SoundEvents.LEVER_CLICK,
                            net.minecraft.sounds.SoundSource.BLOCKS,
                            0.3F, 0.6F);

                } else if (!isPowered && wasPowered) {
                    // 红石失活
                    level.setBlock(pos, state.setValue(POWERED, false), UPDATE_ALL);
                    loveMachineBlockEntity.setActive(false);
                    loveMachineBlockEntity.setStopping(true);
                    loveMachineBlockEntity.setChanged();
                    // 播放失活音效
                    level.playSound(null, pos,
                            net.minecraft.sounds.SoundEvents.LEVER_CLICK,
                            net.minecraft.sounds.SoundSource.BLOCKS,
                            0.3F, 0.5F);
                }

                // 如果状态有变化，通知客户端
                if (isPowered != wasPowered) {
                    level.sendBlockUpdated(pos, state, state.setValue(POWERED, isPowered), UPDATE_ALL);
                }
            }
        }

        super.neighborChanged(state, level, pos, neighborBlock, fromPos, movedByPiston);
    }

    @Override
    public @NotNull FluidState getFluidState(@NotNull BlockState state) {
        return state.getValue(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state);
    }

    /**
     * 在方块被放置时检测红石信号
     */
    @SuppressWarnings("deprecation")
    @Override
    public void onPlace(@NotNull BlockState state, @NotNull Level level, @NotNull BlockPos pos, @NotNull BlockState oldState, boolean movedByPiston) {
        if (!level.isClientSide) {
            boolean isPowered = level.hasNeighborSignal(pos);

            if (isPowered != state.getValue(POWERED)) {
                level.setBlock(pos, state.setValue(POWERED, isPowered), UPDATE_ALL);

                // 更新方块实体状态
                BlockEntity blockEntity = level.getBlockEntity(pos);
                if (blockEntity instanceof LoveMachineBlockEntity loveMachineBlockEntity) {
                    loveMachineBlockEntity.setActive(isPowered);
                    loveMachineBlockEntity.setStopping(!isPowered);
                    loveMachineBlockEntity.setChanged();
                }
            }
        }
    }

    @Override
    public void animateTick(@NotNull BlockState state, @NotNull Level level, @NotNull BlockPos pos, @NotNull RandomSource random) {
        ACTIONS.getOrDefault(type, SpecialAnimationAction.EMPTY).doTick(level, state, pos, random);
    }

    @Nullable
    @Override
    public <T extends BlockEntity> BlockEntityTicker<T> getTicker(@NotNull Level pLevel, @NotNull BlockState pState, @NotNull BlockEntityType<T> pBlockEntityType) {
        return pLevel.isClientSide() ? null : ISeatBlock.createTickerHelper(pBlockEntityType, EDGBlockEntities.LOVE_MACHINE_BLOCK_ENTITY.get(), LoveMachineBlockEntity::serverTick);
    }

    @Override
    public @NotNull BlockState updateShape(@NotNull BlockState state, @NotNull Direction direction, @NotNull BlockState neighborState, @NotNull LevelAccessor level, @NotNull BlockPos pos, @NotNull BlockPos neighborPos) {
        if (state.getValue(BlockStateProperties.WATERLOGGED)) {
            level.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level));
        }
        return super.updateShape(state, direction, neighborState, level, pos, neighborPos);
    }

    @Override
    public BlockState getStateForPlacement(@NotNull BlockPlaceContext context) {
        return this.defaultBlockState().setValue(FACING, context.getNearestLookingDirection().getOpposite());
    }


    @Override
    public BlockEntity newBlockEntity(@NotNull BlockPos blockPos, @NotNull BlockState blockState) {
        return EDGBlockEntities.LOVE_MACHINE_BLOCK_ENTITY.get().create(blockPos, blockState);
    }

    @Override
    public boolean isPathfindable(@NotNull BlockState state, @NotNull BlockGetter level, @NotNull BlockPos pos, @NotNull PathComputationType type) {
        return false;
    }

    @FunctionalInterface
    public interface SpecialAnimationAction {
        SpecialAnimationAction EMPTY = (level, state, pos, random) -> {};
        void doTick(@NotNull Level level, @NotNull BlockState state, @NotNull BlockPos pos, @NotNull RandomSource random);
    }

}
