/**
 * Copyright (C) 2019 Patrik Dufresne Service Logiciel <info@patrikdufresne.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package com.planimod.core;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.util.Arrays;
import java.util.Date;
import java.util.List;

import org.junit.Assert;
import org.junit.Test;

import com.patrikdufresne.managers.ManagerEvent;
import com.patrikdufresne.managers.ManagerException;

/**
 * This class contains test to cover operation done using employee objects.
 * 
 * @author patapouf
 * 
 */
public class EmployeeManagerTest extends ManagerTestCase {

    /**
     * This test case intend to cover the requirement SR001 : permettre d'ajouter un employé ...
     */
    @Test
    public void AddEmployee() {

        addManagerObserver(ManagerEvent.ADD, Employee.class);

        Employee employee = new Employee();
        try {
            managers.getEmployeeManager().add(Arrays.asList(employee));
        } catch (ManagerException e) {
            fail("Error adding object", e);
        }

        assertEquals("Wrong number of events", 1, getManagerEvents().size());

        assertManagerEvent(1, getManagerEvents(), ManagerEvent.ADD, employee);

    }

    /**
     * Check if the list does not contains archived employee.
     * 
     * @throws ManagerException
     */
    @Test
    public void list_WithArchivedEmployee() throws ManagerException {

        Employee emp1 = addEmployee(managers, "employee#1");
        Employee emp2 = addEmployee(managers, "employee#2");

        List<Employee> employees = managers.getEmployeeManager().list();
        assertEquals(2, employees.size());
        assertTrue(employees.contains(emp1));
        assertTrue(employees.contains(emp2));

        // Archive employee
        managers.archiveAll(Arrays.asList(emp2));

        employees = managers.getEmployeeManager().list();
        assertEquals(1, employees.size());
        assertTrue(employees.contains(emp1));

    }

    /**
     * This case intend to cover the requirement SR001 : ... modifier son profile (nom, prénom, date d'embauche) ...
     */
    @Test
    public void Update() {

        addManagerObserver(ManagerEvent.UPDATE, Employee.class);

        Employee e1 = new Employee();
        try {
            managers.getEmployeeManager().add(Arrays.asList(e1));
        } catch (ManagerException e) {
            fail("Error adding object", e);
        }

        e1.setFirstname("test1");
        e1.setLastname("test2");
        e1.setHireDate(new Date());

        assertEquals("Wrong number of events", 0, getManagerEvents().size());

        // Save modification
        try {
            managers.getEmployeeManager().update(Arrays.asList(e1));
        } catch (ManagerException e) {
            fail("Error updating object", e);
        }

        assertEquals("Wrong number of events", 1, getManagerEvents().size());
        assertManagerEvent(1, getManagerEvents(), ManagerEvent.UPDATE, e1);

        // Reload employee
        Employee e2;
        try {
            e2 = managers.getEmployeeManager().get(e1.getId());
        } catch (ManagerException e) {
            fail("Error loading object", e);
            return;
        }

        Assert.assertEquals("Objects not equals", e1.getFirstname(), e2.getFirstname());
        Assert.assertEquals("Objects not equals", e1.getLastname(), e2.getLastname());
        Assert.assertEquals("Objects not equals", e1.getHireDate(), e2.getHireDate());

    }

    /**
     * Check if an exception is raised when trying to update an archived employee object.
     * 
     * @throws ManagerException
     */
    @Test(expected = ManagerException.class)
    public void Update_WithArchivedEmployee() throws ManagerException {

        // create employee object.
        Employee emp = addEmployee(managers, "Employee#1");

        // Archive employee object
        managers.archiveAll(Arrays.asList(emp));

        // Try to update the object
        emp.setFirstname("Emp#1");
        managers.updateAll(Arrays.asList(emp));

    }

    /**
     * Create and then remove object.
     * 
     * @throws ManagerException
     */
    @Test
    public void remove_withoutDependencies() throws ManagerException {

        addManagerObserver(ManagerEvent.REMOVE, Employee.class);

        /*
         * Add employee object
         */
        Employee employee = new Employee();
        managers.getEmployeeManager().add(Arrays.asList(employee));
        assertEquals("Wrong number of events.", 0, getManagerEvents().size());

        /*
         * Remove employee.
         */
        managers.getEmployeeManager().remove(Arrays.asList(employee));

        assertEquals("Wrong number of events.", 1, getManagerEvents().size());
        assertManagerEvent(1, getManagerEvents(), ManagerEvent.REMOVE, employee);

        assertFalse(managers.getEmployeeManager().list().contains(employee));
    }

    /**
     * Test to delete the employee and the associated preference object.
     * 
     * @throws ManagerException
     */
    @Test
    public void remove_WithoutDependencies() throws ManagerException {

        /*
         * Create the require elements
         */
        Employee emp = addEmployee(managers, "Employee1");
        Section s = addSection(managers, "Section");
        Team shift = addTeam(managers, "Shift1");
        setEmployeePreference(managers, emp, null, shift, s, Arrays.asList(shift));

        assertTrue(managers.getEmployeeManager().list().contains(emp));
        assertNotNull(managers.getEmployeePreferenceManager().getByEmployee(emp));

        /*
         * Delete employee
         */
        managers.getEmployeeManager().remove(Arrays.asList(emp));

        assertFalse(managers.getEmployeeManager().list().contains(emp));
        assertNull(managers.getEmployeePreferenceManager().getByEmployee(emp));

    }
}
