 Fs          = require('fs')
 Path        = require('path')
 
+
+###
+    Delayer Class written by Godmar Back for CS 3214 Fall 2009
+    A Delayer object invokes a callback passed to the constructor
+    after the following two conditions are true:
+    - every function returned from a call to add() has been called
+    - the ready() method has been called.
+###
+
+class Delayer
+    constructor : (@cb) ->
+        @count = 0
+        @finalized = false
+
+    add : () ->
+        @count++
+        return () =>
+            @count--
+            if @count is 0 and @finalized then @cb()
+
+    ready : () ->
+        @finalized = true
+        if @count is 0 then @cb()
+
 class ApplicationManager
-    constructor : (paths) ->
+    constructor : (paths, @mountMultiple) ->
         @applications = {}
         @load paths if paths?
         @addDirectory "src/server/applications/admin_interface"
+        @delay = new Delayer(() => @mountMultiple(@applications))
 
     load : (paths) ->
-        #thisObj = this
         for path in paths
-            stats = Fs.lstatSync(path)
-            #Check for symlink
-            if stats.isFile()
-                @addFile path
-            else if stats.isDirectory()
-                @walk path, this, (appPath, thisObj) ->
-                    thisObj.addDirectory appPath
+            path = Path.resolve process.cwd(), path
+            Fs.lstat path, (err, stats) =>
+                throw err if err
+                throw new Error "Path " + path + " not found" if not stats
+                #Check for symlink
+                if stats.isFile()
+                    @addFile path
+                else if stats.isDirectory()
+                    @walk path
+                @delay.ready()
                 
     # Adds an html application to the application manager
     addFile : (path) ->

        if opts.authenticationInterface
            @addDirectory "src/server/applications/authentication_interface", opts.mountPoint + "/authenticate"
            @addDirectory "src/server/applications/password_reset", opts.mountPoint + "/password_reset"
            #@addDirectory "src/server/applications/landing_page", opts.mountPoint + "/landing_page"


    # Reads the configuration files app_config.json and deployment_config.json
    configure : (path) ->

        opts.entryPoint = path
        @add opts


    #Walks a path recursively and finds all CloudBrowser applications
    walk : (path) =>

        readDirDelay = @delay.add()

        friendlyLstat = (filename, cb) ->
            Fs.lstat filename, (err, stats) ->
                stats.filename = filename
                if err then cb err
                else cb err, stats

        statDirEntry = (filename) =>
            lstatDelay = @delay.add()
            friendlyLstat filename, (err, stats) =>
                if err then throw err
                if stats.isDirectory()
                    @walk stats.filename
                else if /app_config\.json$/.test stats.filename
                    @addDirectory path
                lstatDelay()

        Fs.readdir path, (err, list) =>
            if err then throw err
            for filename in list
                filename = Path.resolve path, filename
                statDirEntry filename
            readDirDelay()
                        

    # Configures and adds a CloudBrowser application to the application manager 
    addDirectory : (path, mountPoint) ->
