package eu.dnetlib.broker.common.subscriptions;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.when;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import eu.dnetlib.broker.common.elasticsearch.Event;
import eu.dnetlib.broker.common.utils.DateParser;
import eu.dnetlib.broker.common.utils.MapValueType;

@ExtendWith(MockitoExtension.class)
public class ConditionTest {

	@Mock
	private Event event;

	@BeforeEach
	public void setUp() throws Exception {

		final Map<String, Object> map = new HashMap<>();
		map.put("repo", "PUMA");
		map.put("total", 1234l);
		map.put("impact", 1.23d);
		map.put("impact", 1.23d);
		map.put("date", DateParser.parse("2012-05-15"));
		map.put("open", false);
		map.put("authors", Arrays.asList("Michele Artini", "Claudio Atzori", "Alessia Bardi"));
		when(this.event.getMap()).thenReturn(map);
	}

	@Test
	public void testVerifyEvent_String() {
		assertTrue(new MapCondition("repo", MapValueType.STRING, ConditionOperator.EXACT, Arrays.asList(new ConditionParams("PUMA", null)))
			.verifyEvent(this.event));
		assertFalse(new MapCondition("repo", MapValueType.STRING, ConditionOperator.EXACT, Arrays.asList(new ConditionParams("People", null)))
			.verifyEvent(this.event));
	}

	@Test
	public void testVerifyEvent_Integer() {
		assertTrue(new MapCondition("total", MapValueType.INTEGER, ConditionOperator.EXACT, Arrays.asList(new ConditionParams("1234", null)))
			.verifyEvent(this.event));
		assertFalse(new MapCondition("total", MapValueType.INTEGER, ConditionOperator.EXACT, Arrays.asList(new ConditionParams("2222", null)))
			.verifyEvent(this.event));
		assertTrue(new MapCondition("total", MapValueType.INTEGER, ConditionOperator.RANGE, Arrays.asList(new ConditionParams("1000", "2000")))
			.verifyEvent(this.event));
		assertTrue(new MapCondition("total", MapValueType.INTEGER, ConditionOperator.RANGE, Arrays.asList(new ConditionParams("1200.52", "1300,45")))
			.verifyEvent(this.event));
		assertTrue(new MapCondition("total", MapValueType.INTEGER, ConditionOperator.RANGE, Arrays.asList(new ConditionParams("1000", null)))
			.verifyEvent(this.event));
		assertTrue(new MapCondition("total", MapValueType.INTEGER, ConditionOperator.RANGE, Arrays.asList(new ConditionParams(null, "2000")))
			.verifyEvent(this.event));
		assertFalse(new MapCondition("total", MapValueType.INTEGER, ConditionOperator.RANGE, Arrays.asList(new ConditionParams("0", "1000")))
			.verifyEvent(this.event));
	}

	@Test
	public void testVerifyEvent_Float() {
		assertTrue(new MapCondition("impact", MapValueType.FLOAT, ConditionOperator.EXACT, Arrays.asList(new ConditionParams("1.23d", null)))
			.verifyEvent(this.event));
		assertFalse(new MapCondition("impact", MapValueType.FLOAT, ConditionOperator.EXACT, Arrays.asList(new ConditionParams("1.2d", null)))
			.verifyEvent(this.event));
		assertTrue(new MapCondition("impact", MapValueType.FLOAT, ConditionOperator.RANGE, Arrays.asList(new ConditionParams("1", "2")))
			.verifyEvent(this.event));
		assertTrue(new MapCondition("impact", MapValueType.FLOAT, ConditionOperator.RANGE, Arrays.asList(new ConditionParams("1.2", "1.35")))
			.verifyEvent(this.event));
		assertTrue(new MapCondition("impact", MapValueType.FLOAT, ConditionOperator.RANGE, Arrays.asList(new ConditionParams("1", null)))
			.verifyEvent(this.event));
		assertTrue(new MapCondition("impact", MapValueType.FLOAT, ConditionOperator.RANGE, Arrays.asList(new ConditionParams(null, "2")))
			.verifyEvent(this.event));
		assertFalse(new MapCondition("impact", MapValueType.FLOAT, ConditionOperator.RANGE, Arrays.asList(new ConditionParams("2", "3.2")))
			.verifyEvent(this.event));
	}

	@Test
	public void testVerifyEvent_Date() {
		assertTrue(new MapCondition("date", MapValueType.DATE, ConditionOperator.EXACT, Arrays.asList(new ConditionParams("2012-05-15", null)))
			.verifyEvent(this.event));
		assertFalse(new MapCondition("date", MapValueType.DATE, ConditionOperator.EXACT, Arrays.asList(new ConditionParams("2012-05-16", null)))
			.verifyEvent(this.event));
		assertTrue(new MapCondition("date", MapValueType.DATE, ConditionOperator.RANGE, Arrays.asList(new ConditionParams("2012-05-01", "2012-05-31")))
			.verifyEvent(this.event));
		assertTrue(new MapCondition("date", MapValueType.DATE, ConditionOperator.RANGE, Arrays.asList(new ConditionParams("2012-05-01", null)))
			.verifyEvent(this.event));
		assertTrue(new MapCondition("date", MapValueType.DATE, ConditionOperator.RANGE, Arrays.asList(new ConditionParams(null, "2012-05-31")))
			.verifyEvent(this.event));
		assertFalse(new MapCondition("date", MapValueType.DATE, ConditionOperator.RANGE, Arrays.asList(new ConditionParams("2013-01-01", "2013-12-31")))
			.verifyEvent(this.event));
	}

	@Test
	public void testVerifyEvent_Boolean() {
		assertTrue(new MapCondition("open", MapValueType.BOOLEAN, ConditionOperator.EXACT, Arrays.asList(new ConditionParams("false", null)))
			.verifyEvent(this.event));
		assertFalse(new MapCondition("open", MapValueType.BOOLEAN, ConditionOperator.EXACT, Arrays.asList(new ConditionParams("true", null)))
			.verifyEvent(this.event));
	}

	@Test
	public void testVerifyEvent_List_String() {
		assertTrue(new MapCondition("authors", MapValueType.LIST_STRING, ConditionOperator.MATCH_ALL,
			Arrays.asList(new ConditionParams("artini michele", null))).verifyEvent(this.event));
		assertTrue(new MapCondition("authors", MapValueType.LIST_STRING, ConditionOperator.MATCH_ALL, Arrays.asList(new ConditionParams("artini", null)))
			.verifyEvent(this.event));
		assertTrue(new MapCondition("authors", MapValueType.LIST_STRING, ConditionOperator.MATCH_ANY,
			Arrays.asList(new ConditionParams("artini michele", null))).verifyEvent(this.event));
		assertTrue(new MapCondition("authors", MapValueType.LIST_STRING, ConditionOperator.MATCH_ANY,
			Arrays.asList(new ConditionParams("artini giuseppe", null))).verifyEvent(this.event));
		assertTrue(new MapCondition("authors", MapValueType.LIST_STRING, ConditionOperator.MATCH_ANY, Arrays.asList(new ConditionParams("artini", null)))
			.verifyEvent(this.event));
		assertFalse(new MapCondition("authors", MapValueType.LIST_STRING, ConditionOperator.MATCH_ALL,
			Arrays.asList(new ConditionParams("artini giuseppe", null))).verifyEvent(this.event));
		assertFalse(new MapCondition("authors", MapValueType.LIST_STRING, ConditionOperator.MATCH_ALL, Arrays.asList(new ConditionParams("giuseppe", null)))
			.verifyEvent(this.event));
		assertFalse(new MapCondition("authors", MapValueType.LIST_STRING, ConditionOperator.MATCH_ALL,
			Arrays.asList(new ConditionParams("bardi claudio", null))).verifyEvent(this.event));
		assertFalse(new MapCondition("authors", MapValueType.LIST_STRING, ConditionOperator.MATCH_ANY,
			Arrays.asList(new ConditionParams("andrea mannocci", null))).verifyEvent(this.event));
		assertFalse(new MapCondition("authors", MapValueType.LIST_STRING, ConditionOperator.MATCH_ANY, Arrays.asList(new ConditionParams("mannocci", null)))
			.verifyEvent(this.event));
	}

}
