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

import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicLong;

import org.apache.commons.numbers.core.Precision;
import org.apache.commons.math4.neuralnet.internal.NeuralNetException;

/**
 * Describes a neuron element of a neural network.
 *
 * This class aims to be thread-safe.
 *
 * @since 3.3
 */
public class Neuron {
    /** Identifier. */
    private final long identifier;
    /** Length of the feature set. */
    private final int size;
    /** Neuron data. */
    private final AtomicReference<double[]> features;
    /** Number of attempts to update a neuron. */
    private final AtomicLong numberOfAttemptedUpdates = new AtomicLong(0);
    /** Number of successful updates  of a neuron. */
    private final AtomicLong numberOfSuccessfulUpdates = new AtomicLong(0);

    /**
     * Creates a neuron.
     * The size of the feature set is fixed to the length of the given
     * argument.
     * <br>
     * Constructor is package-private: Neurons must be
     * {@link Network#createNeuron(double[]) created} by the network
     * instance to which they will belong.
     *
     * @param identifier Identifier (assigned by the {@link Network}).
     * @param features Initial values of the feature set.
     */
    Neuron(long identifier,
           double[] features) {
        this.identifier = identifier;
        this.size = features.length;
        this.features = new AtomicReference<>(features.clone());
    }

    /**
     * Performs a deep copy of this instance.
     * Upon return, the copied and original instances will be independent:
     * Updating one will not affect the other.
     *
     * @return a new instance with the same state as this instance.
     * @since 3.6
     */
    public synchronized Neuron copy() {
        final Neuron copy = new Neuron(getIdentifier(),
                                       getFeatures());
        copy.numberOfAttemptedUpdates.set(numberOfAttemptedUpdates.get());
        copy.numberOfSuccessfulUpdates.set(numberOfSuccessfulUpdates.get());

        return copy;
    }

    /**
     * Gets the neuron's identifier.
     *
     * @return the identifier.
     */
    public long getIdentifier() {
        return identifier;
    }

    /**
     * Gets the length of the feature set.
     *
     * @return the number of features.
     */
    public int getSize() {
        return size;
    }

    /**
     * Gets the neuron's features.
     *
     * @return a copy of the neuron's features.
     */
    public double[] getFeatures() {
        return features.get().clone();
    }

    /**
     * Tries to atomically update the neuron's features.
     * Update will be performed only if the expected values match the
     * current values.<br>
     * In effect, when concurrent threads call this method, the state
     * could be modified by one, so that it does not correspond to the
     * the state assumed by another.
     * Typically, a caller {@link #getFeatures() retrieves the current state},
     * and uses it to compute the new state.
     * During this computation, another thread might have done the same
     * thing, and updated the state: If the current thread were to proceed
     * with its own update, it would overwrite the new state (which might
     * already have been used by yet other threads).
     * To prevent this, the method does not perform the update when a
     * concurrent modification has been detected, and returns {@code false}.
     * When this happens, the caller should fetch the new current state,
     * redo its computation, and call this method again.
     *
     * @param expect Current values of the features, as assumed by the caller.
     * Update will never succeed if the contents of this array does not match
     * the values returned by {@link #getFeatures()}.
     * @param update Features's new values.
     * @return {@code true} if the update was successful, {@code false}
     * otherwise.
     * @throws IllegalArgumentException if the length of {@code update} is
     * not the same as specified in the {@link #Neuron(long,double[])
     * constructor}.
     */
    public boolean compareAndSetFeatures(double[] expect,
                                         double[] update) {
        if (update.length != size) {
            throw new NeuralNetException(NeuralNetException.SIZE_MISMATCH,
                                         update.length, size);
        }

        // Get the internal reference. Note that this must not be a copy;
        // otherwise the "compareAndSet" below will always fail.
        final double[] current = features.get();
        if (!containSameValues(current, expect)) {
            // Some other thread already modified the state.
            return false;
        }

        // Increment attempt counter.
        numberOfAttemptedUpdates.incrementAndGet();

        if (features.compareAndSet(current, update.clone())) {
            // The current thread could atomically update the state (attempt succeeded).
            numberOfSuccessfulUpdates.incrementAndGet();
            return true;
        } else {
            // Some other thread came first (attempt failed).
            return false;
        }
    }

    /**
     * Retrieves the number of calls to the
     * {@link #compareAndSetFeatures(double[],double[]) compareAndSetFeatures}
     * method.
     * Note that if the caller wants to use this method in combination with
     * {@link #getNumberOfSuccessfulUpdates()}, additional synchronization
     * may be required to ensure consistency.
     *
     * @return the number of update attempts.
     * @since 3.6
     */
    public long getNumberOfAttemptedUpdates() {
        return numberOfAttemptedUpdates.get();
    }

    /**
     * Retrieves the number of successful calls to the
     * {@link #compareAndSetFeatures(double[],double[]) compareAndSetFeatures}
     * method.
     * Note that if the caller wants to use this method in combination with
     * {@link #getNumberOfAttemptedUpdates()}, additional synchronization
     * may be required to ensure consistency.
     *
     * @return the number of successful updates.
     * @since 3.6
     */
    public long getNumberOfSuccessfulUpdates() {
        return numberOfSuccessfulUpdates.get();
    }

    /**
     * Checks whether the contents of both arrays is the same.
     *
     * @param current Current values.
     * @param expect Expected values.
     * @throws IllegalArgumentException if the length of {@code expect}
     * is not the same as specified in the {@link #Neuron(long,double[])
     * constructor}.
     * @return {@code true} if the arrays contain the same values.
     */
    private boolean containSameValues(double[] current,
                                      double[] expect) {
        if (expect.length != size) {
            throw new NeuralNetException(NeuralNetException.SIZE_MISMATCH,
                                         expect.length, size);
        }

        for (int i = 0; i < size; i++) {
            if (!Precision.equals(current[i], expect[i])) {
                return false;
            }
        }
        return true;
    }
}
