/*
 * @(#)DirectoryMonitor.java
 *
 * Copyright (c) 2002-2003 JSCAPE
 * 1147 S. 53rd Pl., Mesa, Arizona, 85206, U.S.A.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * JSCAPE. ("Confidential Information").  You shall not disclose such
 * Confidential Information and shall use it only in accordance with
 * the terms of the license agreement you entered into with JSCAPE.
 */

package com.jscape.file;

import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * Monitors one or more directories for changes such as added files, removed files and changed files.
 */
public class DirectoryMonitor {

    /**
     * Variable to check whether monitor is running or not.
     */
    private boolean running = false;
    /**
     * Thread for the monitor.
     */
    private DirectoryMonitorThread monitor;
    /**
     * Monitor locations.
     */
    private File[] dirs;
    /**
     * Monitor delay.
     */
    private int delay;

    /**
     * Creates a new DirectoryMonitor instance.
     *
     * @param dirs  the directories to monitor
     * @param delay the frequency in seconds to check directories
     */
    public DirectoryMonitor(final File[] dirs, final int delay) {
        this.dirs = dirs;
        this.delay = delay;
    }

    /**
     * Starts this <code>DirectoryMonitor</code>.
     */
    public void start() {
        synchronized (this) {
            if (!running) {
                monitor = new DirectoryMonitorThread();
                monitor.start();
            }
        }
    }

    /**
     * Stops this <code>DirectoryMonitor</code>.
     */
    public void stop() {
        running = false;
    }

    /**
     * Thread for monitoring directories.
     */
    class DirectoryMonitorThread
            extends Thread {

        /**
         * Current files.
         */
        private Map[] currFiles = new HashMap[dirs.length];
        /**
         * Previous files.
         */
        private Map[] prevFiles = new HashMap[dirs.length];
        /**
         * Previous file dates.
         */
        private Map[] prevFileDates = new HashMap[dirs.length];

        /**
         * Process for checking directories.
         */
        @SuppressWarnings("unchecked")
        public void run() {
            running = true;

            for (int z = 0; z < dirs.length; ++z) {
                currFiles[z] = new HashMap();
                prevFiles[z] = new HashMap();
                prevFileDates[z] = new HashMap();
            }

            while (true) {
                System.out.println("Checking dir");

                // check all directories
                for (int w = 0; w < dirs.length; ++w) {

                    File[] files = dirs[w].listFiles();

                    // clear current files for directory
                    currFiles[w].clear();

                    // build up current files in each directory
                    if (files != null) {
                        for (int f = 0; f < files.length; ++f) {
                            if (files[f].isFile()) {
                                currFiles[w].put(files[f].getName(), files[f]);
                            }
                        }
                    }

                    // check if new files added
                    Iterator current = currFiles[w].keySet().iterator();
                    while (current.hasNext()) {
                        String name = (String) current.next();
                        if (!prevFiles[w].containsKey(name)) {
                            System.out.println("New file added");
                        }
                    }

                    // check if files removed or changed
                    Iterator previous = prevFiles[w].keySet().iterator();
                    while (previous.hasNext()) {
                        String name = (String) previous.next();
                        if (!currFiles[w].containsKey(name)) {
                            System.out.println("File removed");
                        } else {
                            File currFile = (File) currFiles[w].get(name);
                            Long prevTimestamp =
                                    (Long) prevFileDates[w].get(name);
                            if (prevTimestamp.longValue()
                                    != currFile.lastModified()) {
                                System.out.println("File changed");
                            }
                        }
                    }

                    // store current data
                    prevFiles[w].clear();
                    prevFiles[w].putAll(currFiles[w]);

                    // update timestamps
                    prevFileDates[w].clear();
                    Iterator currKeys = currFiles[w].keySet().iterator();
                    while (currKeys.hasNext()) {
                        String key = (String) currKeys.next();
                        File currFile = (File) currFiles[w].get(key);
                        prevFileDates[w].put(key, currFile.lastModified());
                    }

                } // end dirs loop

                try {
                    Thread.sleep(delay);
                } catch (InterruptedException ioe) {
                    ioe.printStackTrace();
                }

            } // end thread loop
        }
    }

}
