package ua.nure.jfn.task4;

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

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Method;

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

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

	private static final PrintStream STD_OUT = System.out;

	private final ByteArrayOutputStream baos = new ByteArrayOutputStream();

	private final PrintStream out = new PrintStream(baos);

	private static String removeCR(String s) {
		return s.replaceAll("\r?", "");
	}

	@ParameterizedTest
	@CsvFileSource(resources = "part5.csv", delimiter = ';', ignoreLeadingAndTrailingWhitespace = false)
	void part5(String actionsData, String expectedTree) throws Exception {
		String expected = expectedTree == null
				? ""
				: expectedTree.replaceAll("~", System.lineSeparator());

		Tree<Integer> tree = new Tree<>();
		for (String action : actionsData.split("\\s+")) {
			String actionName = actionResolver(action.charAt(0));
			Method actionMethod = Tree.class.getMethod(actionName, Comparable.class);
			String actionValues = action.substring(action.indexOf('-') + 1);
			for (String value : actionValues.split("-")) {
				actionMethod.invoke(tree, new Object[] { Integer.parseInt(value) });
			}
		}
		String actual = null;
		try {
			System.setOut(out);

			tree.print();

			out.flush();
			actual = baos.toString();
		} finally {
			System.setOut(STD_OUT);
		}
		expected = removeCR(expected).stripTrailing();
		actual = removeCR(actual.replaceAll("(?m)\\s+$", "").stripTrailing());
		assertEquals(expected, actual);
	}

	private static String actionResolver(char actionChar) {
		switch (actionChar) {
		case 'a':
			return "add";
		case 'r':
			return "remove";
		}
		return null;
	}

}
