package de.renew.navigator.models;

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

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;


/**
 * @author 1baaske
 */
class NavigatorFileTreeTest {
    private static final String INPUT_NAME = "name";

    private NavigatorFileTree _navigatorFileTree;
    private SearchFilter _searchFilter;
    private List<SearchFilter> _searchFilters;

    @BeforeEach
    public void setUp() {
        NavigatorFileTree navigatorFileTree = new NavigatorFileTree();
        SearchFilter activeFileFilter =
            new SearchFilter(INPUT_NAME, SearchFilter.Type.CONTAINS, true);
        List<SearchFilter> activeFileFilters = new ArrayList<>();
        activeFileFilters.add(activeFileFilter);
        this._navigatorFileTree = navigatorFileTree;
        this._searchFilter = activeFileFilter;
        this._searchFilters = activeFileFilters;
    }

    @Test
    public void testSetActiveFileFiltersChange() {
        //given
        assertFalse(_navigatorFileTree.hasChanged());

        //when
        _navigatorFileTree.setActiveFileFilters(_searchFilters);

        //then
        assertNotNull(_navigatorFileTree.getActiveFileFilters());
        assertTrue(_navigatorFileTree.getActiveFileFilters().contains(_searchFilter));
        assertEquals(_searchFilters, _navigatorFileTree.getActiveFileFilters());
        assertTrue(_navigatorFileTree.hasChanged());
    }

    @Test
    public void testSetActiveFileFiltersNoChange() {
        //given
        assertFalse(_navigatorFileTree.hasChanged());
        List<SearchFilter> emptyList = new ArrayList<>();

        //when
        _navigatorFileTree.setActiveFileFilters(emptyList);

        //then
        assertNotNull(_navigatorFileTree.getActiveFileFilters());
        assertEquals(emptyList, _navigatorFileTree.getActiveFileFilters());
        assertTrue(_navigatorFileTree.hasChanged());
    }

    @Test
    public void testActivateFileFilter() {
        //given
        assertFalse(_navigatorFileTree.hasChanged());

        //when
        _navigatorFileTree.activateFileFilter(_searchFilter);

        //then
        assertEquals(_searchFilters, _navigatorFileTree.getActiveFileFilters());
        assertTrue(_navigatorFileTree.hasChanged());
    }

    @Test
    public void testDeactivateFileFilterModelPositive() {
        //given
        List<SearchFilter> emptyList = new ArrayList<>();
        _navigatorFileTree.setActiveFileFilters(_searchFilters);

        //when
        _navigatorFileTree.deactivateFileFilter(_searchFilter);

        //then
        assertEquals(emptyList, _navigatorFileTree.getActiveFileFilters());
    }

    @Test
    public void testDeactivateFileFilterModelNegative() {
        assertThrows(
            IllegalArgumentException.class,
            () -> _navigatorFileTree.deactivateFileFilter(_searchFilter));
        assertFalse(_navigatorFileTree.hasChanged());
    }

    @Test
    public void testGetFileFilterByNamePositive() {
        //given
        _navigatorFileTree.setActiveFileFilters(_searchFilters);

        //when
        SearchFilter filter = _navigatorFileTree.getFileFilterByName(INPUT_NAME);

        //then
        assertEquals(filter, _searchFilter);
    }

    @Test
    public void testGetFileFilterByNameNegative() {
        //given
        _navigatorFileTree.setActiveFileFilters(_searchFilters);

        //when
        String inputSomething = "something";
        SearchFilter filter = _navigatorFileTree.getFileFilterByName(inputSomething);

        //then
        assertNull(filter);
    }

    @Test
    public void testDeactivateFileFilterNamePositive() {
        List<SearchFilter> emptyList = new ArrayList<>();
        _navigatorFileTree.setActiveFileFilters(_searchFilters);

        //when
        _navigatorFileTree.deactivateFileFilter(INPUT_NAME);

        //then
        assertEquals(emptyList, _navigatorFileTree.getActiveFileFilters());
    }

    @Test
    public void testClearTreeRoots() {
        //given
        List<TreeElement> emptyList = new ArrayList<>();
        TreeElement element = new Directory();
        _navigatorFileTree.add(element);

        //when
        _navigatorFileTree.clearTreeRoots();

        //then
        assertEquals(emptyList, _navigatorFileTree._elements);
        assertTrue(_navigatorFileTree.hasChanged());
    }

    @Test
    public void testExpandAll() {
        //given
        Directory element = new Directory();
        _navigatorFileTree.add(element);

        //when
        _navigatorFileTree.expandAll();

        //then
        assertTrue(element.isOpened());
    }

    @Test
    public void testClear() {
        //given
        List<SearchFilter> emptyListFilter = new ArrayList<>();
        List<TreeElement> emptyListTree = new ArrayList<>();
        _navigatorFileTree.setActiveFileFilters(_searchFilters);
        TreeElement element = new Directory();
        _navigatorFileTree.add(element);

        //when
        _navigatorFileTree.clear();

        //then
        assertEquals(emptyListFilter, _navigatorFileTree.getActiveFileFilters());
        assertEquals(emptyListTree, _navigatorFileTree._elements);
    }

    @Test
    public void testAddBackgroundTask() {
        //given
        BackgroundTask task = new BackgroundTask(INPUT_NAME);
        List<BackgroundTask> tasks = new ArrayList<>();
        tasks.add(task);

        //when
        _navigatorFileTree.addBackgroundTask(task);

        //then
        assertEquals(_navigatorFileTree.getBackgroundTasks(), tasks);
        assertTrue(_navigatorFileTree.hasChanged());

    }

    @Test
    public void testRemoveBackgroundTaskPositive() {
        //given
        BackgroundTask task = new BackgroundTask(INPUT_NAME);
        List<BackgroundTask> emptyList = new ArrayList<>();
        _navigatorFileTree.addBackgroundTask(task);

        //when
        _navigatorFileTree.removeBackgroundTask(task);

        //then
        assertEquals(_navigatorFileTree.getBackgroundTasks(), emptyList);
        assertTrue(_navigatorFileTree.hasChanged());
    }

    /**
     * Check that the function doesn't throw an exception if something is removed that is not contained in
     * backgroundTasks.
     */
    @Test
    public void testRemoveBackgroundTaskNegative() {
        //given
        BackgroundTask task = new BackgroundTask(INPUT_NAME);
        List<BackgroundTask> emptyList = new ArrayList<>();

        //when
        _navigatorFileTree.removeBackgroundTask(task);

        //then
        assertEquals(_navigatorFileTree.getBackgroundTasks(), emptyList);
        assertTrue(_navigatorFileTree.hasChanged());
    }

    @Test
    public void testSetTextSearch() {
        //when
        _navigatorFileTree.setTextSearch(_searchFilter);

        //then
        assertEquals(_searchFilter, _navigatorFileTree.getTextSearch());
        assertTrue(_navigatorFileTree.hasChanged());
    }

}