/*
 * 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.math4.legacy.exception.MathArithmeticException;
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;

/**
 * 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.assertEquals(MathArithmeticException.class, actual.getClass());
            } 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
    }
}
