package com.atlassian.bitbucket.scm.cache.git;

import com.atlassian.bitbucket.scm.ssh.ExitCodeCallback;
import com.atlassian.bitbucket.scm.ssh.SshScmRequest;
import com.atlassian.bitbucket.scm.ssh.SshScmRequestHandler;
import com.atlassian.bitbucket.server.ApplicationPropertiesService;
import com.atlassian.bitbucket.util.FileUtils;
import org.apache.commons.io.input.TeeInputStream;
import org.apache.commons.io.output.TeeOutputStream;

import javax.annotation.Nonnull;
import java.io.*;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * This class exists purely for debugging purposes. It allows you to enable configure an SshScmRequestHandler
 * (in atlassian-plugin.xml) that intercepts the input, output and error streams and writes them to separate files in
 * STASH_HOME/tmp/upload-pack/
 */
@SuppressWarnings("UnusedDeclaration")
public class LoggingGitSshRequestHandler implements SshScmRequestHandler {

    private final AtomicInteger counter;
    private final SshScmRequestHandler delegate;
    private final File dir;

    public LoggingGitSshRequestHandler(SshScmRequestHandler delegate, ApplicationPropertiesService propertiesService) {
        this.counter = new AtomicInteger(0);
        this.delegate = delegate;
        this.dir = new File(propertiesService.getTempDir(), "upload-pack");

        FileUtils.mkdir(this.dir);
    }

    @Nonnull
    @Override
    public Optional<SshScmRequest> create(@Nonnull String command, @Nonnull InputStream in, @Nonnull OutputStream out,
                                @Nonnull OutputStream err, @Nonnull ExitCodeCallback exitCodeCallback) {
        int count = counter.incrementAndGet();
        try {
            InputStream teeIn = new TeeInputStream(in, new FileOutputStream(new File(dir, "in" + count + ".txt")), true);
            OutputStream teeOut = new TeeOutputStream(out, new FileOutputStream(new File(dir, "out" + count + ".txt")));
            OutputStream teeErr = new TeeOutputStream(err, new FileOutputStream(new File(dir, "err" + count + ".txt")));

            return delegate.create(command, teeIn, teeOut, teeErr, exitCodeCallback);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public boolean supports(@Nonnull String remoteCommand) {
        return delegate.supports(remoteCommand);
    }
}
