/*
 *  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;

import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;

import java.util.ArrayList;
import java.util.List;

public enum FurnitureShapeType {
    NORMAL {
        @Override
        public BlockPos[] getAllPositions(Level level, BlockState pBlockState, BlockPos pBlockPos) {
            return new BlockPos[]{pBlockPos};
        }
    },
    HORIZONTAL_DOUBLE {
        @Override
        public BlockPos[] getAllPositions(Level level, BlockState pBlockState, BlockPos pBlockPos) {
            List<BlockPos> positions = new ArrayList<>();

            // 总是添加主部件位置
            positions.add(pBlockPos);

            // 检查第二个部件位置
            BlockPos secondPos = pBlockPos.relative(pBlockState.getValue(AbstractSeatBlock.FACING));
            BlockState secondState = level.getBlockState(secondPos);

            // 如果第二个位置是相同的方块类型，添加它
            if (secondState.getBlock() == pBlockState.getBlock()) {
                positions.add(secondPos);
            }

            return positions.toArray(new BlockPos[0]);
        }
    },
    HORIZONTAL_TRIPLE {
        @Override
        public BlockPos[] getAllPositions(Level level, BlockState pBlockState, BlockPos pBlockPos) {
            List<BlockPos> positions = new ArrayList<>();
            Block currentBlock;
            Direction facing = pBlockState.getValue(AbstractSeatBlock.FACING);

            // 总是添加主部件位置（FOOT）
            positions.add(pBlockPos);
            currentBlock = level.getBlockState(pBlockPos.relative(facing)).getBlock();
            // 检查中间部件位置（MIDDLE）
            BlockPos middlePos = pBlockPos.relative(facing);
            BlockState middleState = level.getBlockState(middlePos);

            if (middleState.getBlock() == currentBlock) {
                positions.add(middlePos);
            }

            // 检查顶部部件位置（HEAD）
            BlockPos headPos = pBlockPos.relative(facing, 2);
            BlockState headState = level.getBlockState(headPos);

            if (headState.getBlock() == currentBlock) {
                positions.add(headPos);
            }

            return positions.toArray(new BlockPos[0]);
        }
    },
    VERTICAL_DOUBLE {
        @Override
        public BlockPos[] getAllPositions(Level level, BlockState pBlockState, BlockPos pBlockPos) {
            List<BlockPos> positions = new ArrayList<>();

            // 总是添加主部件位置（FOOT）
            positions.add(pBlockPos);

            // 检查上方部件位置（HEAD）
            BlockPos abovePos = pBlockPos.above();
            BlockState aboveState = level.getBlockState(abovePos);

            if (aboveState.getBlock() == pBlockState.getBlock()) {
                positions.add(abovePos);
            }

            return positions.toArray(new BlockPos[0]);
        }
    },
    VERTICAL_TRIPLE {
        @Override
        public BlockPos[] getAllPositions(Level level, BlockState pBlockState, BlockPos pBlockPos) {
            List<BlockPos> positions = new ArrayList<>();
            Block currentBlock = pBlockState.getBlock();

            // 总是添加主部件位置（FOOT）
            positions.add(pBlockPos);

            // 检查中间部件位置（MIDDLE）
            BlockPos middlePos = pBlockPos.above();
            BlockState middleState = level.getBlockState(middlePos);

            if (middleState.getBlock() == currentBlock) {
                positions.add(middlePos);
            }

            // 检查顶部部件位置（HEAD）
            BlockPos headPos = pBlockPos.above(2);
            BlockState headState = level.getBlockState(headPos);

            if (headState.getBlock() == currentBlock) {
                positions.add(headPos);
            }

            return positions.toArray(new BlockPos[0]);
        }
    },
    OVERRIDE_VERTICAL_TRIPLE {
        @Override
        public BlockPos[] getAllPositions(Level level, BlockState pBlockState, BlockPos pBlockPos) {
            List<BlockPos> positions = new ArrayList<>();
            Block currentBlock = pBlockState.getBlock();
            Direction facing = pBlockState.getValue(AbstractSeatBlock.FACING);

            // 总是添加主部件位置（MIDDLE）
            positions.add(pBlockPos);

            BlockPos right = pBlockPos.relative(facing.getClockWise()); // 右边
            BlockState rightBS = level.getBlockState(right);

            if (rightBS.getBlock() == currentBlock) {
                positions.add(right);
            }

            BlockPos left = pBlockPos.relative(facing.getCounterClockWise()); // 左边
            BlockState leftBS = level.getBlockState(left);

            if (leftBS.getBlock() == currentBlock) {
                positions.add(left);
            }
            positions.add(left);

            return positions.toArray(new BlockPos[0]);
        }
    },
    CRUX {
        @Override
        public BlockPos[] getAllPositions(Level level, BlockState pBlockState, BlockPos pBlockPos) {
            List<BlockPos> positions = new ArrayList<>();
            Block currentBlock = pBlockState.getBlock();
            Direction facing = pBlockState.getValue(AbstractSeatBlock.FACING);

            // 总是添加主部件位置
            positions.add(pBlockPos);

            BlockPos above = pBlockPos.above(); // 上面
            BlockState aboveBS = level.getBlockState(above);
            
            if (aboveBS.getBlock() == currentBlock) {
                positions.add(above);
            }

            BlockPos right = above.relative(facing.getClockWise()); // 右边
            BlockState rightBS = level.getBlockState(right);

            if (rightBS.getBlock() == currentBlock) { 
                positions.add(right);
            }
            
            BlockPos left = above.relative(facing.getCounterClockWise()); // 左边
            BlockState leftBS = level.getBlockState(left);

            if (leftBS.getBlock() == currentBlock) {
                positions.add(left);
            }
            positions.add(left);  
            
            if (leftBS.getBlock() == currentBlock) { 
                positions.add(above);
            }
            return positions.toArray(new BlockPos[0]);
        }
    },
    PETRINE_CROSS {
        @Override
        public BlockPos[] getAllPositions(Level level, BlockState pBlockState, BlockPos pBlockPos) {
            List<BlockPos> positions = new ArrayList<>();
            Block currentBlock = pBlockState.getBlock();
            Direction facing = pBlockState.getValue(AbstractSeatBlock.FACING);

            // 总是添加主部件位置
            positions.add(pBlockPos);

            BlockPos above = pBlockPos.above(); // 上面
            BlockState aboveBS = level.getBlockState(above);

            if (aboveBS.getBlock() == currentBlock) {
                positions.add(above);
            }

            BlockPos right = pBlockPos.relative(facing.getClockWise()); // 右边
            BlockState rightBS = level.getBlockState(right);
            positions.add(right);

            if (rightBS.getBlock() == currentBlock) {
                positions.add(above);
            }

            BlockPos left = pBlockPos.relative(facing.getCounterClockWise()); // 左边
            BlockState leftBS = level.getBlockState(left);
            positions.add(left);

            if (leftBS.getBlock() == currentBlock) {
                positions.add(above);
            }
            return positions.toArray(new BlockPos[0]);
        }
    }
    ;

    /**
     * 获取从主部件开始的所有相连部件位置
     * 参数传入的总是主部件（FOOT部件）的位置
     * 如果某个部件不是相同的方块类型，则停止查找并返回已找到的位置
     *
     * @param level 世界
     * @param pBlockState 主部件的方块状态
     * @param pBlockPos 主部件的位置
     * @return 所有相连的部件位置数组
     */
    public abstract BlockPos[] getAllPositions(Level level, BlockState pBlockState, BlockPos pBlockPos);

    /**
     * 获取理论上的所有位置（不考虑实际是否存在对应方块）
     */
    public BlockPos[] getTheoreticalPositions(BlockState pBlockState, BlockPos pBlockPos) {
        final Direction direction = pBlockState.getValue(AbstractSeatBlock.FACING);
        return switch (this) {
            case NORMAL -> new BlockPos[]{pBlockPos};
            case HORIZONTAL_DOUBLE -> new BlockPos[]{
                    pBlockPos,
                    pBlockPos.relative(direction)
            };
            case HORIZONTAL_TRIPLE -> new BlockPos[]{
                    pBlockPos,
                    pBlockPos.relative(direction),
                    pBlockPos.relative(direction, 2)
            };
            case VERTICAL_DOUBLE -> new BlockPos[]{
                    pBlockPos,
                    pBlockPos.above()
            };
            case VERTICAL_TRIPLE -> new BlockPos[]{
                    pBlockPos,
                    pBlockPos.above(),
                    pBlockPos.above(2)
            };
            case OVERRIDE_VERTICAL_TRIPLE -> new BlockPos[]{
                    pBlockPos,
                    pBlockPos.relative(direction.getClockWise()),
                    pBlockPos.relative(direction.getCounterClockWise())
            };
            case CRUX -> {
                BlockPos above = pBlockPos.above();
                yield new BlockPos[]{
                        pBlockPos,
                        above,
                        above.relative(direction.getClockWise()),
                        above.relative(direction.getCounterClockWise())
                };
            }
            case PETRINE_CROSS -> new BlockPos[] {
                    pBlockPos,
                    pBlockPos.above(),
                    pBlockPos.relative(direction.getClockWise()),
                    pBlockPos.relative(direction.getCounterClockWise())
            };
        };
    }

    /**
     * 检查是否所有部件都存在
     */
    public boolean hasAllParts(Level level, BlockState pBlockState, BlockPos pBlockPos) {
        BlockPos[] theoretical = getTheoreticalPositions(pBlockState, pBlockPos);
        Block currentBlock = pBlockState.getBlock();

        for (BlockPos pos : theoretical) {
            if (level.getBlockState(pos).getBlock() != currentBlock) {
                return false;
            }
        }
        return true;
    }

    /**
     * 获取实际存在的部件数量
     */
    public int getExistingPartCount(Level level, BlockState pBlockState, BlockPos pBlockPos) {
        BlockPos[] positions = getAllPositions(level, pBlockState, pBlockPos);
        return positions.length;
    }
}