package libraryFunctions;

import environment.Environment;
import environment.FunctionEnv;

import symbols.value.StaticVal;
import symbols.value.Value;
import symbols.value.Value_t;

import static utils.Constants.LIBRARY_FUNC_ARG;

public class LibraryFunctions {

    public static void print(Environment env) {
        int totalActuals = env.totalActuals();

        for (int i = 0; i < totalActuals; i++) {
            String data = env.getActualArgument(LIBRARY_FUNC_ARG + i).getType().equals(Value_t.UNDEFINED)
                    ? "UNDEFINED"
                    : env.getActualArgument(LIBRARY_FUNC_ARG + i).getData().toString();
            System.out.print(data);
        }
    }

    public static void println(Environment env) {
        print(env);
        System.out.println("");
    }

    public static void sqrt(Environment env) {

        Double data = getArgument(env);
        if (data == null) {
            return;
        }

        StaticVal retVal;
        data = Math.sqrt(data);

        //Return sprt
        if ((data == Math.floor(data)) && !Double.isInfinite(data)) {
            retVal = new StaticVal(Value_t.INTEGER, data);
        } else {
            retVal = new StaticVal(Value_t.REAL, data);
        }

        ((FunctionEnv) env).setReturnVal(retVal);
    }

    public static void cos(Environment env) {

        Double data = getArgument(env);
        if (data == null) {
            return;
        }

        data = Math.cos(data);

        StaticVal retVal = new StaticVal(Value_t.REAL, data);
        ((FunctionEnv) env).setReturnVal(retVal);

    }

    public static void sin(Environment env) {

        Double data = getArgument(env);
        if (data == null) {
            return;
        }

        data = Math.sin(data);

        StaticVal retVal = new StaticVal(Value_t.REAL, data);
        ((FunctionEnv) env).setReturnVal(retVal);
    }

    private static Double getArgument(Environment env) {
        double data;
        Value value = env.getActualArgument(LIBRARY_FUNC_ARG + 0);
        if (value.isReal()) {
            data = (double) value.getData();

        } else if (value.isInteger()) {
            data = (double) (int) value.getData();

        } else if (value.isString() && value.isConvertedToNumeric()) {
            data = Double.parseDouble((String) value.getData());
        } else if (value.isUndefined()) {
            StaticVal retVal = new StaticVal(Value_t.ERROR, "Argument is UNDEFINED.");
            ((FunctionEnv) env).setReturnVal(retVal);
            return null;
        } else {
            StaticVal retVal = new StaticVal(Value_t.ERROR, "Argument can not cast to Double.");
            ((FunctionEnv) env).setReturnVal(retVal);
            return null;
        }
        return data;
    }
}

@@ -426,19 +426,35 @@
 ing data
- = 
+;%0A%0A            if (
 env.getA
@@ -493,33 +493,49 @@
  i).
-getType().equals(Value_t.
+isUndefined()) %7B%0A                data = %22
 UNDE
@@ -539,17 +539,18 @@
 NDEFINED
-)
+%22;
 %0A       
@@ -558,51 +558,149 @@
     
-        ? %22UNDEFINED%22%0A                    :
+%7D else if (env.getActualArgument(LIBRARY_FUNC_ARG + i).isNull()) %7B%0A                data = %22NULL%22;%0A            %7D else %7B%0A                data =
  env
@@ -762,16 +762,31 @@
 ring();%0A
+            %7D%0A%0A
         

Fix bug] Manage the case when the Value.data is NULL.