package pingis.services;

import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by dwarfcrank on 7/25/17.
 */
@Service
public class SubmissionPackagingService {
    private List<Path> getDirectoryEntries(Path directory) throws IOException {
        List<Path> entries = new ArrayList<>();

        try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(directory)) {
            for (Path entry : directoryStream) {
                if (Files.isDirectory(entry)) {
                    List<Path> subEntries = getDirectoryEntries(entry);
                    entries.addAll(subEntries);
                } else {
                    entries.add(entry);
                }
            }
        }

        return entries;
    }

    private void addTemplateFiles(ArchiveOutputStream archive) throws IOException {
        // TODO: maybe get the template path from config?
        Path templateDirectory = FileSystems.getDefault().getPath("tmc-assets", "submission-template");
        List<Path> templateEntries = getDirectoryEntries(templateDirectory);

        for (Path entry : templateEntries) {
            // Paths must be relativized against the template directory root before including them into the Tar
            // archive. I.e. a file at ./tmc-assets/submission-template/directory/file.txt will be added to
            // the archive as ./directory/file.txt.
            String tarEntryName = templateDirectory.relativize(entry).toString();

            // TODO: special case for build.xml for renaming the project.
            ArchiveEntry archiveEntry = archive.createArchiveEntry(entry.toFile(), tarEntryName);

            archive.putArchiveEntry(archiveEntry);
            Files.copy(entry, archive);
            archive.closeArchiveEntry();
        }
    }

    private void addAdditionalFiles(ArchiveOutputStream archive, Map<String, byte[]> additionalFiles)
            throws IOException {
        for (String entryName : additionalFiles.keySet()) {
            byte[] content = additionalFiles.get(entryName);

            TarArchiveEntry tarEntry = new TarArchiveEntry(entryName);
            tarEntry.setSize(content.length);

            archive.putArchiveEntry(tarEntry);
            archive.write(content);
            archive.closeArchiveEntry();
        }
    }

    public byte[] packageSubmission(Map<String, byte[]> additionalFiles) throws IOException, ArchiveException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        try (ArchiveOutputStream archive = new ArchiveStreamFactory()
                .createArchiveOutputStream(ArchiveStreamFactory.TAR, outputStream)) {

            addTemplateFiles(archive);
            addAdditionalFiles(archive, additionalFiles);

            archive.finish();
        }

        return outputStream.toByteArray();
    }
}

@@ -1320,32 +1320,723 @@
 entries;%0A    %7D%0A%0A
+    private void addFile(ArchiveOutputStream archive, String tarFileName, Path filePath) throws IOException %7B%0A        ArchiveEntry archiveEntry = archive.createArchiveEntry(filePath.toFile(), tarFileName);%0A%0A        archive.putArchiveEntry(archiveEntry);%0A        Files.copy(filePath, archive);%0A        archive.closeArchiveEntry();%0A    %7D%0A%0A    private void addFile(ArchiveOutputStream archive, String tarFileName, byte%5B%5D fileContent) throws IOException %7B%0A        TarArchiveEntry tarEntry = new TarArchiveEntry(tarFileName);%0A        tarEntry.setSize(fileContent.length);%0A%0A        archive.putArchiveEntry(tarEntry);%0A        archive.write(fileContent);%0A        archive.closeArchiveEntry();%0A    %7D%0A%0A
     private void
@@ -2095,32 +2095,32 @@
 s IOException %7B%0A
-
         // TODO:
@@ -2833,224 +2833,44 @@
     
-ArchiveEntry archiveEntry = archive.createArchiveEntry(entry.toFile(), tarEntryName);%0A%0A            archive.putArchiveEntry(archiveEntry);%0A            Files.copy(entry, archive);%0A            archive.closeArchiveE
+addFile(archive, tarEntryName, e
 ntry
-(
 );%0A 
@@ -3158,235 +3158,43 @@
     
-TarArchiveEntry tarEntry = new TarArchiveEntry(entryName);%0A            tarEntry.setSize(content.length);%0A%0A            archive.putArchiveEntry(tarEntry);%0A            archive.write(content);%0A            archive.closeArchiveEntry(
+addFile(archive, entryName, content
 );%0A 

Refactor addTemplateFiles and addAdditionalFiles slightly.