/*
 * 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.sling.commons.jcr.file.internal;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.channels.FileChannel;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.AccessMode;
import java.nio.file.CopyOption;
import java.nio.file.DirectoryStream;
import java.nio.file.FileStore;
import java.nio.file.FileSystem;
import java.nio.file.LinkOption;
import java.nio.file.NoSuchFileException;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.FileAttributeView;
import java.nio.file.spi.FileSystemProvider;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;

import org.apache.sling.commons.jcr.file.JcrFileSupportService;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(
    service = FileSystemProvider.class,
    property = {
        Constants.SERVICE_DESCRIPTION + "=Apache Sling Commons JCR File System Provider",
        Constants.SERVICE_VENDOR + "=The Apache Software Foundation",
        "type=jcr"
    }
)
public class JcrFileSystemProvider extends FileSystemProvider {

    private final Map<Session, JcrFileSystem> cache = new HashMap<>();

    private final JcrFileStore jcrFileStore = new JcrFileStore();

    @Reference
    private volatile JcrFileSupportService jcrFileSupportService;

    private final Object lock = new Object();

    static final String SCHEME = "jcr";

    private final Logger logger = LoggerFactory.getLogger(JcrFileSystemProvider.class);

    public JcrFileSystemProvider() {
    }

    @Override
    public String getScheme() {
        logger.info("getting scheme");
        return SCHEME;
    }

    @Override
    public FileSystem newFileSystem(final URI uri, final Map<String, ?> env) throws IOException {
        logger.info("new file system: {}, {}", uri, env);

        if (!getScheme().equalsIgnoreCase(uri.getScheme())) {
            throw new IllegalArgumentException("URI scheme is not " + getScheme());
        }

        if (env == null) {
            throw new IllegalArgumentException("env is null");
        }

        if (!env.containsKey(Session.class.getName())) {
            throw new IllegalArgumentException("no session in env");
        }

        final Object object = env.get(Session.class.getName());
        if (object == null) {
            throw new IllegalArgumentException("session in env is null");
        }

        if (!(object instanceof Session)) {
            throw new IllegalArgumentException("session in env is not a " + Session.class.getName());
        }

        final Session session = (Session) object;
        if (!session.isLive()) {
            throw new IllegalArgumentException("session in env is not live");
        }

        synchronized (lock) {
            if (isInCache(session)) {
                throw new IllegalArgumentException("session is already in use");
            }
            final JcrFileSystem fileSystem = new JcrFileSystem(this, uri, session);
            putIntoCache(fileSystem);
            return fileSystem;
        }
    }

    @Override
    public FileSystem getFileSystem(final URI uri) {
        final String message = String.format("getting file system by URI is not supported: %s", uri.toString());
        logger.error(message);
        throw new UnsupportedOperationException(message);
    }

    @Override
    public Path getPath(final URI uri) {
        final String message = String.format("getting path by URI is not supported: %s", uri.toString());
        logger.error(message);
        throw new UnsupportedOperationException(message);
    }

    // TODO
    public FileChannel newFileChannel(Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs) throws IOException {
        logger.info("newFileChannel");
        try {
            final Node node = PathUtil.toNode(path);
            return new JcrFileChannel(node);
        } catch (Exception e) {
            throw new IOException(e);
        }
    }

    // TODO
    @Override
    public SeekableByteChannel newByteChannel(Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs) throws IOException {
        logger.info("newByteChannel");
        try {
            final Node node = PathUtil.toNode(path);
            return new JcrFileChannel(node);
        } catch (Exception e) {
            throw new IOException(e);
        }
    }

    @Override
    public DirectoryStream<Path> newDirectoryStream(final Path dir, final DirectoryStream.Filter<? super Path> filter) throws IOException {
        logger.info("new directory stream for {}", dir.toString());
        if (dir instanceof JcrPath) {
            return new JcrDirectoryStream((JcrPath) dir, filter);
        } else {
            throw new IllegalArgumentException("directory is not a JCR path");
        }
    }

    // TODO
    @Override
    public void createDirectory(Path dir, FileAttribute<?>... attrs) throws IOException {
        logger.info("createDirectory");
    }

    // TODO
    @Override
    public void delete(Path path) throws IOException {
        logger.info("delete: {}", path);
        final File file = path.toFile();
        if (!file.exists()) {
            throw new NoSuchFileException(path.toString());
        } else {
            // TODO delete
        }
    }

    // TODO
    @Override
    public void copy(Path source, Path target, CopyOption... options) throws IOException {
        logger.info("copy");
    }

    // TODO
    @Override
    public void move(Path source, Path target, CopyOption... options) throws IOException {
        logger.info("move");
    }

    // TODO
    @Override
    public boolean isSameFile(Path path, Path path2) throws IOException {
        logger.info("isSameFile");
        return false;
    }

    // TODO
    @Override
    public boolean isHidden(Path path) throws IOException {
        logger.info("isHidden");
        return false;
    }

    @Override
    public FileStore getFileStore(final Path path) throws IOException {
        logger.info("getting file store for {}", path.toString());
        return jcrFileStore;
    }

    // TODO
    @Override
    public void checkAccess(final Path path, final AccessMode... modes) throws IOException {
        logger.info("checking access: {}", path.toString());
    }

    // TODO
    @Override
    public <V extends FileAttributeView> V getFileAttributeView(final Path path, final Class<V> type, final LinkOption... options) {
        logger.info("getting file attribute view");
        return null;
    }

    // TODO
    @Override
    public <A extends BasicFileAttributes> A readAttributes(final Path path, final Class<A> type, final LinkOption... options) throws IOException {
        logger.info("reading attributes: {}, {}, {}", path, type, options);
        if (type == BasicFileAttributes.class) {
            final BasicFileAttributes basicFileAttributes = jcrFileSupportService.fromPath(path);
            logger.info("basic file attributes: {}", basicFileAttributes);
            return (A) basicFileAttributes;
        } else {
            throw new IOException("Unsupported file attributes type: " + type);
        }
    }

    // TODO
    @Override
    public Map<String, Object> readAttributes(Path path, String attributes, LinkOption... options) throws IOException {
        logger.info("readAttributes: {}, {}, {}", path, attributes, options);
        return Collections.emptyMap();
    }

    // TODO
    @Override
    public void setAttribute(Path path, String attribute, Object value, LinkOption... options) throws IOException {
        logger.info("setAttribute");
    }

    boolean isFile(final Node node) throws RepositoryException {
        return jcrFileSupportService.isFile(node);
    }

    boolean isDirectory(final Node node) throws RepositoryException {
        return jcrFileSupportService.isDirectory(node);
    }

    boolean isInCache(final Session session) {
        return cache.containsKey(session);
    }

    void putIntoCache(final JcrFileSystem fileSystem) {
        cache.put(fileSystem.getSession(), fileSystem);
    }

    void removeFromCache(final JcrFileSystem fileSystem) {
        cache.remove(fileSystem.getSession());
    }

}
