package eu.dnetlib.lbs.subscriptions;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;

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

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import eu.dnetlib.lbs.elasticsearch.Event;
import eu.dnetlib.lbs.events.input.MapValueType;
import eu.dnetlib.lbs.utils.DateParser;

@RunWith(MockitoJUnitRunner.class)
public class ConditionTest {

	@Mock
	private Event event;

	@Before
	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));
	}

}
