package net.minecraft.server.packs;

import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import java.util.List;
import java.util.regex.Pattern;
import net.minecraft.server.packs.metadata.MetadataSectionType;
import net.minecraft.util.InclusiveRange;

public record OverlayMetadataSection(List<OverlayMetadataSection.OverlayEntry> overlays) {
    private static final Pattern DIR_VALIDATOR = Pattern.compile("[-_a-zA-Z0-9.]+");
    private static final Codec<OverlayMetadataSection> CODEC = RecordCodecBuilder.create(
        instance -> instance.group(OverlayMetadataSection.OverlayEntry.CODEC.listOf().fieldOf("entries").forGetter(OverlayMetadataSection::overlays))
            .apply(instance, OverlayMetadataSection::new)
    );
    public static final MetadataSectionType<OverlayMetadataSection> TYPE = new MetadataSectionType<>("overlays", CODEC);

    private static DataResult<String> validateOverlayDir(String directoryName) {
        return !DIR_VALIDATOR.matcher(directoryName).matches()
            ? DataResult.error(() -> directoryName + " is not accepted directory name")
            : DataResult.success(directoryName);
    }

    public List<String> overlaysForVersion(int version) {
        return this.overlays.stream().filter(overlay -> overlay.isApplicable(version)).map(OverlayMetadataSection.OverlayEntry::overlay).toList();
    }

    public record OverlayEntry(InclusiveRange<Integer> format, String overlay) {
        static final Codec<OverlayMetadataSection.OverlayEntry> CODEC = RecordCodecBuilder.create(
            instance -> instance.group(
                    InclusiveRange.codec(Codec.INT).fieldOf("formats").forGetter(OverlayMetadataSection.OverlayEntry::format),
                    Codec.STRING
                        .validate(OverlayMetadataSection::validateOverlayDir)
                        .fieldOf("directory")
                        .forGetter(OverlayMetadataSection.OverlayEntry::overlay)
                )
                .apply(instance, OverlayMetadataSection.OverlayEntry::new)
        );

        public boolean isApplicable(int version) {
            return this.format.isValueInRange(version);
        }
    }
}
