package org.implab.gradle.common;

import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.api.tasks.Copy;
import org.gradle.api.tasks.Delete;
import org.gradle.api.tasks.TaskContainer;
import org.gradle.api.tasks.TaskProvider;
import org.gradle.language.base.plugins.LifecycleBasePlugin;
import org.implab.gradle.common.files.GenericSourceSet;
import org.implab.gradle.common.utils.Strings;

/**
 * This plugin creates a {@code sources} extension which is
 * a container for {@link GenericSourceSet}.
 *
 */
public abstract class SourcesPlugin implements Plugin<Project> {
    private final Logger logger = Logging.getLogger(SourcesPlugin.class);

    private final String POLICY_NAME = "SourcesPolicy";

    private final String EXTENSION_NAME = "sources";

    @Override
    public void apply(Project target) {
        target.getPlugins().apply(LifecycleBasePlugin.class);

        var sources = target.getObjects().domainObjectContainer(GenericSourceSet.class);
        var tasks = target.getTasks();
        var clean = tasks.named(LifecycleBasePlugin.CLEAN_TASK_NAME);

        target.getExtensions().add(EXTENSION_NAME, sources);

        sources.configureEach(configureSourceSet(tasks, clean));
    }

    private Action<GenericSourceSet> configureSourceSet(TaskContainer tasks, TaskProvider<?> clean) {
        return sourceSet -> {
            var name = sourceSet.getName();

            logger.info("{}: Processing source set '{}'", POLICY_NAME, name);

            var taskName = "clean" + Strings.capitalize(sourceSet.getName());

            logger.info("{}: Register task '{}' of type [{}]", POLICY_NAME, taskName, Copy.class.getTypeName());

            var task = tasks.register(taskName, Delete.class, self -> {
                self.delete(sourceSet.getOutputsDir());
            });

            clean.configure(self -> {
                self.dependsOn(task);
            });
        };
    }
}
