package top.r3944realms.eroticdungeongame.content.block;

import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
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.EnumProperty;
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 org.jetbrains.annotations.Nullable;
import top.r3944realms.eroticdungeongame.content.block.blockentity.SeatBlockEntity;
import top.r3944realms.eroticdungeongame.content.block.part.SeatPart;

import java.util.Map;

@SuppressWarnings("unused")
public abstract class AbstractTwoPartSeatBlock extends AbstractSeatBlock {
    public static final EnumProperty<SeatPart> PART = EnumProperty.create("part", SeatPart.class);
    protected Map<SeatPart, Map<Direction, VoxelShape>> shapeMap;
    public AbstractTwoPartSeatBlock(Properties properties) {
        super(properties);
        registerDefaultState(getStateDefinition().any().setValue(PART, SeatPart.FOOT));
    }

    @Override
    public BlockEntity newBlockEntity(@NotNull BlockPos blockPos, @NotNull BlockState blockState) {
        if(blockState.getValue(PART) == SeatPart.FOOT) {
            return new SeatBlockEntity(blockPos, blockState);
        }
        return null;
    }

    @Override
    public @NotNull VoxelShape getShape(@NotNull BlockState blockState, @NotNull BlockGetter blockGetter, @NotNull BlockPos blockPos, @NotNull CollisionContext collisionContext) {
        return shapeMap.get(blockState.getValue(PART)).get(blockState.getValue(FACING));
    }

    @Override
    protected void createBlockStateDefinition(StateDefinition.@NotNull Builder<Block, BlockState> builder) {
        builder.add(PART, OCCUPIED, FACING, FLIPPED);
    }

    @Override
    public BlockState getStateForPlacement(@NotNull BlockPlaceContext context) {
        Direction direction = context.getClickedFace();
        BlockPos blockPos = context.getClickedPos();
        Level level = context.getLevel();
        if (level.isInWorldBounds(blockPos) && level.getBlockState(blockPos).canBeReplaced(context)) {
            return defaultBlockState()
                    .setValue(FACING, direction)
                    .setValue(PART, SeatPart.FOOT)
                    .setValue(OCCUPIED, Boolean.FALSE)
                    .setValue(FLIPPED, Boolean.FALSE);
        }
        return null;
    }

    @Override
    public void setPlacedBy(@NotNull Level level, @NotNull BlockPos pos, @NotNull BlockState state, @Nullable LivingEntity placer, @NotNull ItemStack stack) {
        level.setBlock(pos.relative(state.getValue(FACING)), state.setValue(PART, SeatPart.HEAD), Block.UPDATE_ALL);
    }

    @Override
    public @NotNull InteractionResult use(@NotNull BlockState blockState, @NotNull Level level, @NotNull BlockPos blockPos, @NotNull Player player, @NotNull InteractionHand hand, @NotNull BlockHitResult hitResult) {
        BlockPos blockPos1 = blockPos;
        if(SeatPart.HEAD == blockState.getValue(PART)) {
            blockPos1 = blockPos.relative(blockState.getValue(FACING).getOpposite());
        }
        return super.use(blockState, level, blockPos1, player, hand, hitResult);
    }

    @Override
    public void onRemove(@NotNull BlockState blockState, Level level, @NotNull BlockPos blockPos, @NotNull BlockState newState, boolean moved) {
        if (blockState.getBlock() != newState.getBlock()) {
            Direction direction = blockState.getValue(FACING);
            BlockPos blockPos1 = blockState.getValue(PART) == SeatPart.FOOT ? blockPos.relative(direction) : blockPos.relative(direction.getOpposite());
            BlockState blockState1 = level.getBlockState(blockPos1);
            if (blockState1.getBlock() == this && blockState1.getValue(PART) != blockState.getValue(PART)) {
                level.removeBlock(blockPos1, false);
            }
        }
        super.onRemove(blockState, level, blockPos, newState, moved);
    }
}
