package dst.ass1.jpa.tests;

import static org.hamcrest.CoreMatchers.hasItems;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

import java.util.Map;
import java.util.stream.Collectors;

import javax.persistence.EntityManager;

import org.junit.Before;
import org.junit.Test;

import dst.ass1.jpa.dao.ICourseDAO;
import dst.ass1.jpa.dao.IDAOFactory;
import dst.ass1.jpa.dao.ILecturerDAO;
import dst.ass1.jpa.dao.impl.DAOFactory;
import dst.ass1.jpa.model.ICourse;
import dst.ass1.jpa.model.ILecturer;
import dst.ass1.jpa.model.ILesson;
import dst.ass1.jpa.model.IMetadata;
import dst.ass1.jpa.util.Constants;

public class Ass1_2_2Test extends Ass1_TestBase {

    private ILecturerDAO lecturerDAO;
    private ICourseDAO courseDAO;

    @Before
    public void setUp() throws Exception {
        // makes sure there's no cache from creating entities
        EntityManager em = orm.createEntityManager();
        IDAOFactory daoFactory = new DAOFactory(em);

        lecturerDAO = daoFactory.createLecturerDAO();
        courseDAO = daoFactory.createCourseDAO();
    }

    @Test
    public void testUpcomingLessonsExists() {
        em.createNamedQuery(Constants.Q_UPCOMING_LESSONS);
    }

    @Test
    public void testUpcomingLessonsQuery() {
        ICourse course = courseDAO.findById(testData.course1Id);
        Map<ILecturer, ILesson> result = lecturerDAO.findUpcomingLessonForLecturersOfCourse(course);

        assertEquals(3, result.size());
        Map<Long, ILesson> resultIds = convertMapKeys(result);
        System.out.println(resultIds);
        assertThat(resultIds.keySet(), hasItems(testData.lecturer1Id, testData.lecturer2Id, testData.lecturer3Id));

        assertEquals(testData.lesson4Id, resultIds.get(testData.lecturer1Id).getId());
        assertEquals(testData.lesson2Id, resultIds.get(testData.lecturer2Id).getId());
        assertEquals(testData.lesson3Id, resultIds.get(testData.lecturer3Id).getId());
    }

    @Test
    public void testUpcomingLessonsQuery2() {
        ICourse course = courseDAO.findById(testData.course2Id);
        Map<ILecturer, ILesson> result = lecturerDAO.findUpcomingLessonForLecturersOfCourse(course);

        assertEquals(1, result.size());
        Map<Long, ILesson> resultIds = convertMapKeys(result);
        System.out.println(resultIds);
        assertThat(resultIds.keySet(), hasItems(testData.lecturer2Id));

        assertEquals(testData.lesson5Id, resultIds.get(testData.lecturer2Id).getId());
    }

    @Test
    public void testUpcomingLessonsQuery_onEmptyDatabase() {
        db.truncateTables();

        ICourse course = modelFactory.createCourse();
        IMetadata metadata = modelFactory.createMetadata();
        course.setMetadata(metadata);
        em.persist(metadata);
        em.persist(course);

        Map<ILecturer, ILesson> result = daoFactory.createLecturerDAO().findUpcomingLessonForLecturersOfCourse(course);
        assertTrue(result.isEmpty());
    }

    private Map<Long, ILesson> convertMapKeys(Map<ILecturer, ILesson> result) {
        return result.entrySet().stream().collect(Collectors.toMap(
                kv -> kv.getKey().getId(),
                kv -> kv.getValue()
        ));
    }

}
