package ua.nure.jfn.task4;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvFileSource;

/**
 * @author Dmytro Kolesnykov
 */
public class Part3Test {

	private static final InputStream STD_IN = System.in;

	private static final PrintStream STD_OUT = System.out;

	private static final String TEST_DATA_FILE_ENCODINE = "UTF-8";

	private static final String EOL_CHAR = "~";

	private static final String[] EMPTY_ARGS = {};

	private static final String EOL = System.lineSeparator();

	private static final String BASE_NAME = "resources";

	private final ByteArrayOutputStream baos = new ByteArrayOutputStream();

	private final PrintStream out = new PrintStream(baos);

	private static String toMultiline(String line) {
		return line.replaceAll(EOL_CHAR, EOL).trim();
	}

	private static String removeCR(String s) {
		return s.replaceAll("\r?", "");
	}
	
	private static final URI classPathURI;
	
	static {
		try {
			classPathURI = Part3.class.getProtectionDomain().getCodeSource().getLocation().toURI();
		} catch (URISyntaxException ex) {
			throw new IllegalStateException(ex);
		}
	}

	@ParameterizedTest
	@CsvFileSource(resources = "part3.csv", delimiter = ';')
	void part3(String defaultLocale, String localesString, String consoleInput, String expectedLine) throws Exception {
		ResourceBundle.clearCache();
		Locale.setDefault(new Locale(defaultLocale));

		try (DirectoryStream<Path> stream = Files.newDirectoryStream(Path.of(classPathURI))) {
			for (Path p : stream) {
				if (p.toString().endsWith(".properties")) {
					Files.delete(p);
				}
			}
		}

		Path classPath = Paths.get(classPathURI);
		List<String> locales = Arrays.asList(localesString.trim().split(" "));
		String actual = "";
		InputStream is = null;
		try {
			for (String locale : locales) {
				String bundleName = BASE_NAME + '_' + locale + ".properties";
				is = getClass().getClassLoader().getResourceAsStream(locale + ".props");
				try (OutputStream out = new FileOutputStream(new File(classPath.toString(), bundleName))) {
					is.transferTo(out);
					is.close();
				}
			}
			String input = toMultiline(consoleInput);
			byte[] buf = input.getBytes(TEST_DATA_FILE_ENCODINE);
			ByteArrayInputStream bais = new ByteArrayInputStream(buf);
			System.setOut(out);
			System.setIn(bais);

			Part3.main(EMPTY_ARGS);

			out.flush();
			actual = baos.toString();
		} finally {
			System.setOut(STD_OUT);
			System.setIn(STD_IN);
		}
		assertEquals(removeCR(toMultiline(expectedLine)).trim(), removeCR(actual).trim());
	}

}
