package org.implab.gradle.variants.artifacts.internal;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.gradle.api.Action;
import org.implab.gradle.variants.artifacts.ArtifactAssemblies;
import org.implab.gradle.variants.artifacts.ArtifactSlot;
import org.implab.gradle.variants.artifacts.OutgoingVariant;

/**
 * Binds materialized slot assemblies to Gradle outgoing publications.
 */
@NonNullByDefault
public class ArtifactAssemblyBinder implements Action<OutgoingVariant> {

    private final ArtifactAssemblies resolver;

    public ArtifactAssemblyBinder(ArtifactAssemblies resolver) {
        this.resolver = resolver;
    }

    @Override
    public void execute(OutgoingVariant outgoingVariant) {
        var slots = outgoingVariant.getSlots();
        var primarySlotProvider = outgoingVariant.getPrimarySlot();
        var variant = outgoingVariant.getVariant();

        // Bind publication state when the owning configuration is materialized.
        outgoingVariant.configureOutgoing(configuration -> {
            var primarySlot = primarySlotProvider.get();
            var outgoing = configuration.getOutgoing();

            // Bind the primary artifact set to the root outgoing configuration.
            resolver.when(
                    new ArtifactSlot(variant, primarySlot),
                    assembly -> outgoing.artifact(
                            assembly.getArtifact(),
                            artifact -> artifact.builtBy(assembly.getAssemblyTask())));

            // Bind non-primary slots to Gradle secondary artifact variants.
            slots.all(slot -> {
                if (slot.equals(primarySlot))
                    return;

                resolver.when(
                        new ArtifactSlot(variant, slot),
                        // Gradle artifact variants must be created while the owning
                        // configuration is being materialized. Lazy registration may
                        // otherwise be realized only after dependency resolution starts.
                        assembly -> outgoing.getVariants()
                                .create(slot.getName())
                                .artifact(
                                        assembly.getArtifact(),
                                        artifact -> artifact.builtBy(assembly.getAssemblyTask())));
            });
        });
    }



}
