package eu.dnetlib.data.utility.cleaner;

import static org.junit.Assert.*;

import java.io.StringReader;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnit44Runner;

@RunWith(MockitoJUnit44Runner.class)
public class GroovyRuleTest {

	/**
	 * Class Under Test
	 */
	private GroovyRule rule;

	@Before
	public void setUp() throws Exception {
		rule = new GroovyRule();
	}

	@Test
	public void testApplyXpathRule_simple_constant() throws Exception {
		String xpath = "/a/b";

		rule.setXpath(xpath);
		rule.setGroovyRule("'YYYY'");

		Document doc = execute("<a><b>XXXX</b></a>");

		assertEquals("YYYY", doc.valueOf(xpath));
	}

	@Test
	public void testApplyXpathRule_simple_regex() throws Exception {
		String xpath = "/a/b";

		rule.setXpath(xpath);
		rule.setGroovyRule("(input =~ /X/).replaceAll('Y')");

		Document doc = execute("<a><b>aXaXa</b></a>");

		assertEquals("aYaYa", doc.valueOf(xpath));
	}

	@Test
	public void testApplyXpathRule_simple_upper() throws Exception {
		String xpath = "/a/b";

		rule.setXpath(xpath);
		rule.setGroovyRule("input.toUpperCase()");

		Document doc = execute("<a><b>xyz</b></a>");

		assertEquals("XYZ", doc.valueOf(xpath));
	}

	@Test
	public void testApplyXpathRule_multi() throws Exception {
		String xpath = "/a/b";

		rule.setXpath(xpath);
		rule.setGroovyRule("'Y'");

		Document doc = execute("<a><b>X</b><b>X</b><b>X</b></a>");

		List<?> list = doc.selectNodes(xpath);

		assertEquals(3, list.size());
		for (Object o : list) {
			assertEquals("Y", ((Node) o).getText());
		}

	}

	@Test
	public void testApplyXpathRule_singleAttr() throws Exception {
		String xpath = "/a/b/@value";

		rule.setXpath(xpath);
		rule.setGroovyRule("'BBBB'");

		Document doc = execute("<a><b value='AAAA'>XXXX</b></a>");

		assertEquals("BBBB", doc.valueOf(xpath));
		assertEquals("XXXX", doc.valueOf("/a/b"));
	}

	@Test
	public void testApplyXpathRule_multiAttr() throws Exception {
		String xpath = "/a/b/@value";

		rule.setXpath(xpath);
		rule.setGroovyRule("'B'");

		Document doc = execute("<a><b value='a' /><b value='b' /><b value='c' /></a>");

		List<?> list = doc.selectNodes(xpath);

		assertEquals(3, list.size());
		for (Object o : list) {
			assertEquals("B", ((Node) o).getText());
		}
	}

	@Test
	public void testApplyXpathRule_complex() throws Exception {
		String xpath = "/a/b";

		rule.setXpath(xpath);
		rule.setGroovyRule("'B'");

		Document doc = execute("<a><b>X<c>C</c></b></a>");

		assertTrue(doc.valueOf(xpath).contains("B"));
		assertEquals("C", doc.valueOf("/a/b/c"));
	}

	private Document execute(String xml) throws Exception {
		SAXReader reader = new SAXReader();
		Document doc = reader.read(new StringReader(xml));

		System.out.println("BEFORE:\n" + doc.asXML() + "\n");
		rule.applyXpathRule(doc, null);
		System.out.println("AFTER:\n" + doc.asXML() + "\n");

		System.out.println("-----------------------------\n");
		return doc;
	}
}
