/*
 * 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.Iterator;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * Configures file systems individually with these options.
 * <p>
 * To configure a file system, you set properties on a {@link FileSystemOptions} object. Most file systems provide a
 * {@link FileSystemConfigBuilder} with specific options for that file system.
 * </p>
 * <p>
 * To use the options, pass them to {@link FileSystemManager#resolveFile(String,FileSystemOptions)}. From there, the
 * options apply to all files that are resolved relative to that file.
 * </p>
 *
 * @see org.apache.commons.vfs2.impl.DefaultFileSystemConfigBuilder
 * @see org.apache.commons.vfs2.provider.ftp.FtpFileSystemConfigBuilder
 * @see org.apache.commons.vfs2.provider.ftps.FtpsFileSystemConfigBuilder
 * @see org.apache.commons.vfs2.provider.hdfs.HdfsFileSystemConfigBuilder
 * @see org.apache.commons.vfs2.provider.http.HttpFileSystemConfigBuilder
 * @see org.apache.commons.vfs2.provider.ram.RamFileSystemConfigBuilder
 * @see org.apache.commons.vfs2.provider.res.ResourceFileSystemConfigBuilder
 * @see org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder
 * @see org.apache.commons.vfs2.provider.zip.ZipFileSystemConfigBuilder
 *
 */
public final class FileSystemOptions implements Cloneable {

    /** The options */
    private final Map<FileSystemOptionKey, Object> options;

    /**
     * Creates a new instance.
     */
    public FileSystemOptions() {
        this(new TreeMap<FileSystemOptionKey, Object>());
    }

    protected FileSystemOptions(final Map<FileSystemOptionKey, Object> options) {
        this.options = options;
    }

    /**
     * Keys in the options Map.
     */
    private static final class FileSystemOptionKey implements Comparable<FileSystemOptionKey> {
        /** Constant used to create hashcode */
        private static final int HASH = 29;

        /** The FileSystem class */
        private final Class<? extends FileSystem> fileSystemClass;

        /** The option name */
        private final String name;

        // TODO: the parameter name suggests that the class should only be a
        // a FileSystem, however some of the tests pass in DefaultFileSystemConfigBuilder
        private FileSystemOptionKey(final Class<? extends FileSystem> fileSystemClass, final String name) {
            this.fileSystemClass = fileSystemClass;
            this.name = name;
        }

        @Override
        public int compareTo(final FileSystemOptionKey o) {
            final int ret = fileSystemClass.getName().compareTo(o.fileSystemClass.getName());
            if (ret != 0) {
                return ret;
            }
            return name.compareTo(o.name);
        }

        @Override
        public boolean equals(final Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }

            final FileSystemOptionKey that = (FileSystemOptionKey) o;

            if (!fileSystemClass.equals(that.fileSystemClass)) {
                return false;
            }
            return name.equals(that.name);
        }

        @Override
        public int hashCode() {
            int result;
            result = fileSystemClass.hashCode();
            result = HASH * result + name.hashCode();
            return result;
        }

        @Override
        public String toString() {
            return fileSystemClass.getName() + "." + name;
        }
    }

    void setOption(final Class<? extends FileSystem> fileSystemClass, final String name, final Object value) {
        options.put(new FileSystemOptionKey(fileSystemClass, name), value);
    }

    <T> T getOption(final Class<? extends FileSystem> fileSystemClass, final String name) {
        final FileSystemOptionKey key = new FileSystemOptionKey(fileSystemClass, name);
        return (T) options.get(key);
    }

    boolean hasOption(final Class<? extends FileSystem> fileSystemClass, final String name) {
        final FileSystemOptionKey key = new FileSystemOptionKey(fileSystemClass, name);
        return options.containsKey(key);
    }

    public int compareTo(final FileSystemOptions other) {
        if (this == other) {
            // the same instance
            return 0;
        }

        final int propsSz = options == null ? 0 : options.size();
        final int propsFkSz = other.options == null ? 0 : other.options.size();
        if (propsSz < propsFkSz) {
            return -1;
        }
        if (propsSz > propsFkSz) {
            return 1;
        }
        if (propsSz == 0) {
            // props empty
            return 0;
        }

        // ensure proper sequence of options
        final SortedMap<FileSystemOptionKey, Object> myOptions = options instanceof SortedMap
                ? (SortedMap<FileSystemOptionKey, Object>) options
                : new TreeMap<>(options);
        final SortedMap<FileSystemOptionKey, Object> theirOptions = other.options instanceof SortedMap
                ? (SortedMap<FileSystemOptionKey, Object>) other.options
                : new TreeMap<>(other.options);
        final Iterator<FileSystemOptionKey> optKeysIter = myOptions.keySet().iterator();
        final Iterator<FileSystemOptionKey> otherKeysIter = theirOptions.keySet().iterator();
        while (optKeysIter.hasNext()) {
            final int comp = optKeysIter.next().compareTo(otherKeysIter.next());
            if (comp != 0) {
                return comp;
            }
        }

        final int hash = Arrays.deepHashCode(myOptions.values().toArray());
        final int hashFk = Arrays.deepHashCode(theirOptions.values().toArray());
        return Integer.compare(hash, hashFk);

        // TODO: compare Entry by Entry ??
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        if (options == null) {
            result = prime * result;
        } else {
            final SortedMap<FileSystemOptionKey, Object> myOptions = options instanceof SortedMap
                    ? (SortedMap<FileSystemOptionKey, Object>) options
                    : new TreeMap<>(options);
            result = prime * result + myOptions.keySet().hashCode();
            result = prime * result + Arrays.deepHashCode(myOptions.values().toArray());
        }
        return result;
    }

    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final FileSystemOptions other = (FileSystemOptions) obj;
        return compareTo(other) == 0;
    }

    /**
     * {@inheritDoc}
     *
     * @since 2.0
     */
    @Override
    public Object clone() {
        return new FileSystemOptions(new TreeMap<>(options));
    }

    @Override
    public String toString() {
        return options.toString();
    }
}
