package function.builtin.predicate;

import function.*;
import sexpression.*;

@FunctionNames({ "=" })
public class EQUALSP extends LispFunction {

    private ArgumentValidator argumentValidator;

    public EQUALSP() {
        this.argumentValidator = new ArgumentValidator("=");
        this.argumentValidator.setMinimumNumberOfArguments(1);
        this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class);
    }

    public SExpression call(Cons argumentList) {
        argumentValidator.validate(argumentList);

        return callTailRecursive(argumentList);
    }

    private SExpression callTailRecursive(Cons argumentList) {
        Cons remainingArguments = (Cons) argumentList.getRest();

        if (remainingArguments.isNull())
            return Symbol.T;

        SExpression firstArgument = argumentList.getFirst();
        LispNumber number1 = (LispNumber) firstArgument;
        SExpression secondArgument = remainingArguments.getFirst();
        LispNumber number2 = (LispNumber) secondArgument;

        if (!isEqual(number1, number2))
            return Nil.getInstance();

        return callTailRecursive(remainingArguments);
    }

    private boolean isEqual(LispNumber number1, LispNumber number2) {
        return number1.getValue().equals(number2.getValue());
    }

}
