/*
 * 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.math3.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.math3.analysis.UnivariateFunction;
import org.apache.commons.math3.analysis.function.Sin;
import org.apache.commons.math3.exception.MathUnsupportedOperationException;
import org.apache.commons.math3.linear.RealVector.Entry;
import org.apache.commons.math3.util.FastMath;
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<String>();
    /** 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 (FastMath.abs(x) <= EPS) {
            return FastMath.abs(y) <= EPS;
        } else if (FastMath.abs(y) <= EPS) {
            return FastMath.abs(x) <= EPS;
        } else {
            return FastMath.abs(x - y) <= EPS * FastMath.min(FastMath.abs(x), FastMath.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());
    }
}
