package org.bndtools.versioncontrol.ignores.manager.api;

import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.bndtools.api.NamedPlugin;
import org.osgi.annotation.versioning.ProviderType;

/**
 * <p>
 * The interface of the version control ignores manager.
 * </p>
 * <p>
 * Its purpose is to allow clients to add version control ignores to directories.
 * </p>
 */
@ProviderType
public interface VersionControlIgnoresManager {
    /**
     * Sanitise a Git ignore glob so that it is a properly formatted ignore glob in Git format.
     * 
     * @param rooted true when the ignore glob must be rooted in the directory to which the ignore glob is applied
     * @param ignoreGlob The ignore glob in Git format
     * @param directory true when the ignore glob denotes a directory
     * @return The sanitised ignore glob in Git format
     */
    String sanitiseGitIgnoreGlob(boolean rooted, String ignoreGlob, boolean directory);

    /**
     * @return an unmodifiable collection containing the information for all plugins
     */
    Collection<NamedPlugin> getAllPluginsInformation();

    /**
     * <p>
     * Apply ignore globs to a directory.
     * </p>
     * <p>
     * This is a convenience method for {@link #addIgnores(Set, File, List)}:
     * </p>
     * 
     * @param plugins the set of plugins (their names) to involve in applying ignore globs. Usually only the plugins
     *            that are enabled through the preferences should be involved: it is strongly advised to get these
     *            through the BndPreferences (the burden is on the caller of this method).
     * @param dstDir the directory which to apply the ignore globs to
     * @param ignores A comma-separated list of ignore globs to apply to the directory. The ignore globs must in Git
     *            ignore format. Can be null, which is the same as "" which will create an empty ignore file when
     *            needed.
     */
    void addIgnores(Set<String> plugins, File dstDir, String ignores);

    /**
     * Apply ignore globs to a directory.
     *
     * @param plugins the set of plugins (their names) to involve in applying ignore globs. Usually only the plugins
     *            that are enabled through the preferences should be involved: it is strongly advised to get these
     *            through the BndPreferences (the burden is on the caller of this method).
     * @param dstDir the directory which to apply the ignore globs to
     * @param ignores A list of ignore globs to apply to the directory. The ignore globs must in Git ignore format and
     *            it's strongly advised to call {@link #sanitiseGitIgnoreGlob(boolean, String, boolean)} for each ignore
     *            glob. Can be null, which is the same as an empty list which will create an empty ignore file when
     *            needed.
     */
    void addIgnores(Set<String> plugins, File dstDir, List<String> ignoredEntries);

    /**
     * <p>
     * Create the (default) ignores for a project.
     * </p>
     * <p>
     * It will setup:
     * <ul>
     * <li>empty ignores for each empty source directory of the project when the version control system of a plugin
     * can't store empty directories</li>
     * <li>ignores for each output directory belonging to a source directory of the project</li>
     * </p>
     * 
     * @param plugins the set of plugins (their names) to involve in applying ignore globs. Usually only the plugins
     *            that are enabled through the preferences should be involved: it is strongly advised to get these
     *            through the BndPreferences (the burden is on the caller of this method).
     * @param projectDir the project directory. For Eclipse projects usually obtained by invoking
     *            IProject.getLocation().toFile()
     * @param sourceOutputLocations a map of source folders against their output folders, all relative to the project
     *            directory
     * @param targetDir the target (usually 'generated' for bnd projects) directory, relative to the project directory
     */
    void createProjectIgnores(Set<String> plugins, File projectDir, Map<String, String> sourceOutputLocations, String targetDir);

    /**
     * Determine which of the plugins can apply ignore globs for the version control system that is managing the
     * project.
     * 
     * @param repositoryProviderId the id of the repository provider that is managing the project
     * @return a set of plugins that can apply ignore globs for the version control system that is managing the project.
     *         null when repositoryProviderId is null or empty or when there are no such plugins.
     */
    public Set<String> getPluginsForProjectRepositoryProviderId(String repositoryProviderId);
}
