/*
 * 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.vfs.provider.ram;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.vfs.FileName;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemOptions;
import org.apache.commons.vfs.FileType;
import org.apache.commons.vfs.provider.AbstractFileSystem;

/**
 * A RAM File System.
 * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
 */
public class RamFileSystem extends AbstractFileSystem implements Serializable
{
    /**
     * Cache of RAM File Data
     */
    private final Map cache;

    /**
     * @param rootName The root file name.
     * @param fileSystemOptions The FileSystem options.
     */
    protected RamFileSystem(FileName rootName,
            FileSystemOptions fileSystemOptions)
    {
        super(rootName, null, fileSystemOptions);
        this.cache = Collections.synchronizedMap(new HashMap());
        // create root
        RamFileData rootData = new RamFileData(rootName);
        rootData.setType(FileType.FOLDER);
        rootData.setLastModified(System.currentTimeMillis());
        this.cache.put(rootName, rootData);
    }

    /*
     * (non-Javadoc)
     *
     * @see org.apache.commons.vfs.provider.AbstractFileSystem#createFile(org.apache.commons.vfs.FileName)
     */
    protected FileObject createFile(FileName name) throws Exception
    {
        RamFileObject file = new RamFileObject(name, this);
        return file;
    }

    /*
     * (non-Javadoc)
     *
     * @see org.apache.commons.vfs.provider.AbstractFileSystem#addCapabilities(java.util.Collection)
     */
    protected void addCapabilities(Collection caps)
    {
        caps.addAll(RamFileProvider.capabilities);
    }

    /**
     * @param name The name of the file.
     * @return children The names of the children.
     */
    String[] listChildren(FileName name)
    {
        RamFileData data = (RamFileData) this.cache.get(name);
        if (data == null || !data.getType().hasChildren())
        {
            return null;
        }
        Collection children = data.getChildren();
        String[] names;

        synchronized(children) {
            names = new String[children.size()];

            int pos = 0;
            Iterator iter = children.iterator();
            while (iter.hasNext())
            {
                RamFileData childData = (RamFileData) iter.next();
                names[pos] = childData.getName().getBaseName();
                pos++;
            }
        }

        return names;
    }

    /**
     * Delete a file
     *
     * @param file
     * @throws FileSystemException
     */
    void delete(RamFileObject file) throws FileSystemException
    {
        // root is read only check
        if (file.getParent() == null)
        {
            throw new FileSystemException("unable to delete root");
        }

        // Remove reference from cache
        this.cache.remove(file.getName());
        // Notify the parent
        RamFileObject parent = (RamFileObject) this.resolveFile(file
                .getParent().getName());
        parent.getData().removeChild(file.getData());
        parent.close();
        // Close the file
        file.getData().clear();
        file.close();
    }

    /**
     * Saves a file
     *
     * @param file
     * @throws FileSystemException
     */
    void save(final RamFileObject file) throws FileSystemException
    {

        // Validate name
        if (file.getData().getName() == null)
        {
            throw new FileSystemException(new IllegalStateException(
                    "The data has no name. " + file));
        }

        // Add to the parent
        if (file.getName().getDepth() > 0)
        {
            RamFileData parentData = (RamFileData) this.cache.get(file
                    .getParent().getName());
            // Only if not already added
            if (!parentData.hasChildren(file.getData()))
            {
                RamFileObject parent = (RamFileObject) file.getParent();
                parent.getData().addChild(file.getData());
                parent.close();
            }
        }
        // Store in cache
        cache.put(file.getName(), file.getData());
        file.getData().updateLastModified();
        file.close();
    }

    /**
     * @param from The original file.
     * @param to The new file.
     * @throws FileSystemException if an error occurs.
     */
    void rename(RamFileObject from, RamFileObject to)
            throws FileSystemException
    {
        if (!this.cache.containsKey(from.getName()))
        {
            throw new FileSystemException("File does not exist: "
                    + from.getName());
        }
        // Copy data

        to.getData().setBuffer(from.getData().getBuffer());
        to.getData().setLastModified(from.getData().getLastModified());
        to.getData().setType(from.getData().getType());

        this.save(to);
        this.delete(from);
    }

    public void attach(RamFileObject fo)
    {
        if (fo.getName() == null)
        {
            throw new IllegalArgumentException("Null argument");
        }
        RamFileData data = (RamFileData) this.cache.get(fo.getName());
        if (data == null)
        {
            data = new RamFileData(fo.getName());
        }
        fo.setData(data);
    }

    /**
     * Import a Tree.
     *
     * @param file The File
     * @throws FileSystemException if an error occurs.
     */
    public void importTree(File file) throws FileSystemException
    {
        FileObject fileFo = getFileSystemManager().toFileObject(file);
        this.toRamFileObject(fileFo, fileFo);
    }

    /**
     * Import the given file with the name relative to the given root
     *
     * @param fo
     * @param root
     * @throws FileSystemException
     */
    void toRamFileObject(FileObject fo, FileObject root)
            throws FileSystemException
    {
        RamFileObject memFo = (RamFileObject) this.resolveFile(fo.getName()
                .getPath().substring(root.getName().getPath().length()));
        if (fo.getType().hasChildren())
        {
            // Create Folder
            memFo.createFolder();
            // Import recursively
            FileObject[] fos = fo.getChildren();
            for (int i = 0; i < fos.length; i++)
            {
                FileObject child = fos[i];
                this.toRamFileObject(child, root);
            }
        }
        else if (fo.getType().equals(FileType.FILE))
        {
            // Read bytes
            try
            {
                InputStream is = fo.getContent().getInputStream();
                try
                {
                    OutputStream os = new BufferedOutputStream(memFo
                            .getOutputStream(), 512);
                    int i;
                    while ((i = is.read()) != -1)
                    {
                        os.write(i);
                    }
                    os.flush();
                    os.close();
                }
                finally
                {
                    try
                    {
                        is.close();
                    }
                    catch (IOException e)
                    {
                        // ignore on close exception
                    }
                }
            }
            catch (IOException e)
            {
                throw new FileSystemException(e.getClass().getName() + " "
                        + e.getMessage());
            }
        }
        else
        {
            throw new FileSystemException("File is not a folder nor a file "
                    + memFo);
        }
    }

    /**
     * @return Returns the size of the FileSystem
     */
    int size()
    {
        int size = 0;
        synchronized(cache) {
            Iterator iter = cache.values().iterator();
            while (iter.hasNext())
            {
                RamFileData data = (RamFileData) iter.next();
                size += data.size();
            }
        }
        return size;
    }

    /**
     * Close the RAMFileSystem.
     */
    public void close()
    {
        this.cache.clear();
        super.close();
    }
}
