/*
 * 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.jci.monitor;

import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Implementation of a FilesystemAlterationObserver
 * 
 * @author tcurdt
 */
public class FilesystemAlterationObserverImpl implements FilesystemAlterationObserver {

    private final Log log = LogFactory.getLog(FilesystemAlterationObserverImpl.class);
    
    private interface MonitorFile {

        long lastModified();
        MonitorFile[] listFiles();
        boolean isDirectory();
        boolean exists();
        String getName();

    }
    
    private final static class MonitorFileImpl implements MonitorFile {

        private final File file;

        public MonitorFileImpl( final File pFile ) {
            file = pFile;
        }

        public boolean exists() {
            return file.exists();
        }

        public MonitorFile[] listFiles() {
            final File[] childs = file.listFiles();

            final MonitorFile[] providers = new MonitorFile[childs.length];
            for (int i = 0; i < providers.length; i++) {
                providers[i] = new MonitorFileImpl(childs[i]);
            }
            return providers;
        }

        public String getName() {
            return file.getName();
        }

        public boolean isDirectory() {
            return file.isDirectory();
        }

        public long lastModified() {
            return file.lastModified();
        }

        public String toString() {
            return file.toString();
        }

    }

    private final class Entry {

        private final static int TYPE_UNKNOWN = 0;
        private final static int TYPE_FILE = 1;
        private final static int TYPE_DIRECTORY = 2;

        private final MonitorFile file;
        private long lastModified = -1;
        private int lastType = TYPE_UNKNOWN;
        private Map<String, Entry> childs = new HashMap<String, Entry>();

        public Entry(final MonitorFile pFile) {
            file = pFile;
        }

        public String getName() {
            return file.getName();
        }
        
        
        public String toString() {
            return file.toString();
        }


        private void compareChilds() {
            if (!file.isDirectory()) {
                return;
            }

            final MonitorFile[] files = file.listFiles();
            final Set<Entry> deleted = new HashSet<Entry>(childs.values());
            for (MonitorFile f : files) {
                final String name = f.getName();
                final Entry entry = (Entry)childs.get(name);
                if (entry != null) {
                    // already recognized as child
                    deleted.remove(entry);

                    if(entry.needsToBeDeleted()) {
                        // we have to delete this one
                        childs.remove(name);
                    }
                } else {
                    // a new child
                    final Entry newChild = new Entry(f);
                    childs.put(name, newChild);
                    newChild.needsToBeDeleted();
                }
            }

            // the ones not found on disk anymore

            for (Entry entry : deleted) {
                entry.deleteChildsAndNotify();
                childs.remove(entry.getName());
            }
        }


        private void deleteChildsAndNotify() {
            for (Entry entry : childs.values()) {
                entry.deleteChildsAndNotify();
            }
            childs.clear();

            if(lastType == TYPE_DIRECTORY) {
                notifyOnDirectoryDelete(this);
            } else if (lastType == TYPE_FILE) {
                notifyOnFileDelete(this);
            }
        }

        public boolean needsToBeDeleted() {

            if (!file.exists()) {
                // deleted or has never existed yet

//                log.debug(file + " does not exist or has been deleted");

                deleteChildsAndNotify();

                // mark to be deleted by parent
                return true;
            } else {
                // exists
                final long currentModified = file.lastModified(); 

                if (currentModified != lastModified) {
                    // last modified has changed
                    lastModified = currentModified;

//                    log.debug(file + " has new last modified");

                    // types only changes when also the last modified changes
                    final int newType = (file.isDirectory()?TYPE_DIRECTORY:TYPE_FILE); 

                    if (lastType != newType) {
                        // the type has changed

//                        log.debug(file + " has a new type");

                        deleteChildsAndNotify();

                        lastType = newType;

                        // and then an add as the new type

                        if (newType == TYPE_DIRECTORY) {
                            notifyOnDirectoryCreate(this);
                            compareChilds();
                        } else {
                            notifyOnFileCreate(this);
                        }

                        return false;
                    }

                    if (newType == TYPE_DIRECTORY) {
                        notifyOnDirectoryChange(this);
                        compareChilds();
                    } else {
                        notifyOnFileChange(this);
                    }

                    return false;

                } else {

                    // so exists and has not changed

//                    log.debug(file + " does exist and has not changed");

                    compareChilds();

                    return false;
                }
            }
        }
        
        public MonitorFile getFile() {
            return file;
        }

        public void markNotChanged() {
            lastModified = file.lastModified();
        }

    }

    private final File rootDirectory;
    private final Entry rootEntry;

    private FilesystemAlterationListener[] listeners = new FilesystemAlterationListener[0];
    private Set<FilesystemAlterationListener> listenersSet = new HashSet<FilesystemAlterationListener>();

    public FilesystemAlterationObserverImpl( final File pRootDirectory ) {
        rootDirectory = pRootDirectory;
        rootEntry = new Entry(new MonitorFileImpl(pRootDirectory));
    }



    private void notifyOnStart() {
        log.debug("onStart " + rootEntry);
        for (FilesystemAlterationListener listener : listeners) {
            listener.onStart(this);
        }
    }
    private void notifyOnStop() {
        log.debug("onStop " + rootEntry);
        for (FilesystemAlterationListener listener : listeners) {
            listener.onStop(this);
        }
    }

    private void notifyOnFileCreate( final Entry pEntry ) {
        log.debug("onFileCreate " + pEntry);
        for (FilesystemAlterationListener listener : listeners) {
            listener.onFileCreate(((MonitorFileImpl)pEntry.getFile()).file );
        }
    }
    private void notifyOnFileChange( final Entry pEntry ) {
        log.debug("onFileChange " + pEntry);
        for (FilesystemAlterationListener listener : listeners) {
            listener.onFileChange(((MonitorFileImpl)pEntry.getFile()).file );
        }
    }
    private void notifyOnFileDelete( final Entry pEntry ) {
        log.debug("onFileDelete " + pEntry);
        for (FilesystemAlterationListener listener : listeners) {
            listener.onFileDelete(((MonitorFileImpl)pEntry.getFile()).file );
        }
    }

    private void notifyOnDirectoryCreate( final Entry pEntry ) {
        log.debug("onDirectoryCreate " + pEntry);
        for (FilesystemAlterationListener listener : listeners) {
            listener.onDirectoryCreate(((MonitorFileImpl)pEntry.getFile()).file );
        }
    }
    private void notifyOnDirectoryChange( final Entry pEntry ) {
        log.debug("onDirectoryChange " + pEntry);
        for (FilesystemAlterationListener listener : listeners) {
            listener.onDirectoryChange(((MonitorFileImpl)pEntry.getFile()).file );
        }
    }
    private void notifyOnDirectoryDelete( final Entry pEntry ) {
        log.debug("onDirectoryDelete " + pEntry);
        for (FilesystemAlterationListener listener : listeners) {
            listener.onDirectoryDelete(((MonitorFileImpl)pEntry.getFile()).file );
        }
    }


    private void checkEntries() {
        if(rootEntry.needsToBeDeleted()) {
            // root not existing
            rootEntry.lastType = Entry.TYPE_UNKNOWN;
        }
    }

    
    public void checkAndNotify() {
    	synchronized(listenersSet) {
	        if (listeners.length == 0) {
	            return;
	        }
	
	        notifyOnStart();
	        
	        checkEntries();
	        
	        notifyOnStop();
    	}
    }

    
    public File getRootDirectory() {
        return rootDirectory;
    }

    public void addListener( final FilesystemAlterationListener pListener ) {
    	synchronized(listenersSet) {
	        if (listenersSet.add(pListener)) {
	            listeners = createArrayFromSet();
	        }
    	}
    }

    public void removeListener( final FilesystemAlterationListener pListener ) {
    	synchronized(listenersSet) {
	        if (listenersSet.remove(pListener)) {
	            listeners = createArrayFromSet();
	        }
    	}
    }

    private FilesystemAlterationListener[] createArrayFromSet() {
        final FilesystemAlterationListener[] newListeners = new FilesystemAlterationListener[listenersSet.size()];
        listenersSet.toArray(newListeners);
        return newListeners;
    }

    public FilesystemAlterationListener[] getListeners() {
    	synchronized(listenersSet) {
        	final FilesystemAlterationListener[] res = new FilesystemAlterationListener[listeners.length];
        	System.arraycopy(listeners, 0, res, 0, res.length);
            return res;
    	}    	
    }

    /*
     
    public static void main( String[] args ) {
        final FilesystemAlterationObserverImpl observer = new FilesystemAlterationObserverImpl(new File(args[0]));
        while(true) {
            observer.checkEntries();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
            }
        }
    }

    */
}
