/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.math4.legacy.core.jdkmath;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.numbers.core.Precision;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

// Unit test should be moved to module "commons-math-core".
// [Currently, it can't be because it depends on "legacy" classes.]
import org.apache.commons.math4.core.jdkmath.AccurateMath;

/**
 * Test to compare AccurateMath results against StrictMath results for boundary values.
 * <p>
 * Running all tests independently: <br>
 * {@code mvn test -Dtest=AccurateMathStrictComparisonTest}<br>
 * or just run tests against a single method (e.g. scalb):<br>
 * {@code mvn test -Dtest=AccurateMathStrictComparisonTest -DargLine="-DtestMethod=scalb"}
 */
@SuppressWarnings("boxing")
@RunWith(Parameterized.class)
public class AccurateMathStrictComparisonTest {

    // Values which often need special handling
    private static final Double[] DOUBLE_SPECIAL_VALUES = {
        -0.0, +0.0,                                         // 1,2
        Double.NaN,                                         // 3
        Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, // 4,5
        -Double.MAX_VALUE, Double.MAX_VALUE,                // 6,7
        // decreasing order of absolute value to help catch first failure
        -Precision.EPSILON, Precision.EPSILON,              // 8,9
        -Precision.SAFE_MIN, Precision.SAFE_MIN,            // 10,11
        -Double.MIN_VALUE, Double.MIN_VALUE,                // 12,13
    };

    private static final Float[] FLOAT_SPECIAL_VALUES = {
        -0.0f, +0.0f,                                       // 1,2
        Float.NaN,                                          // 3
        Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY,   // 4,5
        Float.MIN_VALUE, Float.MAX_VALUE,                   // 6,7
        -Float.MIN_VALUE, -Float.MAX_VALUE,                 // 8,9
    };

    private static final Object[] LONG_SPECIAL_VALUES = {
        -1, 0, 1,                                           // 1,2,3
        Long.MIN_VALUE, Long.MAX_VALUE,                     // 4,5
    };

    private static final Object[] INT_SPECIAL_VALUES = {
        -1, 0, 1,                                           // 1,2,3
        Integer.MIN_VALUE, Integer.MAX_VALUE,               // 4,5
    };

    private final Method mathMethod;
    private final Method fastMethod;
    private final Type[] types;
    private final Object[][] valueArrays;

    public AccurateMathStrictComparisonTest(Method m, Method f, Type[] types, Object[][] data) throws Exception {
        this.mathMethod = m;
        this.fastMethod = f;
        this.types = types;
        this.valueArrays = data;
    }

    @Test
    public void test1() throws Exception {
        setupMethodCall(mathMethod, fastMethod, types, valueArrays);
    }

    private static boolean isNumber(Double d) {
        return !(d.isInfinite() || d.isNaN());
    }

    private static boolean isNumber(Float f) {
        return !(f.isInfinite() || f.isNaN());
    }

    private static void reportFailedResults(Method mathMethod, Object[] params, Object expected, Object actual, int[] entries) {
        final String methodName = mathMethod.getName();
        String format = null;
        long actL = 0;
        long expL = 0;
        if (expected instanceof Double) {
            Double exp = (Double) expected;
            Double act = (Double) actual;
            if (isNumber(exp) && isNumber(act) && exp != 0) { // show difference as hex
                actL = Double.doubleToLongBits(act);
                expL = Double.doubleToLongBits(exp);
                if (Math.abs(actL - expL) == 1) {
                    // Not 100% sure off-by-one errors are allowed everywhere, so only allow for these methods
                    if (methodName.equals("toRadians") || methodName.equals("atan2")) {
                        return;
                    }
                }
                format = "%016x";
            }
        } else if (expected instanceof Float) {
            Float exp = (Float) expected;
            Float act = (Float) actual;
            if (isNumber(exp) && isNumber(act) && exp != 0) { // show difference as hex
                actL = Float.floatToIntBits(act);
                expL = Float.floatToIntBits(exp);
                format = "%08x";
            }
        }
        StringBuilder sb = new StringBuilder();
        sb.append(mathMethod.getReturnType().getSimpleName());
        sb.append(" ");
        sb.append(methodName);
        sb.append("(");
        String sep = "";
        for (Object o : params) {
            sb.append(sep);
            sb.append(o);
            sep = ", ";
        }
        sb.append(") expected ");
        if (format != null) {
            sb.append(String.format(format, expL));
        } else {
            sb.append(expected);
        }
        sb.append(" actual ");
        if (format != null) {
            sb.append(String.format(format, actL));
        } else {
            sb.append(actual);
        }
        sb.append(" entries ");
        sb.append(Arrays.toString(entries));
        String message = sb.toString();
        final boolean fatal = true;
        if (fatal) {
            Assert.fail(message);
        } else {
            // CHECKSTYLE: stop Regexp
            System.out.println(message);
            // CHECKSTYLE: resume Regexp
        }
    }

    private static void callMethods(Method mathMethod, Method fastMethod,
            Object[] params, int[] entries) throws IllegalAccessException {
        try {
            Object expected;
            try {
                expected = mathMethod.invoke(mathMethod, params);
            } catch (InvocationTargetException ite) {
                expected = ite.getCause();
            }
            Object actual;
            try {
                actual = fastMethod.invoke(mathMethod, params);
            } catch (InvocationTargetException ite) {
                actual = ite.getCause();
            }
            if (expected instanceof ArithmeticException) {
                Assert.assertTrue(actual instanceof ArithmeticException);
            } else if (!expected.equals(actual)) {
                reportFailedResults(mathMethod, params, expected, actual, entries);
            }
        } catch (IllegalArgumentException e) {
            Assert.fail(mathMethod + " " + e);
        }
    }

    private static void setupMethodCall(Method mathMethod, Method fastMethod,
            Type[] types, Object[][] valueArrays) throws Exception {
        Object[] params = new Object[types.length];
        int entry1 = 0;
        int[] entries = new int[types.length];
        for (Object d : valueArrays[0]) {
            entry1++;
            params[0] = d;
            entries[0] = entry1;
            if (params.length > 1) {
                int entry2 = 0;
                for (Object d1 : valueArrays[1]) {
                    entry2++;
                    params[1] = d1;
                    entries[1] = entry2;
                    callMethods(mathMethod, fastMethod, params, entries);
                }
            } else {
                callMethods(mathMethod, fastMethod, params, entries);
            }
        }
    }

    @Parameters
    public static List<Object[]> data() throws Exception {
        // CHECKSTYLE: stop Regexp
        String singleMethod = System.getProperty("testMethod");
        List<Object[]> list = new ArrayList<>();
        for (Method mathMethod : StrictMath.class.getDeclaredMethods()) {
            method:
            if (Modifier.isPublic(mathMethod.getModifiers())) { // Only test public methods
                Type[] types = mathMethod.getGenericParameterTypes();
                if (types.length >= 1) { // Only check methods with at least one parameter
                    try {
                        // Get the corresponding AccurateMath method
                        Method fastMethod = AccurateMath.class.getDeclaredMethod(mathMethod.getName(), (Class[]) types);
                        if (Modifier.isPublic(fastMethod.getModifiers())) { // It must be public too
                            if (singleMethod != null && !fastMethod.getName().equals(singleMethod)) {
                                break method;
                            }
                            Object[][] values = new Object[types.length][];
                            int index = 0;
                            for (Type t : types) {
                                if (t.equals(double.class)) {
                                    values[index] = DOUBLE_SPECIAL_VALUES;
                                } else if (t.equals(float.class)) {
                                    values[index] = FLOAT_SPECIAL_VALUES;
                                } else if (t.equals(long.class)) {
                                    values[index] = LONG_SPECIAL_VALUES;
                                } else if (t.equals(int.class)) {
                                    values[index] = INT_SPECIAL_VALUES;
                                } else {
                                    System.out.println("Cannot handle class " + t + " for " + mathMethod);
                                    break method;
                                }
                                index++;
                            }
//                          System.out.println(fastMethod);
                            /*
                             * The current implementation runs each method as a separate test.
                             * Could be amended to run each value as a separate test
                             */
                            list.add(new Object[]{mathMethod, fastMethod, types, values});
//                            setupMethodCall(mathMethod, fastMethod, params, data);
                        } else {
                            System.out
                                .println("Cannot find public AccurateMath method corresponding to: " + mathMethod);
                        }
                    } catch (NoSuchMethodException e) {
                        System.out.println("Cannot find AccurateMath method corresponding to: " + mathMethod);
                    }
                }
            }
        }
        return list;
        // CHECKSTYLE: resume Regexp
    }
}
