package top.r3944realms.lib39.core.sync;

import com.google.common.collect.Maps;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.common.capabilities.Capability;
import org.jetbrains.annotations.Nullable;

import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * The type Sync data 2 manager.
 */
@SuppressWarnings("unused")
public class SyncData2CapManager extends SyncData2Manager<SyncData2CapManager.TypedSyncEntry<? extends ISyncData<?>>> {
    /**
     * The Typed entries.
     */
    protected final Map<ResourceLocation, TypedSyncEntry<?>> typedEntries = Maps.newConcurrentMap();

    @Override
    protected Map<ResourceLocation, TypedSyncEntry<?>> getTypedEntries() {
        return typedEntries;
    }

    /**
     * The type Typed sync entry.
     *
     * @param <T> the type parameter
     */
    protected static class TypedSyncEntry<T extends ISyncData<?>> extends SyncData2Manager.TypedSyncEntry<Capability<T>, T> {
        /**
         * Instantiates a new Typed sync entry.
         *
         * @param manager    the manager
         * @param capability the capability
         */
        public TypedSyncEntry(ISyncManager<Capability<T>, T> manager,@Nullable Capability<T> capability) {
            super(manager, key -> capability != null ? key.getCapability(capability).resolve() : Optional.empty());
        }
    }

    /**
     * Register manager.
     *
     * @param <T>        the type parameter
     * @param key        the key
     * @param manager    the manager
     * @param capability the capability
     */
    public <T extends ISyncData<?>> void registerManager(
            ResourceLocation key,
            ISyncManager<Capability<T>, T> manager,
            Capability<T> capability
    ) {
        Objects.requireNonNull(key, "ResourceLocation key cannot be null");
        Objects.requireNonNull(manager, "Sync manager cannot be null");
        Objects.requireNonNull(capability, "Capability cannot be null");

        typedEntries.put(key, new TypedSyncEntry<>(manager, capability));
    }


    /**
     * 绑定能力（用于分离注册的情况）
     *
     * @param <T>        the type parameter
     * @param key        the key
     * @param capability the capability
     */
    public <T extends ISyncData<?>> void bindCapability(ResourceLocation key, Capability<T> capability) {
        Objects.requireNonNull(key, "ResourceLocation key cannot be null");
        Objects.requireNonNull(capability, "Capability cannot be null");

        TypedSyncEntry<?> entry = typedEntries.get(key);
        if (entry != null) {
            // 更新现有条目的能力
            updateCapabilityInEntry(key, entry, capability);
        } else throw new IllegalArgumentException("No manager found for " + key);
    }

    /**
     * 解绑能力
     *
     * @param key the key
     */
    public void unbindCapability(ResourceLocation key) {
        Objects.requireNonNull(key, "ResourceLocation key cannot be null");

        TypedSyncEntry<?> entry = typedEntries.get(key);
        if (entry != null) {
            // 将能力设置为null，但保留管理器和其他配置
            updateCapabilityInEntry(key, entry, null);
        }
    }

    /**
     * Update capability in entry.
     *
     * @param <T>           the type parameter
     * @param id            the id
     * @param entry         the entry
     * @param newCapability the new capability
     */
    protected  <T extends ISyncData<?>> void updateCapabilityInEntry(ResourceLocation id, TypedSyncEntry<?> entry, Capability<T> newCapability) {
        updateDataProviderInEntry(id, entry, key -> newCapability != null ? key.getCapability(newCapability).resolve() : Optional.empty());
    }
}