/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.commons.vfs2;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

/**
 * Tests FileExtensionSelector.
 *
 * @since 2.1
 */
public class PatternFileSelectorTest
{
    private static FileObject BaseFolder;

    /**
     * 9 files and 1 directory = 10
     */
    private static final int EntryCount = 10;

    private static final int ExtensionCount = 3;

    private static final int FilesPerExtensionCount = 3;

    /**
     * Creates a RAM FS.
     *
     * @throws Exception
     */
    @BeforeClass
    public static void setUpClass() throws Exception
    {
        BaseFolder = VFS.getManager().resolveFile("ram://" + PatternFileSelectorTest.class.getName());
        BaseFolder.deleteAll();
        BaseFolder.createFolder();
        BaseFolder.resolveFile("a.htm").createFile();
        BaseFolder.resolveFile("a.html").createFile();
        BaseFolder.resolveFile("a.xhtml").createFile();
        BaseFolder.resolveFile("b.htm").createFile();
        BaseFolder.resolveFile("b.html").createFile();
        BaseFolder.resolveFile("b.xhtml").createFile();
        BaseFolder.resolveFile("c.htm").createFile();
        BaseFolder.resolveFile("c.html").createFile();
        BaseFolder.resolveFile("c.xhtml").createFile();
    }

    /**
     * Deletes RAM FS files.
     *
     * @throws Exception
     */
    @AfterClass
    public static void tearDownClass() throws Exception
    {
        if (BaseFolder != null)
        {
            BaseFolder.deleteAll();
        }
    }

    /**
     * Tests a null selector.
     *
     * @throws Exception
     */
    @Test(expected = NullPointerException.class)
    public void testNullString() throws Exception
    {
        // Yep, this will blow up.
        new PatternFileSelector((String) null);
    }

    /**
     * Tests matching all
     *
     * @throws Exception
     */
    @Test
    public void testMatchAll() throws Exception
    {
        final FileObject[] list = BaseFolder.findFiles(new PatternFileSelector(".*"));
        Assert.assertEquals(EntryCount, list.length);
    }

    /**
     * Tests a one extension selector.
     *
     * @throws Exception
     */
    @Test
    public void testFileExtensions() throws Exception
    {
        final FileObject[] foArray = BaseFolder.findFiles(Selectors.SELECT_FILES);
        Assert.assertTrue(foArray.length > 0);
        final String regExPrefix = ".*\\.";
        // gather file extensions.
        final Set<String> extensionSet = new HashSet<String>();
        for (final FileObject fo : foArray)
        {
            extensionSet.add(regExPrefix + fo.getName().getExtension());
        }
        final String message = String.format("Extensions: %s; files: %s", extensionSet.toString(),
                Arrays.asList(foArray).toString());
        Assert.assertEquals(message, ExtensionCount, extensionSet.size());
        // check each extension
        for (final String extension : extensionSet)
        {
            final FileSelector selector = new PatternFileSelector(extension);
            final FileObject[] list = BaseFolder.findFiles(selector);
            Assert.assertEquals(FilesPerExtensionCount, list.length);
        }
        // check each file against itself
        for (final FileObject fo : foArray)
        {
            final FileSelector selector = new PatternFileSelector(regExPrefix + fo.getName().getExtension());
            final FileObject[] list = BaseFolder.findFiles(selector);
            Assert.assertEquals(FilesPerExtensionCount, list.length);
        }
    }

}
