package com.atlassian.bitbucket.mesh.git.builder.lstree;

import com.atlassian.bitbucket.mesh.git.batch.BatchChange;
import com.atlassian.bitbucket.mesh.git.batch.BatchChangeType;
import com.atlassian.bitbucket.mesh.io.NullTerminatedWriter;
import com.atlassian.bitbucket.mesh.process.handler.AbstractLineStdioHandler;
import com.atlassian.bitbucket.mesh.process.handler.LineDecoder;

import javax.annotation.Nonnull;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.util.Objects.requireNonNull;

public class FileWritingLsTreeStdioHandler extends AbstractLineStdioHandler<Void> {

    private static final Pattern DIRECTORY_TREE_PATTERN = Pattern.compile("\\d+ blob ([0-9a-fA-F]{40})\\s+(\\d+)\\t(.*)");
    private static final int GROUP_CONTENT_ID = 1;
    private static final int GROUP_PATH = 3;
    private static final int GROUP_SIZE = 2;

    private final NullTerminatedWriter writer;

    public FileWritingLsTreeStdioHandler(@Nonnull Writer writer) {
        super(StandardCharsets.UTF_8, LineDecoder.Mode.NULL);

        this.writer = new NullTerminatedWriter(requireNonNull(writer, "writer"));
    }

    @Override
    public Void getResult() {
        return null;
    }

    @Override
    protected boolean onStdout(@Nonnull String line, boolean truncated) {
        Matcher matcher = DIRECTORY_TREE_PATTERN.matcher(line);
        if (matcher.matches()) {
            try {
                // We don't need to unescape the path, it's not escaped with null-terminated output (-z)
                BatchChange.write(matcher.group(GROUP_PATH), BatchChangeType.ADD, matcher.group(GROUP_CONTENT_ID),
                        Long.parseLong(matcher.group(GROUP_SIZE)), writer);
            } catch (IOException e) {
                throw new UncheckedIOException("Failed to write file change", e);
            }
        }

        return true;
    }
}
