package com.atlassian.stash.internal.scm;

import com.atlassian.bitbucket.content.*;
import com.atlassian.bitbucket.repository.*;
import com.atlassian.bitbucket.scm.*;
import com.atlassian.bitbucket.commit.Changeset;
import com.atlassian.bitbucket.commit.Commit;
import com.atlassian.bitbucket.commit.CommitCallback;
import com.atlassian.bitbucket.commit.graph.TraversalCallback;
import com.atlassian.bitbucket.io.TypeAwareOutputSupplier;
import com.atlassian.bitbucket.util.Page;
import com.atlassian.bitbucket.util.PageRequest;

import javax.annotation.Nonnull;
import java.util.List;
import java.util.Map;

import static java.util.Objects.requireNonNull;

/**
 * Implements {@link ScmCommandFactory} by delegating to the {@link PluginCommandFactory}, binding a {@link Repository}
 * set during construction as the first parameter for all of its methods.
 *
 * @since 1.3
 */
@SuppressWarnings("deprecation")
public class PluginScmCommandFactory implements ScmCommandFactory {

    private final PluginCommandFactory commandFactory;
    private final Repository repository;

    public PluginScmCommandFactory(Repository repository, PluginCommandFactory commandFactory) {
        this.repository = requireNonNull(repository, "repository");
        this.commandFactory = requireNonNull(commandFactory, "commandFactory");
    }

    @Nonnull
    @Override
    public Command<List<Blame>> blame(@Nonnull BlameCommandParameters parameters, @Nonnull PageRequest pageRequest) {
        return commandFactory.blame(repository, parameters, pageRequest);
    }

    @Nonnull
    @Override
    public Command<Void> branches(@Nonnull BranchesCommandParameters parameters, @Nonnull BranchCallback callback) {
        return commandFactory.branches(repository, parameters, callback);
    }

    @Nonnull
    @Override
    public Command<Page<Branch>> branches(@Nonnull BranchesCommandParameters parameters,
                                          @Nonnull PageRequest pageRequest) {
        return commandFactory.branches(repository, parameters, pageRequest);
    }

    @Nonnull
    @Override
    public Command<Void> changes(@Nonnull ChangesCommandParameters parameters, @Nonnull ChangeCallback callback) {
        return commandFactory.changes(repository, parameters, callback);
    }

    @Nonnull
    @Override
    public Command<Page<Change>> changes(@Nonnull ChangesCommandParameters parameters,
                                         @Nonnull PageRequest pageRequest) {
        return commandFactory.changes(repository, parameters, pageRequest);
    }

    @Nonnull
    @Override
    public Command<Page<Changeset>> changesets(@Nonnull ChangesetsCommandParameters parameters,
                                               @Nonnull PageRequest pageRequest) {
        return commandFactory.changesets(repository, parameters, pageRequest);
    }

    @Nonnull
    @Override
    public Command<Commit> commit(@Nonnull CommitCommandParameters parameters) {
        return commandFactory.commit(repository, parameters);
    }

    @Nonnull
    @Override
    public Command<Void> commits(@Nonnull CommitsCommandParameters parameters, @Nonnull CommitCallback callback) {
        return commandFactory.commits(repository, parameters, callback);
    }

    @Nonnull
    @Override
    public Command<Page<Commit>> commits(@Nonnull CommitsCommandParameters parameters,
                                         @Nonnull PageRequest pageRequest) {
        return commandFactory.commits(repository, parameters, pageRequest);
    }

    @Deprecated
    @Nonnull
    @Override
    public Command<Void> create() {
        return commandFactory.create(repository);
    }

    @Nonnull
    @Override
    public Command<Branch> defaultBranch() {
        return commandFactory.defaultBranch(repository);
    }

    @Nonnull
    @Override
    public Command<Void> diff(@Nonnull DiffCommandParameters parameters, @Nonnull DiffContentCallback callback) {
        return commandFactory.diff(repository, parameters, callback);
    }

    @Nonnull
    @Override
    public Command<Void> directory(@Nonnull DirectoryCommandParameters parameters,
                                   @Nonnull ContentTreeCallback callback, @Nonnull PageRequest pageRequest) {
        return commandFactory.directory(repository, parameters, callback, pageRequest);
    }

    @Nonnull
    @Override
    public Command<Void> file(@Nonnull FileCommandParameters parameters, @Nonnull FileContentCallback callback,
                              @Nonnull PageRequest pageRequest) {
        return commandFactory.file(repository, parameters, callback, pageRequest);
    }

    @Deprecated
    @Nonnull
    @Override
    public Command<Void> fork(@Nonnull Repository fork) {
        return commandFactory.fork(repository, fork);
    }

    @Nonnull
    @Override
    public Command<Void> heads(@Nonnull RefCallback callback) {
        return commandFactory.heads(repository, callback);
    }

    @Deprecated
    @Nonnull
    @Override
    public Command<Branch> merge(@Nonnull MergeCommandParameters parameters) {
        return commandFactory.merge(repository, parameters);
    }

    @Nonnull
    @Override
    public Command<Void> rawFile(@Nonnull RawFileCommandParameters parameters,
                                 @Nonnull TypeAwareOutputSupplier outputSupplier) {
        return commandFactory.rawFile(repository, parameters, outputSupplier);
    }

    @Nonnull
    @Override
    public Command<Ref> resolveRef(@Nonnull ResolveRefCommandParameters parameters) {
        return commandFactory.resolveRef(repository, parameters);
    }

    @Deprecated
    @Nonnull
    @Override
    public Command<Ref> resolveRef(@Nonnull String refId) {
        return commandFactory.resolveRef(repository, refId);
    }

    @Nonnull
    @Override
    public Command<Map<String, Ref>> resolveRefs(@Nonnull ResolveRefsCommandParameters parameters) {
        return commandFactory.resolveRefs(repository, parameters);
    }

    @Nonnull
    @Override
    public Command<Void> tags(@Nonnull TagsCommandParameters parameters, @Nonnull TagCallback callback) {
        return commandFactory.tags(repository, parameters, callback);
    }

    @Nonnull
    @Override
    public Command<Page<Tag>> tags(@Nonnull TagsCommandParameters parameters, @Nonnull PageRequest pageRequest) {
        return commandFactory.tags(repository, parameters, pageRequest);
    }

    @Nonnull
    @Override
    public Command<Void> traverseCommits(@Nonnull TraversalCallback callback) {
        return commandFactory.traverseCommits(repository, callback);
    }

    @Nonnull
    @Override
    public Command<ContentTreeNode.Type> type(@Nonnull TypeCommandParameters parameters) {
        return commandFactory.type(repository, parameters);
    }

    @Deprecated
    @Nonnull
    @Override
    public Command<Void> updateDefaultBranch(@Nonnull String branchName)
            throws IllegalArgumentException, UnsupportedOperationException {
        return commandFactory.updateDefaultBranch(repository, branchName);
    }
}
