package aQute.bnd.maven.lib.resolve;

import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;

import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Dependency;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectDependenciesResolver;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import aQute.bnd.build.Workspace;
import aQute.bnd.maven.lib.configuration.BeanProperties;
import aQute.bnd.osgi.Processor;
import aQute.bnd.repository.fileset.FileSetRepository;
import aQute.bnd.service.RepositoryPlugin;
import biz.aQute.resolve.Bndrun;

public class BndrunContainer {

	private static final Logger logger = LoggerFactory.getLogger(BndrunContainer.class);

	private final List<File> bundles;

	private final boolean includeDependencyManagement;

	private final MavenProject project;

	private final RepositorySystemSession repositorySession;

	private final Set<Scope> scopes;

	private final MavenSession session;

	private final boolean useMavenDependencies;

	@SuppressWarnings("deprecation")
	private final org.apache.maven.artifact.factory.ArtifactFactory artifactFactory;

	private final ProjectDependenciesResolver resolver;

	private final RepositorySystem system;

	private FileSetRepository fileSetRepository;
	private Processor processor;

	public static class Builder {

		private final MavenProject project;
		private final MavenSession session;
		private final RepositorySystemSession repositorySession;
		private final ProjectDependenciesResolver resolver;
		@SuppressWarnings("deprecation")
		private final org.apache.maven.artifact.factory.ArtifactFactory artifactFactory;
		private final RepositorySystem system;
		private List<File> bundles = Collections.emptyList();
		private boolean includeDependencyManagement = false;
		private Set<Scope> scopes = new HashSet<>(Arrays.asList(Scope.compile, Scope.runtime));
		private boolean useMavenDependencies = true;

		@SuppressWarnings("deprecation")
		public Builder(MavenProject project, MavenSession session, RepositorySystemSession repositorySession, ProjectDependenciesResolver resolver, org.apache.maven.artifact.factory.ArtifactFactory artifactFactory,
			RepositorySystem system) {

			this.project = Objects.requireNonNull(project);
			this.session = Objects.requireNonNull(session);
			this.repositorySession = Objects.requireNonNull(repositorySession);
			this.resolver = Objects.requireNonNull(resolver);
			this.artifactFactory = Objects.requireNonNull(artifactFactory);
			this.system = Objects.requireNonNull(system);
		}

		public Builder setBundles(List<File> bundles) {
			this.bundles = bundles;
			return this;
		}

		public Builder setIncludeDependencyManagement(boolean includeDependencyManagement) {
			this.includeDependencyManagement = includeDependencyManagement;
			return this;
		}

		public Builder setScopes(Set<Scope> scopes) {
			this.scopes = scopes;
			return this;
		}

		public Builder setUseMavenDependencies(boolean useMavenDependencies) {
			this.useMavenDependencies = useMavenDependencies;
			return this;
		}

		public BndrunContainer build() {
			return new BndrunContainer(project, session, resolver, repositorySession, artifactFactory, system, scopes, bundles, useMavenDependencies, includeDependencyManagement);
		}

	}

	public static int report(Bndrun run) {
		int errors = 0;
		for (String warning : run.getWarnings()) {
			logger.warn("Warning : {}", warning);
		}
		for (String error : run.getErrors()) {
			logger.error("Error   : {}", error);
			errors++;
		}
		return errors;
	}

	@SuppressWarnings("deprecation")
	BndrunContainer(MavenProject project, MavenSession session, ProjectDependenciesResolver resolver, RepositorySystemSession repositorySession, org.apache.maven.artifact.factory.ArtifactFactory artifactFactory, RepositorySystem system,
		Set<Scope> scopes, List<File> bundles, boolean useMavenDependencies, boolean includeDependencyManagement) {
		this.project = project;
		this.session = session;
		this.resolver = resolver;
		this.repositorySession = repositorySession;
		this.artifactFactory = artifactFactory;
		this.system = system;
		this.scopes = scopes;
		this.bundles = bundles;
		this.useMavenDependencies = useMavenDependencies;
		this.includeDependencyManagement = includeDependencyManagement;
	}

	public int execute(File runFile, String task, File workingDir, Operation operation) throws Exception {
		if (!runFile.exists()) {
			logger.error("Could not find bnd run file {}", runFile);
			return 1;
		}
		String bndrun = getNamePart(runFile);
		File temporaryDir = workingDir.toPath()
			.resolve("tmp")
			.resolve(task)
			.resolve(bndrun)
			.toFile();
		File cnf = new File(temporaryDir, Workspace.CNFDIR);
		aQute.lib.io.IO.mkdirs(cnf);
		try (Bndrun run = Bndrun.createBndrun(null, runFile)) {
			run.setBase(temporaryDir);
			Workspace workspace = run.getWorkspace();
			workspace.setParent(getProcessor());
			workspace.setBuildDir(cnf);
			workspace.setOffline(session.getSettings()
				.isOffline());
			workspace.addBasicPlugin(getFileSetRepository());
			for (RepositoryPlugin repo : workspace.getRepositories()) {
				repo.list(null);
			}
			run.getInfo(workspace);
			int errors = report(run);
			if (!run.isOk()) {
				return errors;
			}
			return operation.apply(runFile, bndrun, run);
		}
	}

	public FileSetRepository getFileSetRepository() throws Exception {
		if (fileSetRepository != null) {
			return fileSetRepository;
		}

		if (includeDependencyManagement) {
			includeDependencyManagement(project, artifactFactory);
		}

		DependencyResolver dependencyResolver = new DependencyResolver(project, repositorySession, resolver, system, scopes);

		return fileSetRepository = dependencyResolver.getFileSetRepository(project.getName(), bundles, useMavenDependencies);
	}

	private String getNamePart(File runFile) {
		String nameExt = runFile.getName();
		int pos = nameExt.lastIndexOf('.');
		return (pos > 0) ? nameExt.substring(0, pos) : nameExt;
	}

	private Processor getProcessor() {
		if (processor != null) {
			return processor;
		}

		Properties beanProperties = new BeanProperties();
		beanProperties.put("project", project);
		beanProperties.put("settings", session.getSettings());
		Properties mavenProperties = new Properties(beanProperties);
		mavenProperties.putAll(project.getProperties());
		return processor = new Processor(mavenProperties, false);
	}

	@SuppressWarnings("deprecation")
	private void includeDependencyManagement(MavenProject mavenProject, org.apache.maven.artifact.factory.ArtifactFactory artifactFactory) {
		if (mavenProject.getDependencyManagement() != null) {
			List<Dependency> dependencies = mavenProject.getDependencies();

			mavenProject.getDependencyManagement()
				.getDependencies()
				.forEach(dependencies::add);

			try {
				mavenProject.setDependencyArtifacts(mavenProject.createArtifacts(artifactFactory, null, null));
			} catch (Exception e) {
				throw aQute.lib.exceptions.Exceptions.duck(e);
			}
		}
	}

}

@@ -5917,16 +5917,112 @@
 opes);%0A%0A
+%09%09String name = project.getName()%0A%09%09%09.isEmpty() ? project.getArtifactId() : project.getName();%0A%0A
 %09%09return
@@ -6082,33 +6082,20 @@
 ository(
-project.getN
+n
 ame
-()
 , bundle

make sure to provide a name to the repo