package com.atlassian.bitbucket.mesh.git;

import com.atlassian.bitbucket.mesh.io.IoBiConsumer;
import com.atlassian.bitbucket.mesh.io.MoreFiles;
import com.atlassian.bitbucket.mesh.io.UnderLock;
import com.atlassian.bitbucket.mesh.repository.Repository;

import javax.annotation.Nonnull;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.nio.file.Path;

import static com.atlassian.bitbucket.mesh.git.GitConstants.*;

public class DefaultGitRepositoryLayout implements GitRepositoryLayout {

    @Override
    public void editConfig(@Nonnull Repository repository, @Nonnull IoBiConsumer<Reader, Writer> mutator)
            throws IOException {
        UnderLock.forFile(repository.getPath().resolve(PATH_CONFIG)).edit(mutator, true);
    }

    @Override
    public void editFile(@Nonnull Repository repository, @Nonnull String relativePath,
                         @Nonnull IoBiConsumer<Reader, Writer> mutator) throws IOException {
        Path repoDir = repository.getPath();
        Path file = repoDir.resolve(relativePath);
        if (!MoreFiles.isWithin(file, repoDir)) {
            throw new IllegalArgumentException(relativePath + " does not resolve to a path inside the repository");
        }

        UnderLock.forFile(file).edit(mutator, false);
    }

    @Nonnull
    @Override
    public Path getApplicationInfoDir(@Nonnull Repository repository) {
        return MoreFiles.mkdir(repository.getPath(), PATH_APPLICATION_INFO);
    }

    @Nonnull
    @Override
    public Path getGcPidFile(@Nonnull Repository repository) {
        return getApplicationInfoDir(repository).resolve(PATH_GC_PID);
    }

    @Nonnull
    @Override
    public Path getObjectsDir(@Nonnull Repository repository) {
        return repository.getPath().resolve(GitConstants.PATH_OBJECTS);
    }
}
