package migl.lisp.operator;

import static org.junit.Assert.assertEquals;

import java.math.BigInteger;

import org.junit.Before;
import org.junit.Test;

import migl.lisp.Lisp;
import migl.lisp.LispElement;
import migl.lisp.LispError;
import migl.lisp.LispEval;
import migl.lisp.LispFactory;
import migl.util.ConsList;
import migl.util.ConsListFactory;

public class ComparatorOperatorOwnTest {
	
	private Lisp interpreter;

	@Before
	public void init() {
		interpreter = LispFactory.makeIntepreter();
	}
	
	@Test
	public void testSupOperator() throws LispError {
		assertEquals(LispElement.generate(true), interpreter.eval("(> 8 5)"));
		assertEquals(LispElement.generate(false), interpreter.eval("(> 8 8)"));
		assertEquals(LispElement.generate(false), interpreter.eval("(> 5 8)"));
		assertEquals(LispElement.generate(false), interpreter.eval("(> 8 8 10)"));
		assertEquals(LispElement.generate(false), interpreter.eval("(> 5 5 8)"));
	}
	
	@Test
	public void testSupOrEquOperator() throws LispError {
		assertEquals(LispElement.generate(true), interpreter.eval("(>= 8 5)"));
		assertEquals(LispElement.generate(true), interpreter.eval("(>= 8 8)"));
		assertEquals(LispElement.generate(false), interpreter.eval("(>= 5 8)"));
		assertEquals(LispElement.generate(true), interpreter.eval("(>= 8 8 8)"));
		assertEquals(LispElement.generate(false), interpreter.eval("(>= 5 4 8)"));
	}
	
	@Test
	public void testInfOperator() throws LispError {
		assertEquals(LispElement.generate(true), interpreter.eval("(< 5 8)"));
		assertEquals(LispElement.generate(false), interpreter.eval("(< 8 8)"));
		assertEquals(LispElement.generate(false), interpreter.eval("(< 8 5)"));
		assertEquals(LispElement.generate(false), interpreter.eval("(< 8 8 8)"));
		assertEquals(LispElement.generate(false), interpreter.eval("(< 8 8 5)"));
	}
	
	@Test
	public void testInfOrEquOperator() throws LispError {
		assertEquals(LispElement.generate(true), interpreter.eval("(<= 5 8)"));
		assertEquals(LispElement.generate(true), interpreter.eval("(<= 8 8)"));
		assertEquals(LispElement.generate(false), interpreter.eval("(<= 8 5)"));
		assertEquals(LispElement.generate(true), interpreter.eval("(<= 8 8 10)"));
		assertEquals(LispElement.generate(false), interpreter.eval("(<= 8 8 10 5)"));
	}
	
	@Test
	public void testEquOperator() throws LispError {
		assertEquals(LispElement.generate(true), interpreter.eval("(= 8 8)"));
		assertEquals(LispElement.generate(false), interpreter.eval("(= 8 5)"));
		assertEquals(LispElement.generate(true), interpreter.eval("(= 8 8 8 8)"));
		assertEquals(LispElement.generate(false), interpreter.eval("(= 8 8 5 8)"));
	}
	
	@Test(expected = LispError.class)
	public void testIncorrectNumberArgumentComparator() throws LispError {
		interpreter.eval("(=)");
	}
	
	@Test(expected = LispError.class)
	public void testComparatorOperatorException() throws LispError {
		LispOperator comp = new ComparatorOperator();
		ConsList<Object> cl = ConsListFactory.nil();
		cl = cl.prepend(new BigInteger("8"));
		cl = cl.prepend(4.2);
		comp.apply(new LispEval(interpreter), "_", cl);
	}

}
