package com.atlassian.bitbucket.scm;

import com.atlassian.bitbucket.scm.compare.PluginCompareCommandFactory;
import com.atlassian.bitbucket.scm.hook.PluginHookHandlerFactory;
import com.atlassian.bitbucket.scm.pull.PluginPullRequestCommandFactory;
import com.atlassian.bitbucket.scm.ref.PluginRefCommandFactory;

import javax.annotation.Nonnull;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Set;

/**
 * Convenience implementation of {@link Scm} that returns {@code null} for all of the optional contract members.
 * Required members have no default implementation.
 * <p>
 * Derived classes should provide their supported {@link ScmFeature features} to the constructor. The nullary
 * constructor assumes the SCM doesn't support <i>any</i> of the optional features.
 * <p>
 * SCM implementors are <i>strongly</i> encouraged to use this base class for their {@link Scm} implementation.
 * As new features are added SCMs built on this base class will better retain cross-version support because it
 * will provide {@code null} implementations of new optional members.
 */
public abstract class AbstractScm implements Scm {

    private final Set<ScmFeature> features;

    protected AbstractScm() {
        this(EnumSet.noneOf(ScmFeature.class));
    }

    protected AbstractScm(@Nonnull Set<ScmFeature> features) {
        //EnumSet for lookup speed; ScmFeatures will be accessed very frequently
        this.features = Collections.unmodifiableSet(EnumSet.copyOf(features));
    }

    @Override
    public PluginCommandBuilderFactory getCommandBuilderFactory() {
        return null;
    }

    @Override
    public PluginCompareCommandFactory getCompareCommandFactory() {
        return null;
    }

    @Nonnull
    @Override
    public Set<ScmFeature> getFeatures() {
        return features;
    }

    @Override
    public PluginHookHandlerFactory getHookHandlerFactory() {
        return null;
    }

    @Override
    public PluginPullRequestCommandFactory getPullRequestCommandFactory() {
        return null;
    }

    @Override
    public PluginRefCommandFactory getRefCommandFactory() {
        return null;
    }
}
