package com.tiedup.remake.items;

import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.entities.ModEntities;
import com.tiedup.remake.items.base.*;
import com.tiedup.remake.items.bondage3d.gags.ItemBallGag3D;
import com.tiedup.remake.items.clothes.GenericClothes;
import java.util.EnumMap;
import java.util.Map;
import net.minecraft.world.item.Item;
import net.minecraftforge.common.ForgeSpawnEggItem;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;

/**
 * Mod Items Registration
 * Handles registration of all TiedUp items using DeferredRegister.
 *
 * Refactored with Factory Pattern:
 * - Binds, Gags, Blindfolds, Earplugs, Knives use EnumMaps and factory methods
 * - Complex items (collars, whip, chloroform, etc.) remain individual registrations
 *
 * Usage:
 * - ModItems.getBind(BindVariant.ROPES) - Get a specific bind item
 * - ModItems.getGag(GagVariant.BALL_GAG) - Get a specific gag item
 * - ModItems.WHIP.get() - Get complex items directly
 */
public class ModItems {

    // DeferredRegister for items
    public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(
        ForgeRegistries.ITEMS,
        TiedUpMod.MOD_ID
    );

    // ========== FACTORY-BASED ITEMS ==========

    /**
     * All bind items (15 variants via BindVariant enum)
     */
    public static final Map<BindVariant, RegistryObject<Item>> BINDS =
        registerAllBinds();

    /**
     * All gag items (via GagVariant enum)
     * Note: ItemMedicalGag is registered separately as it has special behavior
     * Note: BALL_GAG_3D is a separate 3D item (not in enum)
     */
    public static final Map<GagVariant, RegistryObject<Item>> GAGS =
        registerAllGags();

    /**
     * Ball Gag 3D - Uses 3D OBJ model rendering via dedicated class.
     * This is a separate item from BALL_GAG (which uses 2D textures).
     */
    public static final RegistryObject<Item> BALL_GAG_3D = ITEMS.register(
        "ball_gag_3d",
        ItemBallGag3D::new
    );

    /**
     * All blindfold items (2 variants via BlindfoldVariant enum)
     */
    public static final Map<BlindfoldVariant, RegistryObject<Item>> BLINDFOLDS =
        registerAllBlindfolds();

    /**
     * All earplugs items (1 variant via EarplugsVariant enum)
     */
    public static final Map<EarplugsVariant, RegistryObject<Item>> EARPLUGS =
        registerAllEarplugs();

    /**
     * All knife items (3 variants via KnifeVariant enum)
     */
    public static final Map<KnifeVariant, RegistryObject<Item>> KNIVES =
        registerAllKnives();

    /**
     * All mittens items (1 variant via MittensVariant enum)
     */
    public static final Map<MittensVariant, RegistryObject<Item>> MITTENS =
        registerAllMittens();

    /**
     * Clothes item - uses dynamic textures from URLs.
     * Users can create presets via anvil naming.
     */
    public static final RegistryObject<Item> CLOTHES = ITEMS.register(
        "clothes",
        GenericClothes::new
    );

    // ========== COMPLEX ITEMS (individual registrations) ==========

    // Medical gag - combo item with IHasBlindingEffect
    public static final RegistryObject<Item> MEDICAL_GAG = ITEMS.register(
        "medical_gag",
        ItemMedicalGag::new
    );

    // Hood - combo item
    public static final RegistryObject<Item> HOOD = ITEMS.register(
        "hood",
        ItemHood::new
    );

    // Collars - complex logic
    public static final RegistryObject<Item> CLASSIC_COLLAR = ITEMS.register(
        "classic_collar",
        ItemClassicCollar::new
    );

    public static final RegistryObject<Item> SHOCK_COLLAR = ITEMS.register(
        "shock_collar",
        ItemShockCollar::new
    );

    public static final RegistryObject<Item> SHOCK_COLLAR_AUTO = ITEMS.register(
        "shock_collar_auto",
        ItemShockCollarAuto::new
    );

    public static final RegistryObject<Item> GPS_COLLAR = ITEMS.register(
        "gps_collar",
        ItemGpsCollar::new
    );

    // Choke Collar - Pet play collar used by Masters
    public static final RegistryObject<Item> CHOKE_COLLAR = ITEMS.register(
        "choke_collar",
        ItemChokeCollar::new
    );

    // Tools with complex behavior
    public static final RegistryObject<Item> WHIP = ITEMS.register(
        "whip",
        ItemWhip::new
    );

    public static final RegistryObject<Item> CHLOROFORM_BOTTLE = ITEMS.register(
        "chloroform_bottle",
        ItemChloroformBottle::new
    );

    public static final RegistryObject<Item> RAG = ITEMS.register(
        "rag",
        ItemRag::new
    );

    public static final RegistryObject<Item> PADLOCK = ITEMS.register(
        "padlock",
        ItemPadlock::new
    );

    public static final RegistryObject<Item> MASTER_KEY = ITEMS.register(
        "master_key",
        ItemMasterKey::new
    );

    public static final RegistryObject<Item> ROPE_ARROW = ITEMS.register(
        "rope_arrow",
        ItemRopeArrow::new
    );

    public static final RegistryObject<Item> PADDLE = ITEMS.register(
        "paddle",
        ItemPaddle::new
    );

    public static final RegistryObject<Item> SHOCKER_CONTROLLER =
        ITEMS.register("shocker_controller", ItemShockerController::new);

    public static final RegistryObject<Item> GPS_LOCATOR = ITEMS.register(
        "gps_locator",
        ItemGpsLocator::new
    );

    public static final RegistryObject<Item> COLLAR_KEY = ITEMS.register(
        "collar_key",
        ItemKey::new
    );

    public static final RegistryObject<Item> LOCKPICK = ITEMS.register(
        "lockpick",
        ItemLockpick::new
    );

    // Taser - Kidnapper's defensive weapon (Fight Back system)
    public static final RegistryObject<Item> TASER = ITEMS.register(
        "taser",
        ItemTaser::new
    );

    // TiedUp! Guide Book - Opens Patchouli documentation
    public static final RegistryObject<Item> TIEDUP_GUIDE = ITEMS.register(
        "tiedup_guide",
        ItemTiedUpGuide::new
    );

    // Command Wand - Gives commands to collared NPCs (Personality System)
    public static final RegistryObject<Item> COMMAND_WAND = ITEMS.register(
        "command_wand",
        ItemCommandWand::new
    );

    // Debug Wand - Testing tool for Personality System (OP item)
    public static final RegistryObject<Item> DEBUG_WAND = ITEMS.register(
        "debug_wand",
        ItemDebugWand::new
    );

    // ========== CELL SYSTEM ITEMS ==========

    // Admin Wand - Structure marker placement and Cell Core management
    public static final RegistryObject<Item> ADMIN_WAND = ITEMS.register(
        "admin_wand",
        ItemAdminWand::new
    );

    // Cell Key - Universal key for iron bar doors
    public static final RegistryObject<Item> CELL_KEY = ITEMS.register(
        "cell_key",
        ItemCellKey::new
    );

    // ========== SLAVE TRADER SYSTEM ==========

    // Token - Access pass for kidnapper camps
    public static final RegistryObject<Item> TOKEN = ITEMS.register(
        "token",
        ItemToken::new
    );

    // ========== SPAWN EGGS ==========

    /**
     * Damsel Spawn Egg
     * Colors: Light Pink (0xFFB6C1) / Hot Pink (0xFF69B4)
     */
    public static final RegistryObject<Item> DAMSEL_SPAWN_EGG = ITEMS.register(
        "damsel_spawn_egg",
        () ->
            new ForgeSpawnEggItem(
                ModEntities.DAMSEL,
                0xFFB6C1, // Light pink (primary)
                0xFF69B4, // Hot pink (secondary)
                new Item.Properties()
            )
    );

    // ========== FACTORY METHODS ==========

    private static Map<BindVariant, RegistryObject<Item>> registerAllBinds() {
        Map<BindVariant, RegistryObject<Item>> map = new EnumMap<>(
            BindVariant.class
        );
        for (BindVariant variant : BindVariant.values()) {
            map.put(
                variant,
                ITEMS.register(variant.getRegistryName(), () ->
                    new GenericBind(variant)
                )
            );
        }
        return map;
    }

    private static Map<GagVariant, RegistryObject<Item>> registerAllGags() {
        Map<GagVariant, RegistryObject<Item>> map = new EnumMap<>(
            GagVariant.class
        );
        for (GagVariant variant : GagVariant.values()) {
            map.put(
                variant,
                ITEMS.register(variant.getRegistryName(), () ->
                    new GenericGag(variant)
                )
            );
        }
        return map;
    }

    private static Map<
        BlindfoldVariant,
        RegistryObject<Item>
    > registerAllBlindfolds() {
        Map<BlindfoldVariant, RegistryObject<Item>> map = new EnumMap<>(
            BlindfoldVariant.class
        );
        for (BlindfoldVariant variant : BlindfoldVariant.values()) {
            map.put(
                variant,
                ITEMS.register(variant.getRegistryName(), () ->
                    new GenericBlindfold(variant)
                )
            );
        }
        return map;
    }

    private static Map<
        EarplugsVariant,
        RegistryObject<Item>
    > registerAllEarplugs() {
        Map<EarplugsVariant, RegistryObject<Item>> map = new EnumMap<>(
            EarplugsVariant.class
        );
        for (EarplugsVariant variant : EarplugsVariant.values()) {
            map.put(
                variant,
                ITEMS.register(variant.getRegistryName(), () ->
                    new GenericEarplugs(variant)
                )
            );
        }
        return map;
    }

    private static Map<KnifeVariant, RegistryObject<Item>> registerAllKnives() {
        Map<KnifeVariant, RegistryObject<Item>> map = new EnumMap<>(
            KnifeVariant.class
        );
        for (KnifeVariant variant : KnifeVariant.values()) {
            map.put(
                variant,
                ITEMS.register(variant.getRegistryName(), () ->
                    new GenericKnife(variant)
                )
            );
        }
        return map;
    }

    private static Map<
        MittensVariant,
        RegistryObject<Item>
    > registerAllMittens() {
        Map<MittensVariant, RegistryObject<Item>> map = new EnumMap<>(
            MittensVariant.class
        );
        for (MittensVariant variant : MittensVariant.values()) {
            map.put(
                variant,
                ITEMS.register(variant.getRegistryName(), () ->
                    new GenericMittens(variant)
                )
            );
        }
        return map;
    }

    // ========== HELPER ACCESSORS ==========

    /**
     * Get a bind item by variant.
     * @param variant The bind variant
     * @return The bind item
     */
    public static Item getBind(BindVariant variant) {
        return BINDS.get(variant).get();
    }

    /**
     * Get a gag item by variant.
     * @param variant The gag variant
     * @return The gag item
     */
    public static Item getGag(GagVariant variant) {
        return GAGS.get(variant).get();
    }

    /**
     * Get a blindfold item by variant.
     * @param variant The blindfold variant
     * @return The blindfold item
     */
    public static Item getBlindfold(BlindfoldVariant variant) {
        return BLINDFOLDS.get(variant).get();
    }

    /**
     * Get an earplugs item by variant.
     * @param variant The earplugs variant
     * @return The earplugs item
     */
    public static Item getEarplugs(EarplugsVariant variant) {
        return EARPLUGS.get(variant).get();
    }

    /**
     * Get a knife item by variant.
     * @param variant The knife variant
     * @return The knife item
     */
    public static Item getKnife(KnifeVariant variant) {
        return KNIVES.get(variant).get();
    }

    /**
     * Get a mittens item by variant.
     * @param variant The mittens variant
     * @return The mittens item
     */
    public static Item getMittens(MittensVariant variant) {
        return MITTENS.get(variant).get();
    }
}
