/*
 * Copyright (C) 2012-present the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.pf4j.util;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

import java.io.File;
import java.io.FileFilter;
import java.nio.file.Path;
import java.util.Arrays;

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

class OrFileFilterTest {

    @TempDir
    Path tempDir;

    @Test
    void emptyFilterReturnsTrue() {
        OrFileFilter filter = new OrFileFilter();
        File testFile = tempDir.resolve("test.txt").toFile();

        assertTrue(filter.accept(testFile));
    }

    @Test
    void singleFilterReturnsItsResult() {
        FileFilter alwaysTrue = file -> true;
        FileFilter alwaysFalse = file -> false;

        File testFile = tempDir.resolve("test.txt").toFile();

        assertTrue(new OrFileFilter(alwaysTrue).accept(testFile));
        assertFalse(new OrFileFilter(alwaysFalse).accept(testFile));
    }

    @Test
    void returnsTrueIfAnyFilterReturnsTrue() {
        FileFilter alwaysTrue = file -> true;
        FileFilter alwaysFalse = file -> false;

        File testFile = tempDir.resolve("test.txt").toFile();

        OrFileFilter filter = new OrFileFilter(alwaysTrue, alwaysFalse);
        assertTrue(filter.accept(testFile));

        filter = new OrFileFilter(alwaysFalse, alwaysTrue);
        assertTrue(filter.accept(testFile));
    }

    @Test
    void returnsFalseIfAllFiltersReturnFalse() {
        FileFilter alwaysFalse1 = file -> false;
        FileFilter alwaysFalse2 = file -> false;

        File testFile = tempDir.resolve("test.txt").toFile();

        OrFileFilter filter = new OrFileFilter(alwaysFalse1, alwaysFalse2);
        assertFalse(filter.accept(testFile));
    }

    @Test
    void addFileFilter() {
        FileFilter alwaysTrue = file -> true;

        OrFileFilter filter = new OrFileFilter();
        filter.addFileFilter(alwaysTrue);

        File testFile = tempDir.resolve("test.txt").toFile();
        assertTrue(filter.accept(testFile));
    }

    @Test
    void removeFileFilter() {
        FileFilter alwaysTrue = file -> true;
        FileFilter alwaysFalse = file -> false;

        OrFileFilter filter = new OrFileFilter(alwaysTrue, alwaysFalse);
        File testFile = tempDir.resolve("test.txt").toFile();

        assertTrue(filter.accept(testFile));

        assertTrue(filter.removeFileFilter(alwaysTrue));
        assertFalse(filter.accept(testFile));

        assertFalse(filter.removeFileFilter(alwaysTrue));
    }

    @Test
    void setFileFilters() {
        FileFilter alwaysTrue = file -> true;
        FileFilter alwaysFalse = file -> false;

        OrFileFilter filter = new OrFileFilter();
        filter.setFileFilters(Arrays.asList(alwaysTrue, alwaysFalse));

        File testFile = tempDir.resolve("test.txt").toFile();
        assertTrue(filter.accept(testFile));
    }

    @Test
    void getFileFilters() {
        FileFilter filter1 = file -> true;
        FileFilter filter2 = file -> false;

        OrFileFilter orFilter = new OrFileFilter(filter1, filter2);

        assertEquals(2, orFilter.getFileFilters().size());
        assertTrue(orFilter.getFileFilters().contains(filter1));
        assertTrue(orFilter.getFileFilters().contains(filter2));
    }

    @Test
    void constructorWithList() {
        FileFilter filter1 = file -> true;
        FileFilter filter2 = file -> false;

        OrFileFilter orFilter = new OrFileFilter(Arrays.asList(filter1, filter2));

        File testFile = tempDir.resolve("test.txt").toFile();
        assertTrue(orFilter.accept(testFile));
    }

}