package com.atlassian.bitbucket.mesh.git;

import com.atlassian.bitbucket.mesh.repository.BitbucketServerRepository;
import com.atlassian.bitbucket.mesh.repository.ManagedRepository;
import com.atlassian.bitbucket.mesh.repository.Repository;
import com.atlassian.bitbucket.mesh.repository.RepositoryVisitor;

import javax.annotation.Nonnull;
import java.util.function.Function;

import static com.atlassian.bitbucket.mesh.git.GitConstants.PATH_DARK_REFS;
import static com.atlassian.bitbucket.mesh.git.GitConstants.PATH_STASH_REFS;

/**
 * Mapper that maps stash-refs/* -&gt; dark-refs/* when uploading to managed repositories and
 * dark-refs/* -&gt; stash-refs/* when uploading to Bitbucket Server repositories.
 */
public class DarkRefMapper implements RepositoryVisitor<Function<String, String>> {

    public static final DarkRefMapper INSTANCE = new DarkRefMapper();

    private DarkRefMapper() {
        // No-ops
    }

    @Override
    public Function<String, String> visit(@Nonnull BitbucketServerRepository repository) {
        return DarkRefMapper::darkRefsToStashRefs;
    }

    @Override
    public Function<String, String> visit(@Nonnull ManagedRepository repository) {
        return DarkRefMapper::stashRefsToDarkRefs;
    }

    @Override
    public Function<String, String> defaultValue(Repository repository) {
        //Don't attempt to translate any dark refs when uploading to a
        //PathRepository, WorkTree or SharedObjectsRepository.
        return Function.identity();
    }

    private static String darkRefsToStashRefs(String refId) {
        return refId.startsWith(PATH_DARK_REFS) ?
                PATH_STASH_REFS + refId.substring(PATH_DARK_REFS.length()) : refId;
    }

    private static String stashRefsToDarkRefs(String refId) {
        return refId.startsWith(PATH_STASH_REFS) ?
                PATH_DARK_REFS + refId.substring(PATH_STASH_REFS.length()) : refId;
    }
}
