package de.duehl.math.stochastic;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

import java.util.ArrayList;
import java.util.List;

public class RandomSampleWithPutBackTest {

    @Test
    public void emptySetFails() {
        assertThrows(IllegalArgumentException.class, () -> {
            new RandomSampleWithPutBack(-1, 15);
        });
    }

    @Test
    public void emptySetFails2() {
        assertThrows(IllegalArgumentException.class, () -> {
            new RandomSampleWithPutBack(1, 0, 15);
        });
    }

    @Test
    public void emptySetFails3() {
        assertThrows(IllegalArgumentException.class, () -> {
            new RandomSampleWithPutBack(18, 17, 15);
        });
    }

    @Test
    public void setWithOneMemberIsOkIfSampleWantsTwoMembers() {
        new RandomSampleWithPutBack(1, 1, 2);
    }

    @Test
    public void setWithOneMemberIsOkIfSampleWantsOneMember() {
        new RandomSampleWithPutBack(1, 1, 1);
    }

    @Test
    public void setWithOneMemberAndSampleWithOneMember() {
        RandomSample randomSample = new RandomSampleWithPutBack(1, 1, 1);
        randomSample.drawSample();
        List<Integer> actualSample = randomSample.getSample();
        assertEquals(1, actualSample.size());
        assertEquals(Integer.valueOf(1), actualSample.get(0));
    }

    @Test
    public void multiTest1() {
        int from = 1;
        int to = 100_000;
        int sampleSize = 1_000;

        List<Integer> sample = drawSample(from, to, sampleSize);
        checkSample(from, to, sampleSize, sample);
    }

    @Test
    public void multiTest2() {
        int from = 153_123;
        int to = 5_322_124;
        int sampleSize = 1_000;

        List<Integer> sample = drawSample(from, to, sampleSize);
        checkSample(from, to, sampleSize, sample);
    }

    private void checkSample(int from, int to, int sampleSize, List<Integer> sample) {
        assertEquals(sampleSize, sample.size());
        for (int sampleNumber : sample) {
            assertTrue(from <= sampleNumber);
            assertTrue(sampleNumber <= to);
        }
    }

    private List<Integer> drawSample(int from, int to, int sampleSize) {
        RandomSample randomSample = new RandomSampleWithPutBack(from, to, sampleSize);
        randomSample.drawSample();
        List<Integer> actualSample = randomSample.getSample();
        return actualSample;
    }

    @Test
    public void notWanted() {
        int from = 1;
        int to = 10;
        int sampleSize = 3;
        List<Integer> notWantedNumbers = new ArrayList<>();
        notWantedNumbers.add(1);
        notWantedNumbers.add(3);
        notWantedNumbers.add(5);
        notWantedNumbers.add(6);
        notWantedNumbers.add(8);
        notWantedNumbers.add(9);
        notWantedNumbers.add(10);

        RandomSample randomSample = new RandomSampleWithPutBack(from, to, sampleSize);
        randomSample.setIndicesToIgnore(notWantedNumbers);
        randomSample.drawSample();
        List<Integer> sample = randomSample.getSample();

        checkSample(from, to, sampleSize, sample);
        assertFalse(sample.contains(1));
        assertFalse(sample.contains(3));
        assertFalse(sample.contains(5));
        assertFalse(sample.contains(6));
        assertFalse(sample.contains(8));
        assertFalse(sample.contains(9));
        assertFalse(sample.contains(10));
    }

}
