package routines;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import org.junit.jupiter.api.Test;

class LcagGeneralTest {

	@Test
	void testFirstValue() {
		Object result;

		result = LcagGeneral.firstValue("1", "2", "3");
		assertEquals("1", result);

		result = LcagGeneral.firstValue(null, null, "3");
		assertEquals("3", result);

		result = LcagGeneral.firstValue();
		assertEquals(null, result);

		result = LcagGeneral.firstValue((String) null);
		assertEquals(null, result);

		result = LcagGeneral.firstValue(null, Integer.valueOf(8));
		assertEquals(8, result);

		// Test mixed argument types (not actually needed):
		result = LcagGeneral.firstValue(null, Integer.valueOf(8), "2");
		assertEquals(8, result);

		result = LcagGeneral.firstValue(null, "2", Integer.valueOf(8));
		assertEquals("2", result);

	}

	@Test
	void testInSync() {
		boolean result;

		result = LcagGeneral.inSync("A", "A");
		assertTrue(result);

	}

	@Test
	void testInSyncIgnoreCase() {
		boolean result = LcagGeneral.inSyncIgnoreCase("A", "a");
		assertTrue(result);
	}

	@Test
	void testCompareValue() {
		SimpleDateFormat df = LcagDateTime.MDM_DATE_FORMAT;
		Date aDate = new Date();
		String aDateString = df.format(aDate);
		String result;

		// Test differences in spaces only
		// '+' means: replace '+' by blanc here to match 2nd arg
		// '-' means: delete '-' in 2nd arg to match first arg
		result = LcagGeneral.compareValue("ab c", "abc");
		assertEquals("_spacesDiffer_ab+", result);

		result = LcagGeneral.compareValue("abc", "ab c");
		assertEquals("_spacesDiffer_ab-", result);

		result = LcagGeneral.compareValue("a  bc", "ab  c");
		assertEquals("_spacesDiffer_a++b--c", result);

		result = LcagGeneral.compareValue("L3:LYS GCG", "L3:LYS GCG");
		assertEquals("_equal_", result);

		// Test <TAB> and new line differences
		result = LcagGeneral.compareValue("a\nbc", "ab\tc");
		assertEquals("_spacesDiffer_a", result); // only \n and \t difference starting after char 'a'

		result = LcagGeneral.compareValue("1 2 3", "123");
		assertEquals("_spacesDiffer_1+2", result);

		// Date parameter tests
		result = LcagGeneral.compareValue("2021-02-11", "2019-02-11");
		assertEquals("2019-02-11", result); // Time diffs dont matter

		result = LcagGeneral.compareValue(aDate, new Date());
		assertEquals("_equal_", result); // Time diffs dont matter

		result = LcagGeneral.compareValue(aDate, null);
		assertEquals("_n/a_", result);

		result = LcagGeneral.compareValue(null, aDate);
		assertEquals(aDateString, result);

	}

	@Test
	void testIncrementCounter() {
		Integer result;
		HashMap<String, Object> globalMap = new HashMap<String, Object>();

		result = LcagGeneral.incrementCounter(globalMap, "aCounter");
		assertEquals((Integer) 1, result, "New defined counter should have value 1");

		result = LcagGeneral.incrementCounter(globalMap, "aCounter");
		assertEquals((Integer) 2, result, "Existing counter incremented should have next higher value");

		result = LcagGeneral.incrementCounter(globalMap, "aCounter2");
		assertEquals((Integer) 1, result, "Second new counter should start with value 1");
	}

	@Test
	void testInSyncByPolicy() {
		boolean result;

		result = LcagGeneral.inSyncByPolicy("A", "A", LcagGeneral.IN_SYNC_POLICY_CASE_SENSITIVE);
		assertTrue(result, "Should be in-sync");

		result = LcagGeneral.inSyncByPolicy("A", "a", LcagGeneral.IN_SYNC_POLICY_CASE_SENSITIVE);
		assertFalse(result, "Should not be in-sync");

		result = LcagGeneral.inSyncByPolicy("A", "a", LcagGeneral.IN_SYNC_POLICY_IGNORE_CASE);
		assertTrue(result, "Should be in-sync");
	}

	@Test
	void testIntersect() {
		List<String> list1 = new ArrayList<String>(Arrays.asList("A", "B", "C", "D", "E"));
		List<String> list2 = Arrays.asList("1", "C", "2", "D", "3");

		boolean result = list1.retainAll(list2);
		List<String> expected = Arrays.asList("C", "D");

		assertTrue(result, "List should have changed");
		assertArrayEquals(expected.toArray(), list1.toArray());
	}

}
