package org.implab.gradle.common.sources;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.implab.gradle.common.core.lang.Closures;
import org.gradle.api.Action;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.InvalidUserDataException;

import groovy.lang.Closure;
import groovy.lang.DelegatesTo;

@NonNullByDefault
public final class OutgoingVariantPublication {
    private final String variantName;
    private final BuildVariant topologyVariant;
    private final VariantArtifact variantArtifact;
    private final Configuration configuration;
    private final OutgoingArtifactSlotPublication primarySlot;
    private final java.util.List<OutgoingArtifactSlotPublication> slots;

    public OutgoingVariantPublication(
            String variantName,
            BuildVariant topologyVariant,
            VariantArtifact variantArtifact,
            Configuration configuration,
            OutgoingArtifactSlotPublication primarySlot,
            java.util.List<OutgoingArtifactSlotPublication> slots) {
        this.variantName = variantName;
        this.topologyVariant = topologyVariant;
        this.variantArtifact = variantArtifact;
        this.configuration = configuration;
        this.primarySlot = primarySlot;
        this.slots = java.util.List.copyOf(slots);
    }

    public String variantName() {
        return variantName;
    }

    public BuildVariant topologyVariant() {
        return topologyVariant;
    }

    public VariantArtifact variantArtifact() {
        return variantArtifact;
    }

    public Configuration configuration() {
        return configuration;
    }

    public OutgoingArtifactSlotPublication primarySlot() {
        return primarySlot;
    }

    public java.util.List<OutgoingArtifactSlotPublication> slots() {
        return slots;
    }

    public java.util.List<OutgoingArtifactSlotPublication> secondarySlots() {
        return slots.stream()
                .filter(slotPublication -> !slotPublication.primary())
                .toList();
    }

    public java.util.Optional<OutgoingArtifactSlotPublication> findSlot(String slotName) {
        var normalizedSlotName = VariantArtifact.normalize(slotName, "slot name must not be null or blank");
        return slots.stream()
                .filter(slotPublication -> normalizedSlotName.equals(slotPublication.slotName()))
                .findFirst();
    }

    public OutgoingArtifactSlotPublication requireSlot(String slotName) {
        var normalizedSlotName = VariantArtifact.normalize(slotName, "slot name must not be null or blank");
        return findSlot(normalizedSlotName)
                .orElseThrow(() -> new InvalidUserDataException(
                        "Outgoing publication for variant '" + variantName + "' doesn't declare slot '"
                                + normalizedSlotName + "'"));
    }

    public void configureConfiguration(Action<? super Configuration> action) {
        action.execute(configuration);
    }

    public void configureConfiguration(
            @DelegatesTo(value = Configuration.class, strategy = Closure.DELEGATE_FIRST) Closure<?> action) {
        configureConfiguration(Closures.action(action));
    }
}
