/*
 *  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.ChatFormatting;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.network.chat.Component;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.WoodType;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.NotNull;
import top.r3944realms.eroticdungeongame.content.block.IWoodTypeBlock;
import top.r3944realms.eroticdungeongame.content.block.blockentity.BaseSeatBlockEntity;
import top.r3944realms.eroticdungeongame.content.block.multiply.vertical.VerticalDoubleSeatBlock;
import top.r3944realms.eroticdungeongame.content.block.part.SeatPart;
import top.r3944realms.eroticdungeongame.content.item.DeviceKeyItem;
import top.r3944realms.eroticdungeongame.core.register.EDGBlockEntities;
import top.r3944realms.eroticdungeongame.core.register.EDGItems;
import top.r3944realms.eroticdungeongame.core.service.SeatService;
import top.r3944realms.lib39.util.lang.Pair;
import top.r3944realms.lib39.util.shape.ShapeUtil;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public class PilloryBlock extends VerticalDoubleSeatBlock implements IWoodTypeBlock {
    private final WoodType woodType;
    protected Map<Pair<SeatPart, Boolean>, Map<Direction, VoxelShape>> shapeMap;
    public static final BooleanProperty CLOSED = BooleanProperty.create("closed");

    public PilloryBlock(WoodType woodType) {
        super(PROPERTIES);
        this.woodType = woodType;
        registerDefaultState(
                setPrimaryStatePart(
                        getStateDefinition().any()
                                .setValue(PART, getPrimaryPart())
                                .setValue(FACING, Direction.NORTH)
                                .setValue(OCCUPIED, Boolean.FALSE)
                                .setValue(FLIPPED, Boolean.FALSE)
                                .setValue(WATERLOGGED, Boolean.FALSE)
                                .setValue(CLOSED, Boolean.FALSE)
                )
        );
    }

    public WoodType getWoodType() {
        return woodType;
    }

    public void setClosed(@NotNull Level level, BlockPos pos, @NotNull BlockState state, boolean v) {
        level.setBlock(pos, state.setValue(CLOSED, v), UPDATE_NEIGHBORS);
    }

    public boolean getClosed(@NotNull BlockState state) {
        return state.getValue(CLOSED);
    }

    @Override
    public @NotNull InteractionResult use(@NotNull BlockState blockState, @NotNull Level level, @NotNull BlockPos blockPos, @NotNull Player player, @NotNull InteractionHand hand, @NotNull BlockHitResult hitResult) {
        if (player.getItemInHand(InteractionHand.MAIN_HAND).is(EDGItems.DEVICE_KEY.get())) return InteractionResult.PASS;
        if (!player.isCrouching() && !level.isClientSide && blockState.getValue(PART) == SeatPart.HEAD) {
            boolean value = !getClosed(blockState);
            BlockEntity blockEntity = getBlockEntity(blockState, level, getPrimaryPartPos(blockState, blockPos));
            if (value) {
                if (!blockState.getValue(OCCUPIED)) {
                    List<Player> entitiesOfClass = level.getEntitiesOfClass(Player.class, AABB.ofSize(blockPos.getCenter(), 2.0, 2.0, 2.0));
                    if (!entitiesOfClass.isEmpty()){
                        Player player1 = entitiesOfClass.get(0);
                        if (blockEntity instanceof BaseSeatBlockEntity baseSeat) {

                                if (Objects.equals(player.getUUID(), baseSeat.getBoundPlayerUUID())) {
                                    return InteractionResult.FAIL;
                                }
                                if (!baseSeat.bindPlayerToSeat(level, blockPos.below(), blockState, player1))
                                    return InteractionResult.FAIL;
                        }
                    }
                }
            } else {

                if (blockEntity instanceof BaseSeatBlockEntity baseSeat) {
                    if (Objects.equals(player.getUUID(), baseSeat.getBoundPlayerUUID())) {
                        return InteractionResult.FAIL;
                    }
                    if (!baseSeat.hasLockCode() || DeviceKeyItem.isMatch(player.getItemInHand(hand), baseSeat.getLockCode())) {
                        SeatService.releasePlayer(level, blockPos);
                    } else {
                        player.displayClientMessage(Component.translatable("eroticdungeongame.message.quit.failed.locked").withStyle(ChatFormatting.RED), true);
                        return InteractionResult.FAIL;
                    }
                }
            }
            //TODO: 声音
            level.setBlock(blockPos, blockState.setValue(CLOSED, value),UPDATE_ALL_IMMEDIATE);
        }
        return InteractionResult.SUCCESS;
    }

    @Override
    public InteractionResult useOnPrimaryPart(@NotNull BlockState useBlockState, @NotNull Level level, @NotNull BlockPos primaryBlockPos, @NotNull Player player, @NotNull InteractionHand hand, @NotNull BlockHitResult hitResult) {
       return super.useOnPrimaryPart(useBlockState, level, primaryBlockPos, player, hand, hitResult);
    }

    @Override
    public void setupShape() {
        VoxelShape head_open = ShapeUtil.builder()
                .addPixelBox(16 * -0.0625, 0, 16 * 0.375, 16 * 0.125, 16 * 0.5625, 16 * 0.625)
                .addPixelBox(16 * 0.875, 0, 16 * 0.375, 16 * 1.0625, 16 * 0.5625, 16 * 0.625)
                .addPixelBox(16 * 0.125, 16 * 0.1875, 16 * 0.4375, 16 * 0.875, 16 * 0.5, 16 * 0.5625)
                .build();

        VoxelShape head_close = ShapeUtil.builder()
                .addPixelBox(16 * -0.0625, 0, 16 * 0.375, 16 * 0.125, 16 * 0.5625, 16 * 0.625)
                .addPixelBox(16 * 0.875, 0, 16 * 0.375, 16 * 1.0625, 16 * 0.5625, 16 * 0.625)
                .addPixelBox(16 * 0.125, 0, 16 * 0.4375, 16 * 0.875, 16 * 0.25, 16 * 0.5625)
                .build();
        VoxelShape foot = ShapeUtil.builder()
                .addPixelBox(16 * -0.0625, 0, 16 * 0.375, 16 * 0.125, 16, 16 * 0.625)
                .addPixelBox(16 * 0.875, 0, 16 * 0.375, 16 * 1.0625, 16, 16 * 0.625)
                .addPixelBox(16 * 0.125, 16 * 0.625, 16 * 0.4375, 16 * 0.875, 16 * 0.9375, 16 * 0.5625)
                .build();
        Map<Pair<SeatPart, Boolean>, Map<Direction, VoxelShape>> shapes = new HashMap<>();
        shapes.put(Pair.of(SeatPart.HEAD, false), ShapeUtil.createUniformDirectionMap(head_open));
        shapes.put(Pair.of(SeatPart.HEAD, true), ShapeUtil.createUniformDirectionMap(head_close));
        Map<Direction, VoxelShape> uniformDirectionMap = ShapeUtil.createUniformDirectionMap(foot);
        shapes.put(Pair.of(SeatPart.FOOT, true), uniformDirectionMap);
        shapes.put(Pair.of(SeatPart.FOOT, false), uniformDirectionMap);
        this.shapeMap = shapes;
    }
    @Override
    public @NotNull VoxelShape getShape(@NotNull BlockState blockState, @NotNull BlockGetter blockGetter,
                                        @NotNull BlockPos blockPos, @NotNull CollisionContext collisionContext) {
        SeatPart part = blockState.getValue(PART);
        Boolean state = blockState.getValue(CLOSED);
        Direction facing = blockState.getValue(FACING);

        if (shapeMap != null) {
            Pair<SeatPart, Boolean> key = Pair.of(part, state);
            if (shapeMap.containsKey(key) && shapeMap.get(key).containsKey(facing)) {
                return shapeMap.get(key).get(facing);
            }
        }
        return super.getShape(blockState, blockGetter, blockPos, collisionContext);
    }

    @Override
    protected void createBlockStateDefinition(StateDefinition.@NotNull Builder<Block, BlockState> builder) {
        super.createBlockStateDefinition(builder);
        builder.add(CLOSED);
    }

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