package h02;

import org.tudalgo.algoutils.student.annotation.StudentImplementationRequired;

/**
 * This class serves as a container for the methods that are to be implemented by the students for exercise H2.1.1.
 */
public class OneDimensionalArrayStuff {

    /**
     * Prevent instantiation of this utility class.
     */
    private OneDimensionalArrayStuff() {
        throw new IllegalStateException("This class is not meant to be instantiated.");
    }

    /**
     * Returns a new array that is a copy of the input array with the given value appended at the end.
     *
     * @param array the input array
     * @param value the value to append
     * @return a new array that is a copy of the input array with the given value appended at the end
     */
    @SuppressWarnings("ManualArrayCopy")
    @StudentImplementationRequired("H2.1.1")
    public static int[] push(final int[] array, final int value) {
        var newarr = new int[array.length+1];
        for (int i = 0; i < array.length; i++) {
            newarr[i] = array[i];
        }
        newarr[array.length] = value;
        return newarr;
    }

    /**
     * Calculates the next Fibonacci number based on the given array and returns a new array with the next Fibonacci
     * number appended at the end.
     *
     * @param array the input array containing the last two Fibonacci numbers up to the current point
     * @return a new array with the next Fibonacci number appended at the end
     */
    @StudentImplementationRequired("H2.1.1")
    public static int[] calculateNextFibonacci(final int[] array) {
        var a = array[array.length-2];
        var b = array[array.length-1];
        return push(array, a+b);
    }

    /**
     * Returns the n-th Fibonacci number.
     *
     * @param n the index of the Fibonacci number to return
     * @return the n-th Fibonacci number
     */
    @StudentImplementationRequired("H2.1.1")
    public static int fibonacci(int n) {
        var arr = new int[] {0, 1};
        if (n < 2) {
            return arr[n];
        }
        n -= 2;
        while (n --> 0) {
            arr = calculateNextFibonacci(arr);
        }
        return arr[arr.length-1];
    }
}
