package com.atlassian.bitbucket.mesh.git.gc;

import com.google.common.io.LineProcessor;

import javax.annotation.Nonnull;
import java.io.IOException;
import java.io.Writer;
import java.time.Duration;
import java.time.Instant;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * A {@link LineProcessor} which prunes {@code gc.log} entries which are older than a configured threshold,
 * or which don't follow the expected format.
 */
class GcLogProcessor implements LineProcessor<Void> {

    private static final Pattern PATTERN_LOG_ENTRY = Pattern.compile("([\\d]+): .+$");

    private final Writer writer;
    private final long threshold;

    GcLogProcessor(Writer writer, Duration duration) {
        this.writer = writer;

        threshold = Instant.now().minus(duration).getEpochSecond();
    }

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

    @Override
    public boolean processLine(@Nonnull String line) throws IOException {
        Matcher matcher = PATTERN_LOG_ENTRY.matcher(line);
        if (matcher.matches()) { // Drop any malformed lines
            long timestamp = Long.parseLong(matcher.group(1));
            if (timestamp < threshold) {
                // gc.log lines are ordered from newest to oldest, so once we find a line that exceeds
                // the threshold we know all subsequent lines should be pruned as well
                return false;
            }
            // If the entry is newer than the threshold, copy it to the new log
            writer.write(line);
            writer.write('\n');
        }

        // If the line wasn't pruned, or was pruned because it didn't match the expected format, read
        // the next line
        return true;
    }
}
