package ca.ucalgary.services.util;

import java.io.File;
import java.io.IOException;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Iterator;
    
/**
 * Provides a facility to generate a temporary directory that can be automaticallly deleted on 
 * program exit.  Amazingly, no JDK facility to do this exists (only for files, not directories).
 *
 * This code is adapted from http://forum.java.sun.com/thread.jspa?threadID=470197&messageID=2169110
 * posted by Jean-Francois Briere (with permission).
 */
public class TempDir{
    private static DirDeleter deleterThread;
    
    static{
        deleterThread = new DirDeleter();
        Runtime.getRuntime().addShutdownHook(deleterThread);
    }
    
    /**
     * Creates a temp directory with a generated name (given a certain prefix) in a given directory.
     * The directory (and all its content) will be destroyed on exit, or when delete() is called.
     * If the directory passed in is null, the default temporary directory for Java will be used as
     * the parent directory for the newly created one.
     */    
    public static File createTempDir(String prefix, File directory) throws IOException{
        File tempFile = File.createTempFile(prefix, "", directory);
        if (!tempFile.delete())
            throw new IOException();
        if (!tempFile.mkdir())
            throw new IOException();
        deleterThread.add(tempFile);
        return tempFile;        
    }
    
    /**
     * Recursively destroys a directory and its contents.
     */ 
    public static void delete(File dir){
	File[] fileArray = dir.listFiles();
	
	if (fileArray != null){
	    for (int i = 0; i < fileArray.length; i++){
		if (fileArray[i].isDirectory()){
		    delete(fileArray[i]);
		}
		else if(fileArray[i].exists()){
		    fileArray[i].delete();
		}
	    }
	}
	dir.delete();
	// Tell the shutdown thread not to bother with deleting this one, we already did.
	deleterThread.remove(dir);
    }
}

/**
 * Helper class for TempDir that actually does the recursive deletion of directories
 * (since you can't just delete a non-empty directory).
 */
class DirDeleter extends Thread{
    private ArrayList<File> dirList = new ArrayList<File>();
    
    public synchronized void add(File dir){
	dirList.add(dir);
    }
    
    // Called at shutdown
    public void run(){
	synchronized (this){
	    for(File dir: dirList){
		TempDir.delete(dir);
	    }
	}
    }
    
    // To be called if the file was deleted manually during the course of running the program,
    // or you decide to keep it around after shutdown
    public synchronized void remove(File dir){
	dirList.remove(dir);
    }
}  //end DirDeleter inner class def
