package org.implab.gradle.variants;

import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.implab.gradle.common.core.lang.Deferred;
import org.implab.gradle.variants.artifacts.ArtifactAssemblyRegistry;
import org.implab.gradle.variants.artifacts.OutgoingArtifactSlotSpec;
import org.implab.gradle.variants.artifacts.OutgoingConfigurationSpec;
import org.implab.gradle.variants.artifacts.VariantArtifactsContext;
import org.implab.gradle.variants.artifacts.VariantArtifactsExtension;
import org.implab.gradle.variants.artifacts.VariantArtifactsSpec;
import org.implab.gradle.variants.artifacts.internal.OutgoingRegistry;
import org.implab.gradle.variants.core.Variant;
import org.implab.gradle.variants.core.VariantsExtension;

public abstract class VariantArtifactsPlugin implements Plugin<Project> {

    @Override
    public void apply(Project target) {
        var extensions = target.getExtensions();
        var objects = target.getObjects();
        var providers = target.getProviders();
        var configurations = target.getConfigurations();
        var tasks = target.getTasks();

        // Apply the main VariantsPlugin to ensure the core variant model is available.
        target.getPlugins().apply(VariantsPlugin.class);
        // Access the VariantsExtension to configure variant sources.
        var variantsExtension = extensions.getByType(VariantsExtension.class);

        var outgoing = new OutgoingRegistry(configurations, objects, providers);
        var assemblies = new ArtifactAssemblyRegistry(objects, tasks);

        var deferred = new Deferred<VariantArtifactsContext>();

        variantsExtension.whenFinalized(variants -> {
            deferred.resolve(new VariantArtifactsRegistry(variants));
        });

        var variantArtifacts = new VariantArtifactsExtension() {

            @Override
            public void variant(String variantName, Action<? super VariantArtifactsSpec> action) {
                deferred.whenResolved(context -> registry.configureVariant(
                        objects.named(Variant.class, variantName), action));
            }

            @Override
            public void whenFinalized(Action<? super VariantArtifactsContext> action) {
                deferred.whenResolved(registry -> action.execute(registry.variantsContext()));
            }

            @Override
            public void whenOutgoingVariant(Action<? super OutgoingConfigurationSpec> action) {
                deferred.whenResolved(registry -> registry.configureOutgoing(action));

            }

            @Override
            public void whenOutgoingSlot(Action<? super OutgoingArtifactSlotSpec> action) {
                deferred.whenResolved(registry -> registry.configureOutgoingSlot(action));
            }

        };

        extensions.add(VariantArtifactsExtension.class, "variantArtifacts", variantArtifacts);

    }

}
