package com.refactorerl.ui.common;

import static org.junit.Assert.*;

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

import org.junit.AfterClass;
import org.junit.Test;

import com.ericsson.otp.erlang.OtpErlangAtom;
import com.ericsson.otp.erlang.OtpErlangBoolean;
import com.ericsson.otp.erlang.OtpErlangList;
import com.ericsson.otp.erlang.OtpErlangObject;
import com.ericsson.otp.erlang.OtpErlangString;
import com.ericsson.otp.erlang.OtpErlangTuple;

public class OtpErlangHelperTest {

	@AfterClass
	public static void tearDownAfterClass() throws Exception {
	}

	@Test
	public void testToOtpErlangString() {
		OtpErlangObject normalString = OtpErlangHelper
				.toOtpErlangString("This should work.");
		assertTrue(normalString instanceof OtpErlangString);
		assertTrue(OtpErlangHelper.toUnquotedString(normalString).equals(
				"This should work."));
		OtpErlangObject emptyString = OtpErlangHelper.toOtpErlangString("");
		assertTrue(emptyString instanceof OtpErlangList);
		assertTrue(OtpErlangHelper.arity(emptyString) == 0);
	}

	@Test
	public void testBooleanValue() {
		assertTrue(OtpErlangHelper.booleanValue(new OtpErlangBoolean(true)));
		assertTrue(OtpErlangHelper.booleanValue(new OtpErlangAtom("true")));
		assertFalse(OtpErlangHelper.booleanValue(new OtpErlangBoolean(false)));
		assertFalse(OtpErlangHelper.booleanValue(new OtpErlangAtom("false")));

	}

	@Test
	public void testCreateList() {
		OtpErlangList ls = OtpErlangHelper.createList(new OtpErlangAtom("x"));
		assertTrue(ls.iterator().next().equals(new OtpErlangAtom("x")));
		ls = OtpErlangHelper.createList();
		assertTrue(ls.arity() == 0);
	}

	@Test
	public void testCreatePropListMapOfStringOtpErlangObject() {
		try {
			Map<String, OtpErlangObject> propMap = new HashMap<>();
			propMap.put("k1", new OtpErlangAtom("v1"));
			propMap.put("k2", new OtpErlangAtom("v2"));
			OtpErlangList propList = OtpErlangHelper.createPropList(propMap);

			assertTrue(propList.arity() == 2);

			OtpErlangTuple tup1 = OtpErlangHelper.nth(propList, 0);
			OtpErlangTuple tup2 = OtpErlangHelper.nth(propList, 1);

			assertTrue(tup1.arity() == 2 && tup2.arity() == 2);

			boolean ord1 = OtpErlangHelper.nthEqualsAtom(tup1, 0, "k1")
					&& OtpErlangHelper.nthEqualsAtom(tup1, 1, "v1")
					&& OtpErlangHelper.nthEqualsAtom(tup2, 0, "k2")
					&& OtpErlangHelper.nthEqualsAtom(tup2, 1, "v2");

			boolean ord2 = OtpErlangHelper.nthEqualsAtom(tup2, 0, "k1")
					&& OtpErlangHelper.nthEqualsAtom(tup2, 1, "v1")
					&& OtpErlangHelper.nthEqualsAtom(tup1, 0, "k2")
					&& OtpErlangHelper.nthEqualsAtom(tup1, 1, "v2");

			assertTrue(ord1 || ord2);

			propMap = new HashMap<>();
			propList = OtpErlangHelper.createPropList(propMap);
			assertTrue(propList.arity() == 0);

		} catch (ClassCastException e) {
			fail(e.toString());
		}
	}

	@Test
	public void testCreateTuple() {
		OtpErlangTuple tup = OtpErlangHelper
				.createTuple(new OtpErlangAtom("x"));
		assertTrue(tup.elementAt(0).equals(new OtpErlangAtom("x")));
		tup = OtpErlangHelper.createTuple();
		assertTrue(tup.arity() == 0);
	}

	@Test
	public void testNthEqualsAtom() {
		OtpErlangTuple tup = OtpErlangHelper.createTuple(
				new OtpErlangAtom("x"), new OtpErlangAtom("y"));
		OtpErlangList ls = OtpErlangHelper.createList(new OtpErlangAtom("x"),
				new OtpErlangAtom("y"));

		assertTrue(OtpErlangHelper.nthEqualsAtom(tup, 1, "y"));
		assertTrue(OtpErlangHelper.nthEqualsAtom(ls, 1, "y"));

		boolean b = false;
		try {
			assertTrue(OtpErlangHelper.nthEqualsAtom(ls, -1, "y"));
		} catch (IndexOutOfBoundsException e) {
			b = true;
		}
		assertTrue(b);

		b = false;
		try {
			assertTrue(OtpErlangHelper.nthEqualsAtom(ls, 42, "y"));
		} catch (IndexOutOfBoundsException e) {
			b = true;
		}
		assertTrue(b);

	}

	@Test
	public void testTranslatePropList() {
		OtpErlangList propList = OtpErlangHelper.createList();
		Map<String, OtpErlangObject> propMap = OtpErlangHelper
				.translatePropList(propList);
		assertTrue(propMap.keySet().size() == 0);

		boolean b = false;
		try {
			propList = OtpErlangHelper
					.createList(OtpErlangHelper.createTuple());
			propMap = OtpErlangHelper.translatePropList(propList);
		} catch (IllegalArgumentException e) {
			b = true;
		}
		assertTrue(b);

		b = false;
		try {
			propList = OtpErlangHelper.createList(OtpErlangHelper
					.createTuple(new OtpErlangAtom("k1")));
			propMap = OtpErlangHelper.translatePropList(propList);
		} catch (IllegalArgumentException e) {
			b = true;
		}
		assertTrue(b);

		propList = OtpErlangHelper.createList(OtpErlangHelper.createTuple(
				new OtpErlangAtom("k1"), new OtpErlangBoolean(true)),
				OtpErlangHelper.createTuple(new OtpErlangAtom("k2"),
						new OtpErlangBoolean(false)));
		propMap = OtpErlangHelper.translatePropList(propList);
		assertTrue(OtpErlangHelper.booleanValue(propMap.get("k1")));
		assertFalse(OtpErlangHelper.booleanValue(propMap.get("k2")));
		assertTrue(propMap.keySet().size() == 2);
	}

}
