package function.builtin;

import java.text.MessageFormat;

import error.LispException;
import function.*;
import sexpression.*;
import table.FunctionTable;

@FunctionNames({ "SYMBOL-FUNCTION" })
public class SYMBOL_FUNCTION extends LispFunction {

    private ArgumentValidator argumentValidator;

    public SYMBOL_FUNCTION() {
        this.argumentValidator = new ArgumentValidator("SYMBOL-FUNCTION");
        this.argumentValidator.setExactNumberOfArguments(1);
        this.argumentValidator.setEveryArgumentExpectedType(Symbol.class);
    }

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

        SExpression symbol = argumentList.getFirst();
        LispFunction function = FunctionTable.lookupFunction(symbol.toString());

        if (function != null) {
            if (function instanceof UserDefinedFunction)
                return ((UserDefinedFunction) function).getLambdaExpression();

            return new Symbol(MessageFormat.format("#<SYSTEM-FUNCTION {0}>", symbol.toString()));
        }

        throw new UndefinedSymbolFunctionException(symbol);
    }

    public static class UndefinedSymbolFunctionException extends LispException {

        private static final long serialVersionUID = 1L;
        private SExpression function;

        public UndefinedSymbolFunctionException(SExpression function) {
            this.function = function;
        }

        @Override
        public String getMessage() {
            return MessageFormat.format("SYMBOL-FUNCTION: undefined function: {0}", function);
        }
    }

}
