/*
 * Copyright 2014 The Codehaus Foundation.
 *
 * 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.codehaus.plexus.archiver.util;

import javax.annotation.Nonnull;

import org.codehaus.plexus.archiver.BaseFileSet;
import org.codehaus.plexus.components.io.filemappers.FileMapper;
import org.codehaus.plexus.components.io.fileselectors.FileSelector;
import org.codehaus.plexus.components.io.functions.InputStreamTransformer;

/**
 * Default implementation of {@link BaseFileSet}.
 *
 * @since 1.0-alpha-9
 */
public abstract class AbstractFileSet<T extends AbstractFileSet> implements BaseFileSet {

    private String prefix;

    private String[] includes;

    private String[] excludes;

    private FileSelector[] fileSelectors;

    private boolean caseSensitive = true;

    private boolean usingDefaultExcludes = true;

    private boolean includingEmptyDirectories = true;

    private InputStreamTransformer streamTransformer = null;

    private FileMapper[] fileMappers;

    /**
     * Sets a string of patterns, which excluded files
     * should match.
     */
    public void setExcludes(String[] excludes) {
        this.excludes = excludes;
    }

    @Override
    public String[] getExcludes() {
        return excludes;
    }

    /**
     * Sets a set of file selectors, which should be used
     * to select the included files.
     */
    public void setFileSelectors(FileSelector[] fileSelectors) {
        this.fileSelectors = fileSelectors;
    }

    @Override
    public FileSelector[] getFileSelectors() {
        return fileSelectors;
    }

    /**
     * Sets a string of patterns, which included files
     * should match.
     */
    public void setIncludes(String[] includes) {
        this.includes = includes;
    }

    @Override
    public String[] getIncludes() {
        return includes;
    }

    /**
     * Sets the prefix, which the file sets contents shall
     * have.
     */
    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }

    @Override
    public String getPrefix() {
        return prefix;
    }

    /**
     * Sets, whether the include/exclude patterns are
     * case sensitive. Defaults to true.
     */
    public void setCaseSensitive(boolean caseSensitive) {
        this.caseSensitive = caseSensitive;
    }

    @Override
    public boolean isCaseSensitive() {
        return caseSensitive;
    }

    /**
     * Sets, whether the default excludes are being
     * applied. Defaults to true.
     */
    public void setUsingDefaultExcludes(boolean usingDefaultExcludes) {
        this.usingDefaultExcludes = usingDefaultExcludes;
    }

    @Override
    public boolean isUsingDefaultExcludes() {
        return usingDefaultExcludes;
    }

    /**
     * Sets, whether empty directories are being included. Defaults
     * to true.
     */
    public void setIncludingEmptyDirectories(boolean includingEmptyDirectories) {
        this.includingEmptyDirectories = includingEmptyDirectories;
    }

    @Override
    public boolean isIncludingEmptyDirectories() {
        return includingEmptyDirectories;
    }

    public T prefixed(String prefix) {
        setPrefix(prefix);
        return (T) this;
    }

    public T include(String[] includes) {
        setIncludes(includes);
        return (T) this;
    }

    public T exclude(String[] excludes) {
        setExcludes(excludes);
        return (T) this;
    }

    public T includeExclude(String[] includes, String[] excludes) {
        return (T) include(includes).exclude(excludes);
    }

    public T includeEmptyDirs(boolean includeEmptyDirectories) {
        setIncludingEmptyDirectories(includeEmptyDirectories);
        return (T) this;
    }

    @SuppressWarnings("unchecked")
    public T usingDefaultExcludes(boolean usingDefaultExcludes) {
        setUsingDefaultExcludes(usingDefaultExcludes);
        return (T) this;
    }

    public void setStreamTransformer(@Nonnull InputStreamTransformer streamTransformer) {
        this.streamTransformer = streamTransformer;
    }

    @Override
    public InputStreamTransformer getStreamTransformer() {
        return streamTransformer;
    }

    /**
     * Sets a set of file mappers, which should be used
     * to change the filename of the included files.
     */
    public void setFileMappers(FileMapper[] fileMappers) {
        this.fileMappers = fileMappers;
    }

    @Override
    public FileMapper[] getFileMappers() {
        return fileMappers;
    }
}
