/*
 * 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.linear;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;

import org.apache.commons.math4.legacy.analysis.UnivariateFunction;
import org.apache.commons.math4.legacy.analysis.function.Sin;
import org.apache.commons.math4.legacy.exception.MathUnsupportedOperationException;
import org.apache.commons.math4.legacy.linear.RealVector.Entry;
import org.apache.commons.math4.legacy.core.jdkmath.AccurateMath;
import org.junit.Assert;
import org.junit.Test;

/**
 * This is an abstract test of the {@link
 * RealVector#unmodifiableRealVector(RealVector) unmodifiable vector}
 * implementation. These unmodifiable vectors decorate a (modifiable)
 * {@link RealVector}; therefore, a new implementation of this abstract
 * test should be considered for each implementation of
 * {@link RealVector}.
 *
 *
 */
public abstract class UnmodifiableRealVectorAbstractTest {
    /** The dimension of the randomly generated vectors. */
    protected static final int DIM = 100;
    /** Absolute tolerance. */
    protected static final double EPS = 10 * Math.ulp(1d);
    /**
     * The list of methods which are excluded from the general test
     * {@link #testAllButExcluded()}.
     */
    protected static final Set<String> EXCLUDE = new HashSet<>();
    /** The random number generator (always initialized with the same seed. */
    protected static final Random RANDOM;

    static {
        EXCLUDE.add("getEntry");
        EXCLUDE.add("setEntry");
        EXCLUDE.add("addToEntry");
        EXCLUDE.add("getSubVector");
        EXCLUDE.add("setSubVector");
        EXCLUDE.add("iterator");
        EXCLUDE.add("sparseIterator");
        EXCLUDE.add("walkInDefaultOrder");
        EXCLUDE.add("walkInOptimizedOrder");
        EXCLUDE.add("ebeDivide");
        EXCLUDE.add("ebeMultiply");

        // Excluded because they are inherited from "Object".
        for (Method m : Object.class.getMethods()) {
            EXCLUDE.add(m.getName());
        }
        RANDOM = new Random(20110813);
    }

    /**
     * Returns {@code true} if the specified {@code double} are equal (within a
     * given tolerance).
     *
     * @param x First {@code double}.
     * @param y Second {@code double}.
     * @return {@code true} if {@code x} and {@code y} are equal.
     */
    public static boolean equals(final double x, final double y) {
        if (x == y) {
            return true;
        } else if (AccurateMath.abs(x) <= EPS) {
            return AccurateMath.abs(y) <= EPS;
        } else if (AccurateMath.abs(y) <= EPS) {
            return AccurateMath.abs(x) <= EPS;
        } else {
            return AccurateMath.abs(x - y) <= EPS * AccurateMath.min(AccurateMath.abs(x), AccurateMath.abs(y));
        }
    }

    /**
     * Returns {@code true} if the specified {@code double} arrays are equal
     * (within a given tolerance).
     *
     * @param x First array.
     * @param y Second array.
     * @return {@code true} if {@code x} and {@code y} are equal.
     */
    public static boolean equals(final double[] x, final double[] y) {
        if (x.length != y.length) {
            return false;
        }
        final int n = x.length;
        for (int i = 0; i < n; i++) {
            if (!equals(x[i], y[i])) {
                return false;
            }
        }
        return true;
    }

    /**
     * Returns {@code true} if the specified {@code RealVector} are equal
     * (within a given tolerance).
     *
     * @param x First vector.
     * @param y Second vector.
     * @return {@code true} if {@code x} and {@code y} are equal.
     */
    public static boolean equals(final RealVector x, final RealVector y) {
        if (x.getDimension() != y.getDimension()) {
            return false;
        }
        final int n = x.getDimension();
        for (int i = 0; i < n; i++) {
            if (!equals(x.getEntry(i), y.getEntry(i))) {
                return false;
            }
        }
        return true;
    }

    /**
     * Returns {@code true} if the specified {@code RealVector} is equal to the
     * specified {@code double} array (within a given tolerance).
     *
     * @param x Vector.
     * @param y Array.
     * @return {@code true} if {@code x} and {@code y} are equal.
     */
    public static boolean equals(final RealVector x, final double[] y) {
        if (x.getDimension() != y.length) {
            return false;
        }
        final int n = x.getDimension();
        for (int i = 0; i < n; i++) {
            if (!equals(x.getEntry(i), y[i])) {
                return false;
            }
        }
        return true;
    }

    /**
     * Returns {@code true} if the specified {@code RealMatrix} are equal
     * (within a given tolerance).
     *
     * @param x First matrix.
     * @param y Second matrix.
     * @return {@code true} if {@code x} and {@code y} are equal.
     */
    public static boolean equals(final RealMatrix x, final RealMatrix y) {
        if (x.getRowDimension() != y.getRowDimension()) {
            return false;
        }
        if (x.getColumnDimension() != y.getColumnDimension()) {
            return false;
        }
        final int rows = x.getRowDimension();
        final int cols = x.getColumnDimension();
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (!equals(x.getEntry(i, j), y.getEntry(i, j))) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * Returns {@code true} if the specified {@code Object} are equal.
     *
     * @param x First object.
     * @param y Second object.
     * @return {@code true} if {@code x} and {@code y} are equal.
     * @throws IllegalArgumentException if {@code x} and {@code y} could
     * not be compared.
     */
    public static boolean equals(final Object x, final Object y) {
        if (x instanceof Boolean) {
            if (y instanceof Boolean) {
                return ((Boolean) x).booleanValue() == ((Boolean) y)
                        .booleanValue();
            } else {
                return false;
            }
        }
        if (x instanceof Integer) {
            if (y instanceof Integer) {
                return ((Integer) x).intValue() == ((Integer) y).intValue();
            } else {
                return false;
            }
        } else if (x instanceof Double) {
            if (y instanceof Double) {
                return equals(((Double) x).doubleValue(),
                        ((Double) y).doubleValue());
            } else {
                return false;
            }
        } else if (x instanceof double[]) {
            if (y instanceof double[]) {
                return equals((double[]) x, (double[]) y);
            } else if (y instanceof RealVector) {
                return equals((RealVector) y, (double[]) x);
            } else {
                return false;
            }
        } else if (x instanceof RealVector) {
            if (y instanceof double[]) {
                return equals((RealVector) x, (double[]) y);
            } else if (y instanceof RealVector) {
                return equals((RealVector) x, (RealVector) y);
            } else {
                return false;
            }
        } else if (x instanceof RealMatrix) {
            if (y instanceof RealMatrix) {
                return equals((RealMatrix) x, (RealMatrix) y);
            } else {
                return false;
            }
        } else {
            throw new IllegalArgumentException("could not compare " + x + ", "
                    + y);
        }
    }

    /**
     * Creates a new random vector of a specified type. This vector is then to
     * be wrapped in an unmodifiable vector.
     *
     * @return a new random vector.
     */
    public abstract RealVector createVector();

    /**
     * Creates a new random object of the specified type.
     *
     * @param c Class of the object to be created.
     * @return a new random object.
     * @throws IllegalArgumentException if the specified class is not
     * recognized by this method.
     */
    public Object createParameter(final Class<?> c) {
        if (c == Integer.TYPE) {
            return Integer.valueOf(RANDOM.nextInt());
        } else if (c == Double.TYPE) {
            return Double.valueOf(RANDOM.nextDouble());
        } else if (c == double[].class) {
            final double[] v = new double[DIM];
            for (int i = 0; i < DIM; i++) {
                v[i] = RANDOM.nextDouble();
            }
            return v;
        } else if (c.isAssignableFrom(RealVector.class)) {
            return createVector();
        } else if (c.isAssignableFrom(UnivariateFunction.class)) {
            return new Sin();
        } else {
            throw new IllegalArgumentException("could not create " + c);
        }
    }

    /**
     * This is the general test of most methods in the
     * {@link RealVector#unmodifiableRealVector(RealVector) unmodifiable vector}.
     * It works as follows.
     * First, an unmodifiable view of a copy of the specified random vector
     * {@code u} is created: this defines {@code v}. Then the <em>same</em>
     * method {@code m} is invoked on {@code u} and {@code v}, with randomly
     * generated parameters {@code args}.
     * If it turns out that {@code u} has changed after the call of method
     * {@code m}, then this test checks that the call of this method on
     * {@code v} resulted in a {@link MathUnsupportedOperationException}. If
     * {@code u} was not modified, then this test checks that the results
     * returned by the call of method {@code m} on {@code u} and {@code v}
     * returned the same result.
     *
     * @param m Method to be tested.
     * @param u Random vector from which the unmodifiable view is to be
     *constructed.
     * @param args Arguments to be passed to method {@code m}.
     */
    private void callMethod(final Method m,
                            final RealVector u,
                            final Object... args)
        throws IllegalAccessException,
               IllegalArgumentException,
               InvocationTargetException {
        final RealVector uu = u.copy();
        final RealVector v = RealVector.unmodifiableRealVector(u.copy());
        Object exp = m.invoke(u, args);
        if (equals(uu, u)) {
            Object act = m.invoke(v, args);
            Assert.assertTrue(m.toGenericString() + ", unmodifiable vector has changed",
                              equals(uu, v));
            Assert.assertTrue(m.toGenericString() + ", wrong result",
                              equals(exp, act));

        } else {
            boolean flag = false;
            try {
                m.invoke(v, args);
            } catch (InvocationTargetException e) {
                if (e.getCause() instanceof MathUnsupportedOperationException) {
                    flag = true;
                }
            }
            Assert.assertTrue(m.toGenericString()+", exception should have been thrown", flag);
        }
    }

    /**
     * This test calls {@link #callMethod(Method, RealVector, Object...)} on
     * every method defined in interface {@link RealVector}. It generates the
     * appropriate random arguments. Some methods are manually excluded (see
     * {@link #EXCLUDE}), they must be handled by separate tests.
     */
    @Test
    public void testAllButExcluded()
        throws IllegalAccessException,
               IllegalArgumentException,
               InvocationTargetException {
        Method[] method = RealVector.class.getMethods();
        for (int i = 0; i < method.length; i++) {
            Method m = method[i];
            if (!EXCLUDE.contains(m.getName())) {
                RealVector u = (RealVector) createParameter(RealVector.class);
                Class<?>[] paramType = m.getParameterTypes();
                Object[] param = new Object[paramType.length];
                for (int j = 0; j < paramType.length; j++) {
                    param[j] = createParameter(paramType[j]);
                }
                callMethod(m, u, param);
            }
        }
    }

    @Test
    public void testGetEntry() {
        RealVector u = createVector();
        RealVector v = RealVector.unmodifiableRealVector(u);
        for (int i = 0; i < DIM; i++) {
            Assert.assertTrue(equals(u.getEntry(i), v.getEntry(i)));
        }
    }

    @Test(expected = MathUnsupportedOperationException.class)
    public void testSetEntry() {
        RealVector u = createVector();
        RealVector v = RealVector.unmodifiableRealVector(u);
        for (int i = 0; i < DIM; i++) {
            v.setEntry(i, 0d);
        }
    }

    @Test(expected = MathUnsupportedOperationException.class)
    public void testAddToEntry() {
        RealVector u = createVector();
        RealVector v = RealVector.unmodifiableRealVector(u);
        for (int i = 0; i < DIM; i++) {
            v.addToEntry(i, 0d);
        }
    }

    @Test
    public void testGetSubVector() {
        RealVector u = createVector();
        RealVector v = RealVector.unmodifiableRealVector(u);
        for (int i = 0; i < DIM; i++) {
            for (int n = 1; n < DIM - i; n++) {
                RealVector exp = u.getSubVector(i, n);
                RealVector act = v.getSubVector(i, n);
                Assert.assertTrue(equals(exp, act));
            }
        }
    }

    @Test(expected = MathUnsupportedOperationException.class)
    public void testSetSubVector() {
        RealVector u = createVector();
        RealVector v = RealVector.unmodifiableRealVector(u);
        v.setSubVector(0, new ArrayRealVector());
    }

    @Test
    public void testIterator() {
        RealVector u = createVector();
        Iterator<Entry> i = u.iterator();
        RealVector v = RealVector.unmodifiableRealVector(u.copy());
        Iterator<Entry> j = v.iterator();
        boolean flag;
        while (i.hasNext()) {
            Assert.assertTrue(j.hasNext());
            Entry exp = i.next();
            Entry act = j.next();
            Assert.assertTrue(equals(exp.getIndex(), act.getIndex()));
            Assert.assertTrue(equals(exp.getValue(), act.getValue()));
            exp.setIndex(RANDOM.nextInt(DIM));
            act.setIndex(RANDOM.nextInt(DIM));
            flag = false;
            try {
                act.setValue(RANDOM.nextDouble());
            } catch (MathUnsupportedOperationException e) {
                flag = true;
            }
            Assert.assertTrue("exception should have been thrown", flag);
        }
        Assert.assertFalse(j.hasNext());
    }

    @Test
    public void testSparseIterator() {
        RealVector u = createVector();
        Iterator<Entry> i = u.sparseIterator();
        RealVector v = RealVector.unmodifiableRealVector(u.copy());
        Iterator<Entry> j = v.sparseIterator();
        boolean flag;
        while (i.hasNext()) {
            Assert.assertTrue(j.hasNext());
            Entry exp = i.next();
            Entry act = j.next();
            Assert.assertTrue(equals(exp.getIndex(), act.getIndex()));
            Assert.assertTrue(equals(exp.getValue(), act.getValue()));
            exp.setIndex(RANDOM.nextInt(DIM));
            act.setIndex(RANDOM.nextInt(DIM));
            flag = false;
            try {
                act.setValue(RANDOM.nextDouble());
            } catch (MathUnsupportedOperationException e) {
                flag = true;
            }
            Assert.assertTrue("exception should have been thrown", flag);
        }
        Assert.assertFalse(j.hasNext());
    }
}
