/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
 */
package com.scytl.ov.mixing.core.shuffle;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.security.SecureRandom;

import org.junit.BeforeClass;
import org.junit.Test;

import com.scytl.ov.mixing.shuffle.Permutation;

public class PermutationGeneratorTest {

    private static PermutationGenerator permutationGenerator;

    private static int NUM_LIST_ELEMENTS;

    @BeforeClass
    public static void setUp() {

        SecureRandom secureRandom = new SecureRandom();

        permutationGenerator = new PermutationGenerator(secureRandom);

        NUM_LIST_ELEMENTS = 1000;
    }

    @Test
    public void whenGeneratePermutationThenExpectedSize() {

        Permutation permutation = permutationGenerator.generate(NUM_LIST_ELEMENTS);

        final String errorMsg = "Permutation is not the expected length";
        assertEquals(errorMsg, NUM_LIST_ELEMENTS, permutation.getLength());
    }

    /**
     * It is perfectly valid for a permutation to be exactly the same as the identity permutation (which is simply a
     * sequential list of integers, i.e. 1, 2, 3,... n). However, this is very unlikely to happen. If that were to
     * happen then it is quite probable that there is a software problem. Therefore, it is reasonable to have a test
     * that verifies a certain minimum level of difference between the identity permutation and a generated permutation.
     */
    @Test
    public void whenGeneratePermutationThenExpectedLevelOfRandomnessSatisfied() {

        Permutation permutation = permutationGenerator.generate(NUM_LIST_ELEMENTS);

        final int numElementsInOriginalPosition =
            getNumElementsInOriginalPosition(createSequentialIntArray(), permutation);

        boolean reasonableExpectationSatisfied = numElementsInOriginalPosition <= NUM_LIST_ELEMENTS / 4;

        final String errorMsg =
            "Expected that the number of elements with different positions in the permutated array would be greater.";
        assertTrue(errorMsg, reasonableExpectationSatisfied);
    }

    private int[] createSequentialIntArray() {

        final int[] list = new int[NUM_LIST_ELEMENTS];
        for (int i = 0; i < NUM_LIST_ELEMENTS; i++) {
            list[i] = i;
        }
        return list;
    }

    private int getNumElementsInOriginalPosition(final int[] intArray, final Permutation list2) {

        int matchesFound = 0;

        final int list1Size = intArray.length;

        for (int i = 0; i < list1Size; i++) {
            if (intArray[i] == list2.getCorrespondingIndexInSourceList(i)) {
                matchesFound++;
            }
        }

        return matchesFound;
    }
}
