package org.academiadecodigo.bootcamp.fxlogin.service.bootcamp;

import org.academiadecodigo.bootcamp.fxlogin.model.Bootcamp;
import org.academiadecodigo.bootcamp.fxlogin.model.Cadet;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.HashSet;
import java.util.Set;

import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

/**
 * MIT License
 * (c) 2017 Ricardo Constantino
 */

public class MockBootcampServiceTest {

    private BootcampService bootcampService;
    private Bootcamp bootcamp;
    private Bootcamp anotherBootcamp;
    private Cadet cadet;
    private Cadet anotherCadet;
    private Set<Cadet> oneCadet;
    private Set<Cadet> twoCadets;

    @Before
    public void setUp() throws Exception {
        bootcampService = new MockBootcampService();

        // create mocked code cadets
        cadet = mock(Cadet.class);
        anotherCadet = mock(Cadet.class);
        oneCadet = new HashSet<>();
        oneCadet.add(cadet);
        twoCadets = new HashSet<>();
        twoCadets.add(cadet);
        twoCadets.add(anotherCadet);

        // create mocked bootcamps and add some mocked code cadets to them
        bootcamp = mock(Bootcamp.class);
        when(bootcamp.getId()).thenReturn(1);
        when(bootcamp.getLocation()).thenReturn(Bootcamp.Location.LISBOA);
        when(bootcamp.getCadets()).thenReturn(oneCadet);
        anotherBootcamp = mock(Bootcamp.class);
        when(anotherBootcamp.getId()).thenReturn(2);
        when(bootcamp.getLocation()).thenReturn(Bootcamp.Location.FUNDAO);
        when(anotherBootcamp.getCadets()).thenReturn(twoCadets);
    }

    @After
    public void tearDown() throws Exception {
        bootcampService = null;
    }

    @Test
    public void createBootcamp() throws Exception {
        int id = 1;
        Bootcamp.Location location = Bootcamp.Location.LISBOA;
        String start = "2017/01/01";
        String end = "2017/03/01";
        bootcampService.createBootcamp(id, location, start, end);
        assertEquals(1, bootcampService.listBootcamps().size());
        Bootcamp addedBootcamp = bootcampService.listBootcamps().get(0);
        assertNotNull(addedBootcamp);
        assertSame(id, addedBootcamp.getId());
        assertEquals(location, addedBootcamp.getLocation());
        assertEquals(start, addedBootcamp.getStart());
        assertEquals(end, addedBootcamp.getEnd());
    }

    @Test
    public void addBootcamp() throws Exception {
        bootcampService.addBootcamp(bootcamp);
        assertEquals(1, bootcampService.listBootcamps().size());
        assertTrue(bootcampService.listBootcamps().contains(bootcamp));
        assertSame(bootcamp, bootcampService.listBootcamps().get(0));
    }

    @Test
    public void addCodeCadet() throws Exception {
        bootcampService.addBootcamp(bootcamp);
        bootcampService.addCodeCadet(bootcamp.getId(), cadet);
        verify(bootcamp, times(1)).addCodeCadet(cadet);
        assertEquals(1, bootcampService.listCodeCadets(bootcamp.getId()).size());
        assertTrue(bootcampService.listCodeCadets(bootcamp.getId()).contains(cadet));
        assertSame(cadet, bootcampService.listCodeCadets(bootcamp.getId()).toArray()[0]);
    }

    @Test
    public void addCodeCadets() throws Exception {
        bootcampService.addBootcamp(anotherBootcamp);
        bootcampService.addCodeCadets(anotherBootcamp.getId(), cadet, anotherCadet);
        verify(anotherBootcamp, times(1)).addCodeCadet(cadet);
        verify(anotherBootcamp, times(1)).addCodeCadet(anotherCadet);
        assertEquals(2, bootcampService.listCodeCadets(anotherBootcamp.getId()).size());
        assertTrue(bootcampService.listCodeCadets(anotherBootcamp.getId()).containsAll(twoCadets));
        assertSame(cadet, bootcampService.listCodeCadets(anotherBootcamp.getId()).toArray()[0]);
        assertSame(anotherCadet, bootcampService.listCodeCadets(anotherBootcamp.getId()).toArray()[1]);
    }

    @Test
    public void listBootcamps() throws Exception {
        bootcampService.addBootcamp(bootcamp);
        assertEquals(1, bootcampService.listBootcamps().size());
        assertSame(bootcamp, bootcampService.listBootcamps().get(0));
    }

    @Test
    public void listCodeCadets() throws Exception {
        bootcampService.addBootcamp(bootcamp);
        assertTrue(bootcampService.listCodeCadets(bootcamp.getId()).containsAll(oneCadet));
    }

    @Test
    public void setSelectedBootcamp() throws Exception {
        bootcampService.addBootcamp(bootcamp);
        bootcampService.setSelectedBootcamp(bootcamp.getId());
        assertSame(bootcamp.getId(), bootcampService.getSelectedBootcamp());
    }

    @Test
    public void getSelectedBootcamp() throws Exception {
        bootcampService.addBootcamp(anotherBootcamp);
        bootcampService.setSelectedBootcamp(anotherBootcamp.getId());
        assertSame(anotherBootcamp.getId(), bootcampService.getSelectedBootcamp());
    }

}