package CH.ifa.draw.io.exportFormats;

import java.io.File;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import javax.swing.filechooser.FileFilter;

import CH.ifa.draw.IOHelper;
import CH.ifa.draw.io.CombinationFileFilter;
import CH.ifa.draw.io.SimpleFileFilter;
import de.renew.ioontology.ExtensionFileFilter;
import de.renew.ioontology.MultiExtensionFileFilter;
import de.renew.ioontology.MultiExtensionFileFilterImpl;

/**
 * Abstract implementation of ExportFormatMulti and extension of the class ExportFormatAbstract.
 * @deprecated This type is not to be used anymore. Please use {@link de.renew.ioontology.exporting.ExportFormatMultiAbstract} and its subtypes instead.
 */
@Deprecated(since = "5.0", forRemoval = true)
@SuppressWarnings("removal")
public abstract class ExportFormatMultiAbstract extends ExportFormatAbstract
    implements ExportFormatMulti
{
    // All ExportFormats that have been added (MultiFormats do count as one element).
    private List<ExportFormat> _formats;

    /**
     * Constructs ExportFormatAbstract with a given name and a name for the new {@link MultiExtensionFileFilter}.
     * @param name the given name
     * @param filterName the name for the new combination file filter
     */
    public ExportFormatMultiAbstract(String name, String filterName) {
        super(name, new MultiExtensionFileFilterImpl(filterName));
        setFormats(new LinkedList<ExportFormat>());
    }

    /**
     * Returns map of all added ExportFormats.
     * @ensure result != null
     * @return list of export formats
     */
    public List<ExportFormat> formats() {
        List<ExportFormat> result;
        result = _formats;
        assert (result != null) : "Failure in ExportFormatAbstract: result == null";
        return result;
    }

    /**
     * Sets _formats to formats.
     * @require formats != null
     * @ensure formats() != null
     * @ensure formats().equals(formats)
     * @param formats the value to be set.
     */
    protected void setFormats(List<ExportFormat> formats) {
        _formats = formats;
        assert (formats() != null) : "Failure in ExportFormatAbstract: formats() == null";
        assert (formats().equals(formats))
            : "Failure in ExportFormatAbstract: formats() != formats";
    }

    /**
     * Returns the MultiExtensionFileFilter that contains all added FileFilters
     * (Does not contain other MultiExtensionFileFilter, but their elements).
     * @ensure result != null.
     * @return MultiExtensionFileFilter the MultiExtensionFileFilter for the ExportFormat.
     */
    protected MultiExtensionFileFilter multiFileFilter() {
        MultiExtensionFileFilter result = (MultiExtensionFileFilter) fileFilter();
        Objects.requireNonNull(result, "Failure in ExportFormatAbstract: result == null");
        return result;
    }

    /**
     * Adds a fileFilter to the CombinationFileFilter (If the fileFilter itself is a
     * CombinationFileFilter, only its elements are added).
     * @require fileFilter != null.
     * @param fileFilter the fileFilter to be added.
     */
    protected void addFileFilter(FileFilter fileFilter) {
        if (fileFilter instanceof CombinationFileFilter comFileFilter) {
            Iterator<SimpleFileFilter> filters = comFileFilter.getFileFilters().iterator();
            while (filters.hasNext()) {
                FileFilter element = filters.next();
                addFileFilter(element);
            }
        } else if (fileFilter instanceof MultiExtensionFileFilter multiFilter) {
            for (ExtensionFileFilter filter : multiFilter.getFileFilters()) {
                if (filter instanceof FileFilter ff) {
                    addFileFilter(ff);
                } else {
                    addFileFilter(IOHelper.mapToSwingFileFilter(filter));
                }
            }
        } else {
            if (fileFilter instanceof ExtensionFileFilter) {
                multiFileFilter().add((ExtensionFileFilter) fileFilter);
            }
        }
    }

    /**
     * Removes the fileFilter from the CombinationFileFilter (If fileFilter is
     * a CombinationFileFiler, all its elements are removed).
     * @require fileFilter != null.
     * @param fileFilter fileFilter to be removed.
     */
    protected void removeFileFilter(FileFilter fileFilter) {
        if (fileFilter instanceof CombinationFileFilter comFileFilter) {
            Iterator<SimpleFileFilter> filters = comFileFilter.getFileFilters().iterator();
            while (filters.hasNext()) {
                FileFilter element = filters.next();
                removeFileFilter(element);
            }
        } else if (fileFilter instanceof MultiExtensionFileFilter multiFilter) {
            for (ExtensionFileFilter filter : multiFilter.getFileFilters()) {
                if (filter instanceof FileFilter ff) {
                    removeFileFilter(ff);
                } else {
                    removeFileFilter(IOHelper.mapToSwingFileFilter(filter));
                }
            }
        } else {
            if (fileFilter instanceof ExtensionFileFilter) {
                multiFileFilter().remove((SimpleFileFilter) fileFilter);
            }
        }
    }

    // ---------------------------------------------------------------------
    // Implementation of the ExportFormatMulti Interface
    // ---------------------------------------------------------------------

    @Override
    public void addExportFormat(ExportFormat format) {
        formats().add(format);
        FileFilter filter = format.fileFilter();
        addFileFilter(filter);
    }

    @Override
    public ExportFormat[] allExportFormats() {
        ExportFormat[] result = null;
        result = new ExportFormat[formats().size()];
        for (int pos = 0; pos < result.length; pos++) {
            result[pos] = formats().get(pos);
        }
        assert (result != null) : "Failure in ExportFormatAbstract: result == null";
        return result;
    }

    @Override
    public void removeExportFormat(ExportFormat format) {
        removeFileFilter(format.fileFilter());
        formats().remove(format);
    }


    @Override
    public boolean canExportNto1() {
        return false;
    }

    @Override
    public ExportFormat[] canExport(File path) {
        ExportFormat[] result = super.canExport(path);
        if (path != null) {
            List<ExportFormat[]> list = new LinkedList<ExportFormat[]>();
            int count = 0;
            for (int pos = 0; pos < allExportFormats().length; pos++) {
                ExportFormat[] formats = allExportFormats()[pos].canExport(path);
                if (formats.length > 0) {
                    list.add(formats);
                    count = count + formats.length;
                }
            }
            result = new ExportFormat[count];
            Iterator<ExportFormat[]> iter = list.iterator();
            while (iter.hasNext()) {
                ExportFormat[] element = iter.next();
                for (ExportFormat exportFormat : element) {
                    result[--count] = exportFormat;
                }
            }
        }
        assert (result != null) : "Failure in ExportFormatMultiAbstract: result == null";
        return result;
    }
}