package de.renew.navigator.vc;

import java.io.File;
import java.net.URI;
import java.util.HashSet;
import java.util.Set;

import de.renew.util.StringUtil;


/**
 * @author Konstantin Simon Maria Moellers
 * @version 2015-10-19
 */
public abstract class AbstractRepository implements Repository {

    private final File _rootDirectory;
    private final VersionControl _versionControl;
    private final Set<File> _ignored;
    private final Set<File> _added;
    private final Set<File> _modified;
    private Commit _lastCommit;

    /**
     * Constructor to create an instance of the AbstractRepository.
     *
     * @param rootDirectory the File of the work tree of this repository.
     * @param versionControl the VersionControl handling this repository.
     */
    public AbstractRepository(File rootDirectory, VersionControl versionControl) {
        this._rootDirectory = rootDirectory;
        this._versionControl = versionControl;
        _lastCommit = null;
        _ignored = new HashSet<>();
        _added = new HashSet<>();
        _modified = new HashSet<>();
    }

    /**
     * This method clears all the set constants of the AbstractRepository.
     */
    public final void clearFileSets() {
        _ignored.clear();
        _added.clear();
        _modified.clear();
    }

    /**
     * This method adds all files to the ignored constant of this repository.
     *
     * @param files The Set of Files that should be added.
     */
    public final void addAllToIgnored(Set<File> files) {
        _ignored.addAll(files);
    }

    /**
     * This method adds all files to the added constant of this repository.
     *
     * @param files The Set of Files that should be added.
     */
    public final void addAllToAdded(Set<File> files) {
        _added.addAll(files);
    }

    /**
     * This method adds all files to the modified constant of this repository.
     *
     * @param files The Set of Files that should be added.
     */
    public final void addAllToModified(Set<File> files) {
        _modified.addAll(files);
    }

    /**
     * This method sets the last commit of this repository.
     *
     * @param lastCommit The Commit that should be set as the last commit.
     */
    public void setLastCommit(Commit lastCommit) {
        this._lastCommit = lastCommit;
    }

    @Override
    public final File getRootDirectory() {
        return _rootDirectory;
    }

    @Override
    public final VersionControl getVersionControl() {
        return _versionControl;
    }

    @Override
    public Commit getLastCommit() {
        return _lastCommit;
    }

    @Override
    public final URI makeRelativeURI(File fileInRepository) {
        return StringUtil.makeRelative(_rootDirectory.toURI(), fileInRepository.toURI());
    }

    @Override
    public String toString() {
        return "[" + _rootDirectory.toString() + "] " + _versionControl.getName() + "@"
            + getBranch();
    }

    @Override
    public final Set<File> getIgnored() {
        return _ignored;
    }

    @Override
    public final Set<File> getAdded() {
        return _added;
    }

    @Override
    public final Set<File> getModified() {
        return _modified;
    }

    /**
     * @return the last commit.
     */
    protected abstract Commit retrieveLastCommit();
}