package com.bishnet.cucumber.parallel.report;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.nio.file.StandardOpenOption;
import java.util.List;
import java.util.ListIterator;
import java.util.UUID;

public class HtmlReportMerger {

	private static final String IMAGE_PATTERN = "*.png";
	private static final String REPORT_JS = "report.js";
	private List<Path> reportDirs;
	
	public HtmlReportMerger(List<Path> reportDirs) {
		this.reportDirs = reportDirs;
	}
	
	public void merge(Path mergedReport) throws IOException {
		Files.createDirectories(mergedReport);
		boolean firstReport = true;
		for (Path reportDir : reportDirs) {
			if (firstReport) {
				copyResourceFiles(reportDir, mergedReport);
				firstReport = false;
			}
			copyImagesAndJavaScriptWithImageRename(reportDir, mergedReport);
		}
	}
	
	private void copyImagesAndJavaScriptWithImageRename(Path reportDir, Path targetDir) throws IOException {
		try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(reportDir, IMAGE_PATTERN)) {
			List<String> reportJs = Files.readAllLines(reportDir.resolve(REPORT_JS), StandardCharsets.UTF_8);
			for (Path embeddedImage : dirStream) {
				String uniqueName = UUID.randomUUID().toString() + ".png";
				Files.copy(embeddedImage, targetDir.resolve(uniqueName));
				ListIterator<String> listIterator = reportJs.listIterator();
				while(listIterator.hasNext()) {
					listIterator.set(listIterator.next().replace(embeddedImage.getFileName().toString(), uniqueName));
				}
			}
			Files.write(targetDir.resolve(REPORT_JS), reportJs, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.APPEND);
		}
	}
	
	private void copyResourceFiles(Path sourceDir, Path targetDir) throws IOException {
		PathMatcher reportAndImageMatcher = FileSystems.getDefault().getPathMatcher("glob:{" + REPORT_JS +"," + IMAGE_PATTERN +"}");
		try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(sourceDir)) {
			for (Path resourceFile : dirStream)
				if (!reportAndImageMatcher.matches(resourceFile.getFileName()))
					Files.copy(resourceFile, targetDir.resolve(resourceFile.getFileName()));
		}
	}
}

@@ -210,16 +210,49 @@
 .Files;%0A
+import java.nio.file.OpenOption;%0A
 import j
@@ -304,16 +304,57 @@
 atcher;%0A
+import java.nio.file.StandardCopyOption;%0A
 import j
@@ -968,33 +968,8 @@
 t);%0A
-%09%09%09%09firstReport = false;%0A
 %09%09%09%7D
@@ -1030,25 +1030,62 @@
 mergedReport
-)
+, firstReport);%0A%09%09%09firstReport = false
 ;%0A%09%09%7D%0A%09%7D%0A%09%0A%09
@@ -1158,32 +1158,57 @@
 , Path targetDir
+, boolean overwriteReport
 ) throws IOExcep
@@ -1793,16 +1793,247 @@
 %09%7D%0A%09%09%09%7D%0A
+%09%09%09OpenOption%5B%5D copyOptions;%0A%09%09%09if (overwriteReport)%0A%09%09%09%09copyOptions = new OpenOption%5B%5D %7B StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING %7D;%0A%09%09%09else%0A%09%09%09%09copyOptions = new OpenOption%5B%5D %7B StandardOpenOption.APPEND %7D;%0A
 %09%09%09Files
@@ -2107,60 +2107,19 @@
 _8, 
-StandardOpenOption.CREATE, StandardOpenOption.APPEND
+copyOptions
 );%0A%09
@@ -2600,16 +2600,53 @@
 eName())
+, StandardCopyOption.REPLACE_EXISTING
 );%0A%09%09%7D%0A%09

Replace existing HTML report if target directory already exists.