/*
 *  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.datagen.provider;

import net.minecraft.core.Direction;
import net.minecraft.data.PackOutput;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraftforge.client.model.generators.BlockStateProvider;
import net.minecraftforge.client.model.generators.ConfiguredModel;
import net.minecraftforge.client.model.generators.ModelFile;
import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraftforge.registries.ForgeRegistries;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import top.r3944realms.eroticdungeongame.EroticDungeon;
import top.r3944realms.eroticdungeongame.content.block.multiply.AbstractCrossSeatBlock;
import top.r3944realms.eroticdungeongame.content.block.multiply.AbstractThreePartSeatBlock;
import top.r3944realms.eroticdungeongame.content.block.multiply.AbstractTwoPartSeatBlock;
import top.r3944realms.eroticdungeongame.content.block.multiply.vertical.VerticalTripleSeatBlock;
import top.r3944realms.eroticdungeongame.content.block.part.AdvanceSeatPart;
import top.r3944realms.eroticdungeongame.content.block.part.CrossSeatPart;
import top.r3944realms.eroticdungeongame.content.block.part.SeatPart;
import top.r3944realms.eroticdungeongame.content.block.type.*;
import top.r3944realms.eroticdungeongame.core.register.EDGBlocks;
import top.r3944realms.eroticdungeongame.util.WoodTypeHelper;

public class EDGBlockStatesProvider extends BlockStateProvider {
    public EDGBlockStatesProvider(PackOutput output, ExistingFileHelper exFileHelper) {
        super(output, EroticDungeon.MOD_ID, exFileHelper);
    }

    private ResourceLocation key(Block block) {
        return ForgeRegistries.BLOCKS.getKey(block);
    }

    public String name(Block block) {
        return key(block).getPath();
    }

    @Override
    protected void registerStatesAndModels() {
        generateBedBlockStates();
        generateIronCageBlockStatesSimple();
        generateSpanishDonkeyBlockStatesSimple();
        generateRackBlockStates();
        generateXCrossBlockStates();
        generateCruxBlockStates();
        generatePetrineCrossBlockStates();
        generatePilloryBlockStates();
        generateWallRackBlockStates();
        generateCuffPoleStates();
        generateProneBenchBlockStatesSimple();
        generateHandingPostBlockStates();
        generateDungeonCraftingBlockStates();
        generateLoveMachineBlockStatesSimple();
    }
    private void generateDungeonCraftingBlockStates() {
        Block block = EDGBlocks.DUNGEON_CRAFTING_TABLE.get();
        ModelFile model = new ModelFile.ExistingModelFile(
                EroticDungeon.rl( "block/dungeon_crafting_table"),
                models().existingFileHelper
        );
        getVariantBuilder(block).forAllStates(blockState ->
                ConfiguredModel.builder()
                        .modelFile(model)
                        .build()
        );
    }
    private void generateIronCageBlockStatesSimple() {
        Block ironCageBlock = EDGBlocks.IRON_CAGE.get();

        // 创建GeckoLib模型引用
        ModelFile geckoModel = new ModelFile.ExistingModelFile(
                EroticDungeon.rl( "block/iron_cage"),
                models().existingFileHelper
        );

        getVariantBuilder(ironCageBlock).forAllStates(state -> {
            Direction direction = state.getValue(BlockStateProperties.HORIZONTAL_FACING);
            int rotationY = getMainWestRotationY(direction);

            return ConfiguredModel.builder()
                    .modelFile(geckoModel)
                    .rotationY(rotationY)
                    .build();
        });
    }
    private void generateSpanishDonkeyBlockStatesSimple() {
        for (SpanishDonkeyBlock spanishDonkeyBlock : EDGBlocks.getSpanishDonkeyBlocks()) {

            ModelFile geckoModel = new ModelFile.ExistingModelFile(
                    EroticDungeon.rl( "block/spanish_donkey/" + spanishDonkeyBlock.getWoodType().name()),
                    models().existingFileHelper
            );

            getVariantBuilder(spanishDonkeyBlock).forAllStates(state -> {
                Direction direction = state.getValue(BlockStateProperties.HORIZONTAL_FACING);
                int rotationY = getMainWestRotationY(direction);

                return ConfiguredModel.builder()
                        .modelFile(geckoModel)
                        .rotationY(rotationY)
                        .build();
            });
        }
    }
    private void generateLoveMachineBlockStatesSimple() {
        ModelFile geckoModel = new ModelFile.ExistingModelFile(
                EroticDungeon.rl( "block/love_machine"),
                models().existingFileHelper
        );

        getVariantBuilder(EDGBlocks.END_ROD_LOVE_MACHINE.get()).forAllStates(state -> {
            Direction direction = state.getValue(BlockStateProperties.FACING);
            int rotationY = getMainNorthRotationY(direction);
            int rotationX = getRotationX(direction);
            return ConfiguredModel.builder()
                    .modelFile(geckoModel)
                    .rotationY(rotationY)
                    .rotationX(rotationX)
                    .build();
        });
        getVariantBuilder(EDGBlocks.LIGHTNING_ROD_LOVE_MACHINE.get()).forAllStates(state -> {
            Direction direction = state.getValue(BlockStateProperties.FACING);
            int rotationY = getMainNorthRotationY(direction);
            int rotationX = getRotationX(direction);
            return ConfiguredModel.builder()
                    .modelFile(geckoModel)
                    .rotationY(rotationY)
                    .rotationX(rotationX)
                    .build();
        });

    }
    private void generateBedBlockStates() {
        for (@NotNull CuffBedBlock cuffBedBlock : EDGBlocks.getCuffedBlocks()) {

            // 获取颜色名称
            String colorName = cuffBedBlock.color.getName();

            // 获取对应的模型文件
            ModelFile headModel = models().getExistingFile(EroticDungeon.rl("block/cuff_bed/" + colorName + "_head"));
            ModelFile footModel = models().getExistingFile(EroticDungeon.rl("block/cuff_bed/" + colorName + "_foot"));

            // 使用 forAllStates 方法简化状态配置
            getVariantBuilder(cuffBedBlock).forAllStates(state -> {
                Direction direction = state.getValue(BlockStateProperties.HORIZONTAL_FACING);
                SeatPart part = state.getValue(AbstractTwoPartSeatBlock.PART);

                ModelFile model = (part == SeatPart.HEAD) ? headModel : footModel;
                int rotationY = getMainWestRotationY(direction);

                return ConfiguredModel.builder()
                        .modelFile(model)
                        .rotationY(rotationY)
                        .build();
            });
        }
    }

    private void generateRackBlockStates() {
        for (@NotNull RackBlock rackBlock : EDGBlocks.getRackBlocks()) {
            // 获取木头名称
            String wood = WoodTypeHelper.getWoodSimpleName(rackBlock.getWoodType());
            // 获取对应的模型文件
            ModelFile headModel = models().getExistingFile(EroticDungeon.rl("block/rack/" + wood + "_head"));
            ModelFile middleModel = models().getExistingFile(EroticDungeon.rl("block/rack/" + wood + "_middle"));
            ModelFile footModel = models().getExistingFile(EroticDungeon.rl("block/rack/" + wood + "_foot"));

            // 使用 forAllStates 方法简化状态配置
            getVariantBuilder(rackBlock).forAllStates(state -> {
                Direction direction = state.getValue(BlockStateProperties.HORIZONTAL_FACING);
                AdvanceSeatPart part = state.getValue(AbstractThreePartSeatBlock.PART);

                ModelFile model = (part == AdvanceSeatPart.HEAD) ? headModel : (part == AdvanceSeatPart.FOOT) ? footModel : middleModel;
                int rotationY = getMainNorthRotationY(direction);

                return ConfiguredModel.builder()
                        .modelFile(model)
                        .rotationY(rotationY)
                        .build();
            });
        }
    }

    private void generateXCrossBlockStates() {
        for (@NotNull XCrossBlock xCrossBlock : EDGBlocks.getXCrossBlocks()) {
            // 获取木头名称
            String wood = WoodTypeHelper.getWoodSimpleName(xCrossBlock.getWoodType());
            // 获取对应的模型文件
            ModelFile headModel = models().getExistingFile(EroticDungeon.rl("block/x_cross/" + wood + "_head"));;
            ModelFile footModel = models().getExistingFile(EroticDungeon.rl("block/x_cross/" + wood + "_foot"));

            // 使用 forAllStates 方法简化状态配置
            getVariantBuilder(xCrossBlock).forAllStates(state -> {
                Direction direction = state.getValue(BlockStateProperties.HORIZONTAL_FACING);
                SeatPart part = state.getValue(XCrossBlock.PART);

                ModelFile model = (part == SeatPart.HEAD) ? headModel : footModel;
                int rotationY = getMainNorthRotationY(direction);

                return ConfiguredModel.builder()
                        .modelFile(model)
                        .rotationY(rotationY)
                        .build();
            });
        }
    }

    private void generateCuffPoleStates() {
        for (@NotNull CuffPoleBlock cuffPoleBlock : EDGBlocks.getCuffPoleBlocks()) {
            // 获取木头名称
            String wood = WoodTypeHelper.getWoodSimpleName(cuffPoleBlock.getWoodType());
            // 获取对应的模型文件
            ModelFile headModel = models().getExistingFile(EroticDungeon.rl("block/cuff_pole/" + wood + "_head"));;
            ModelFile footModel = models().getExistingFile(EroticDungeon.rl("block/cuff_pole/" + wood + "_foot"));

            // 使用 forAllStates 方法简化状态配置
            getVariantBuilder(cuffPoleBlock).forAllStates(state -> {
                Direction direction = state.getValue(BlockStateProperties.HORIZONTAL_FACING);
                SeatPart part = state.getValue(XCrossBlock.PART);

                ModelFile model = (part == SeatPart.HEAD) ? headModel : footModel;
                int rotationY = getMainNorthRotationY(direction);

                return ConfiguredModel.builder()
                        .modelFile(model)
                        .rotationY(rotationY)
                        .build();
            });
        }
    }


    private void generateProneBenchBlockStatesSimple() {
        for (ProneBenchBlock proneBenchBlock : EDGBlocks.getProneBenchBlocks()) {

            ModelFile model = new ModelFile.ExistingModelFile(
                    EroticDungeon.rl( "block/prone_bench/" + proneBenchBlock.getColor().getName() + "_" + proneBenchBlock.getWoodType().name()),
                    models().existingFileHelper
            );

            getVariantBuilder(proneBenchBlock).forAllStates(state -> {
                Direction direction = state.getValue(BlockStateProperties.HORIZONTAL_FACING);
                int rotationY = getMainNorthRotationY(direction);

                return ConfiguredModel.builder()
                        .modelFile(model)
                        .rotationY(rotationY)
                        .build();
            });
        }

    }


    private void generateCruxBlockStates() {
        for (@NotNull CruxBlock cruxBlock : EDGBlocks.getCruxBlocks()) {
            // 获取木头名称
            String wood = WoodTypeHelper.getWoodSimpleName(cruxBlock.getWoodType());
            // 获取对应的模型文件
            ModelFile headMiddleModel = models().getExistingFile(EroticDungeon.rl("block/crux/" + wood + "_head_middle"));
            ModelFile headLeftModel = models().getExistingFile(EroticDungeon.rl("block/crux/" + wood + "_head_left"));
            ModelFile headRightModel = models().getExistingFile(EroticDungeon.rl("block/crux/" + wood + "_head_right"));
            ModelFile footModel = models().getExistingFile(EroticDungeon.rl("block/crux/" + wood + "_foot"));

            // 使用 forAllStates 方法简化状态配置
            getVariantBuilder(cruxBlock).forAllStates(state -> {
                Direction direction = state.getValue(BlockStateProperties.HORIZONTAL_FACING);
                CrossSeatPart part = state.getValue(AbstractCrossSeatBlock.PART);

                ModelFile model = (part == CrossSeatPart.MAIN_MIDDLE) ? headMiddleModel : (part == CrossSeatPart.SECONDARY_MIDDLE) ? footModel : (part == CrossSeatPart.MAIN_LEFT) ? headLeftModel : headRightModel;
                int rotationY = getMainNorthRotationY(direction);

                return ConfiguredModel.builder()
                        .modelFile(model)
                        .rotationY(rotationY)
                        .build();
            });
        }
    }

    private void generatePetrineCrossBlockStates() {
        for (@NotNull PetrineCrossBlock petrineCrossBlock : EDGBlocks.getPetrineCrossBlocks()) {
            // 获取木头名称
            String wood = WoodTypeHelper.getWoodSimpleName(petrineCrossBlock.getWoodType());
            // 获取对应的模型文件
            ModelFile footMiddleModel = models().getExistingFile(EroticDungeon.rl("block/petrine_cross/" + wood + "_foot_middle"));
            ModelFile footLeftModel = models().getExistingFile(EroticDungeon.rl("block/petrine_cross/" + wood + "_foot_left"));
            ModelFile footRightModel = models().getExistingFile(EroticDungeon.rl("block/petrine_cross/" + wood + "_foot_right"));
            ModelFile headModel = models().getExistingFile(EroticDungeon.rl("block/petrine_cross/" + wood + "_head"));

            // 使用 forAllStates 方法简化状态配置
            getVariantBuilder(petrineCrossBlock).forAllStates(state -> {
                Direction direction = state.getValue(BlockStateProperties.HORIZONTAL_FACING);
                CrossSeatPart part = state.getValue(AbstractCrossSeatBlock.PART);

                ModelFile model = (part == CrossSeatPart.MAIN_MIDDLE) ? footMiddleModel : (part == CrossSeatPart.SECONDARY_MIDDLE) ? headModel : (part == CrossSeatPart.MAIN_LEFT) ? footLeftModel : footRightModel;
                int rotationY = getMainNorthRotationY(direction);

                return ConfiguredModel.builder()
                        .modelFile(model)
                        .rotationY(rotationY)
                        .build();
            });
        }
    }

    private void generatePilloryBlockStates() {
        for (@NotNull PilloryBlock pilloryBlock : EDGBlocks.getPilloryBlocks()) {
            // 获取木头名称
            String wood = WoodTypeHelper.getWoodSimpleName(pilloryBlock.getWoodType());
            // 获取对应的模型文件

            ModelFile openedHeadModel = models().getExistingFile(EroticDungeon.rl("block/pillory/" + wood + "_head_opened"));
            ModelFile closedHeadModel = models().getExistingFile(EroticDungeon.rl("block/pillory/" + wood + "_head_closed"));
            ModelFile footModel = models().getExistingFile(EroticDungeon.rl("block/pillory/" + wood + "_foot"));

            // 使用 forAllStates 方法简化状态配置
            getVariantBuilder(pilloryBlock).forAllStates(state -> {
                Direction direction = state.getValue(BlockStateProperties.HORIZONTAL_FACING);
                SeatPart part = state.getValue(AbstractTwoPartSeatBlock.PART);
                Boolean isClose = state.getValue(PilloryBlock.CLOSED);
                ModelFile model = (part == SeatPart.HEAD) ? isClose ? closedHeadModel : openedHeadModel : footModel;
                int rotationY = getMainNorthRotationY(direction);

                return ConfiguredModel.builder()
                        .modelFile(model)
                        .rotationY(rotationY)
                        .build();
            });
        }
    }

    private void generateWallRackBlockStates() {
        for (@NotNull WallRackBlock wallRackBlock : EDGBlocks.getWallRackBlocks()) {
            // 获取木头名称
            String wood = WoodTypeHelper.getWoodSimpleName(wallRackBlock.getWoodType());
            // 获取对应的模型文件
            ModelFile leftModel = models().getExistingFile(EroticDungeon.rl("block/wall_rack/" + wood + "_left"));
            ModelFile middleModel = models().getExistingFile(EroticDungeon.rl("block/wall_rack/" + wood + "_middle"));
            ModelFile rightModel = models().getExistingFile(EroticDungeon.rl("block/wall_rack/" + wood + "_right"));

            // 使用 forAllStates 方法简化状态配置
            getVariantBuilder(wallRackBlock).forAllStates(state -> {
                Direction direction = state.getValue(BlockStateProperties.HORIZONTAL_FACING);
                AdvanceSeatPart part = state.getValue(AbstractThreePartSeatBlock.PART);

                ModelFile model = (part == AdvanceSeatPart.HEAD) ? leftModel : (part == AdvanceSeatPart.FOOT) ? rightModel : middleModel;
                int rotationY = getMainNorthRotationY(direction);
                return ConfiguredModel.builder()
                        .modelFile(model)
                        .rotationY(rotationY)
                        .build();
            });
        }
    }


    private void generateHandingPostBlockStates() {
        for (@NotNull HangingPostBlock hangingPostBlock : EDGBlocks.getHangingPostBlocks()) {
            // 获取木头名称
            String wood = WoodTypeHelper.getWoodSimpleName(hangingPostBlock.getWoodType());
            // 获取对应的模型文件
            ModelFile headModel = models().getExistingFile(EroticDungeon.rl("block/hanging_post/" + wood + "_head"));
            ModelFile middleModel = models().getExistingFile(EroticDungeon.rl("block/hanging_post/" + wood + "_middle"));
            ModelFile footModel = models().getExistingFile(EroticDungeon.rl("block/hanging_post/" + wood + "_foot"));

            // 使用 forAllStates 方法简化状态配置
            getVariantBuilder(hangingPostBlock).forAllStates(state -> {
                Direction direction = state.getValue(BlockStateProperties.HORIZONTAL_FACING);
                AdvanceSeatPart part = state.getValue(VerticalTripleSeatBlock.PART);

                ModelFile model = (part == AdvanceSeatPart.MIDDLE) ? middleModel : (part == AdvanceSeatPart.FOOT) ? footModel : headModel;
                int rotationY = getMainNorthRotationY(direction);

                return ConfiguredModel.builder()
                        .modelFile(model)
                        .rotationY(rotationY)
                        .build();
            });
        }
    }


    @Contract(pure = true)
    private int getMainWestRotationY(@NotNull Direction direction) {
        return switch (direction) {
            case WEST -> 0;    // 西 - 基准方向，0度
            case NORTH -> 90;  // 北 - 相对于西旋转90度
            case EAST -> 180;  // 东 - 相对于西旋转180度
            case SOUTH -> 270; // 南 - 相对于西旋转270度
            default -> 0;
        };
    }

    @Contract(pure = true)
    private int getMainNorthRotationY(@NotNull Direction direction) {
        return switch (direction) {
            case WEST -> 270;    // 西 - 基准方向，270度
            case NORTH -> 0;  // 北 - 相对于西旋转0度
            case EAST -> 90;  // 东 - 相对于西旋转90度
            case SOUTH -> 180; // 南 - 相对于西旋转180度
            default -> 0;
        };
    }
    @Contract(pure = true)
    private int getRotationX(@NotNull Direction direction) {
        return switch (direction) {
            case UP -> 90;    // 向上需要旋转90度
            case DOWN -> 270; // 向下需要旋转270度
            default -> 0;     // 水平方向不需要X轴旋转
        };
    }

}