/*
 *  @author Ranides Atterwim <ranides@gmail.com>
 *  @copyright Ranides Atterwim
 *  @license WTFPL
 *  @url http://ranides.net/projects/assira
 */

package net.ranides.assira.io;

import java.io.File;
import java.util.EnumSet;
import java.util.Set;

/**
 * Klasa abstrakcyjna ułatwiająca pisanie bardziej zaawansowanych filtrów, które
 * mogą być używane w SWINGowym {@link javax.swing.JFileChooser} lub innych 
 * metodach, np w klasie {@link DirectoryHelper}
 * @author ranides
 */
public abstract class FileFilter extends javax.swing.filechooser.FileFilter implements java.io.FileFilter {
    
    /**
     * Tryb generowania wyniku listowania zawartości katalogów przez filtr.
     */
    public enum AcceptMode {
        /** Dodaje do wyniku pliki spełniające warunki filtru. */
        FILE,
        
        /** Dodaje do wyniku wszystkie napotkane pliki */
        ANY_FILE,
        
        /** Dodaje do wyniku katalogi spełniające warunki filtru. */
        DIRECTORY,
        
        /** Dodaje do wyniku wszystkie napotkane katalogi */
        ANY_DIRECTORY,
        
        /** Przegląda katalog wgłąb */
        RECURSIVE,
    }
    
    /**
     * Metoda sprawdzająca, czy podany plik spełnia kryteria filtru.
     * @param file
     * @return
     */
    public abstract boolean acceptFile(File file);
    
    private EnumSet<AcceptMode> mode = EnumSet.of(AcceptMode.ANY_DIRECTORY, AcceptMode.FILE);
    private String description = "(anonymous filter)";

    /**
     * Tworzy nowy filtr, który akceptuje wszystkie katalogi, oraz pliki
     * pasujące spełniające kryteria. Konstruktor użyteczny dla filtrów, które
     * są przeznaczone do użycia w "przeglądarkach plików" (FileChooser etc)
     */
    public FileFilter() {
        this( EnumSet.of(AcceptMode.ANY_DIRECTORY, AcceptMode.FILE) );
        
    }

    /**
     * Tworzy nowy filtr, który akceptuje obiekty o określonym typie.
     * @param mode 
     */
    public FileFilter(Set<AcceptMode> mode) {
        this("(anonymous filter)", mode);
    }
    
    /**
     * Tworzy nowy filtr o określonym opisie, który akceptuje obiekty o określonym typie.
     * @param description
     * @param mode  
     */
    public FileFilter(String description, Set<AcceptMode> mode) {
        this.mode = EnumSet.copyOf(mode);
        this.description = description;
    }
    
    @Override
    public final String getDescription() {
        return description;
    }

    /**
     * Ustawia opis filtru
     * @param description
     */
    public final void setDescription(String description) {
        this.description = description;
    }

    /**
     * Zwraca flagi ustawione w filtrze. Flagi mają wpływ na typ obiektów
     * akceptowanych przez filtr. Niektóre metody uwzględniają również to, czy
     * filtr ma włączony tryb przeszukiwania wgłąb.
     * @return
     */
    public EnumSet<AcceptMode> getMode() {
        return mode;
    }

    /**
     * Ustawia flagi filtru. Flagi mają wpływ na typ obiektów akceptowanych przez 
     * filtr. Niektóre metody uwzględniają również to, czy filtr ma włączony tryb
     * przeszukiwania wgłąb.
     * @param mode
     */
    public void setMode(Set<AcceptMode> mode) {
        this.mode = EnumSet.copyOf(mode);
    }

    @Override
    public final boolean accept(File file) {
        if( file.isDirectory() ) {
            if( mode.contains(AcceptMode.ANY_DIRECTORY)) {
                return true;
            } else if (mode.contains(AcceptMode.DIRECTORY)) {
                return acceptFile(file);
            } else {
                return false;
            }
        } else {
            if( mode.contains(AcceptMode.ANY_FILE)) {
                return true;
            } else if (mode.contains(AcceptMode.FILE)) {
                return acceptFile(file);
            } else {
                return false;
            }
        }
    }

}
