package function.builtin.predicate;

import static testutil.TestUtilities.evaluateString;
import static testutil.TypeAssertions.assertNil;
import static testutil.TypeAssertions.assertT;

import org.junit.Test;

import function.ArgumentValidator.TooFewArgumentsException;
import function.ArgumentValidator.TooManyArgumentsException;
import testutil.SymbolAndFunctionCleaner;

public class EQTest extends SymbolAndFunctionCleaner {

    @Test
    public void eqWithEqualAtoms() {
        String input = "(eq 1 1)";

        assertT(evaluateString(input));
    }

    @Test
    public void eqWithEqualAtomsAndAlias() {
        String input = "(eq? 1 1)";

        assertT(evaluateString(input));
    }

    @Test
    public void eqWithUnequalAtoms() {
        String input = "(eq 1 2)";

        assertNil(evaluateString(input));
    }

    @Test
    public void eqWithTwoEqualNumbers() {
        String input = "(eq -4 -4)";

        assertT(evaluateString(input));
    }

    @Test
    public void eqWithTwoUnequalNumbers() {
        String input = "(eq +5 +7)";

        assertNil(evaluateString(input));
    }

    @Test
    public void eqWithTwoEqualStrings() {
        String input = "(eq \"potato\" \"potato\")";

        assertT(evaluateString(input));
    }

    @Test
    public void eqWithTwoUnequalStrings() {
        String input = "(eq \"tomato\" \"potato\")";

        assertNil(evaluateString(input));
    }

    @Test
    public void eqWithTwoDifferentCasedStrings() {
        String input = "(eq \"Potato\" \"potato\")";

        assertNil(evaluateString(input));
    }

    @Test
    public void eqWithAtomAndList() {
        String input = "(eq 1 '(2))";

        assertNil(evaluateString(input));
    }

    @Test
    public void eqWithSameList() {
        String initializeL1 = "(setq l1 '(1 2 3))";
        String initializeL2 = "(setq l2 l1)";
        String input = "(eq l1 l2)";

        evaluateString(initializeL1);
        evaluateString(initializeL2);

        assertT(evaluateString(input));
    }

    @Test
    public void eqWithEqualLists() {
        String input = "(eq '(1 2) '(1 2))";

        assertNil(evaluateString(input));
    }

    @Test
    public void eqWithUnequalLists() {
        String input = "(eq '(1 2) '(3 4))";

        assertNil(evaluateString(input));
    }

    @Test(expected = TooManyArgumentsException.class)
    public void eqWithTooManyArguments() {
        evaluateString("(eq 'one 'two 'three)");
    }

    @Test(expected = TooFewArgumentsException.class)
    public void eqWithTooFewArguments() {
        evaluateString("(eq 'one)");
    }

}
