// Exports a Bundles singleton

var Datastore = require('nedb'),
    Parser = require('./parser.js'),
    events = require('events'),
    watcher = require('./watcher.js'),
    fs = require('fs'),
    db = new Datastore({ filename: 'db/bundles.db', autoload: true }),
    Q = require('Q');

// Using a unique constraint with the bundle name
db.ensureIndex({ fieldName: 'name', unique: true }, function (err) {});

// Used in the "watcher" listener. Couldn't think of a cleaner way of doing it.
var self = {};

function Bundles() {
    self = this;

    // Do an initial scan of the bundles dir
    var bundlesDir = fs.readdirSync('bundles/');

    bundlesDir.forEach(function(bndlName) {
        // Skip if nodecg.json doesn't exist
        var bndlPath = 'bundles/' + bndlName + '/';
        if (!fs.existsSync(bndlPath + "nodecg.json")) {
            return;
        }

        var bundle = Parser.parse(bndlName);
        self.add(bundle);
    });

    // Remove any entries that are no longer present on disk
    self.all()
        .then(function (bundles) {
            bundles.forEach(function(bundle) {
                var bndlPath = 'bundles/' + bundle.name + '/';
                if (!fs.existsSync(bndlPath + "nodecg.json")) {
                    console.log('[lib/bundle/index.js] ' + bundle.name + '\'s nodecg.json can no longer be found on disk, assuming the bundle has been deleted or moved');
                    self.remove(bundle.name);
                }
            });
        }, function (reason) {
            console.log('[lib/bundle/index.js] Failed bundle DB init integrity scan: ' + reason);
        });

}

Bundles.prototype.all = function() {
    // Find all bundles in the datastore
    var deferred = Q.defer();
    db.find({}, function (err, docs) {
        if (err) {
            deferred.reject(new Error(err));
        } else {
            deferred.resolve(docs);
        }
    });
    return deferred.promise;
};

Bundles.prototype.find = function(name) {
    // Find a bundle by name
    var deferred = Q.defer();
    db.findOne({ name: name }, function (err, doc) {
        if (err) {
            deferred.reject(new Error(err));
        } else {
            deferred.resolve(doc);
        }
    });
    return deferred.promise;
};

Bundles.prototype.add = function(bundle) {
    // Upserting the bundle
    db.update({ name: bundle.name }, bundle, { upsert: true }, function (err, numReplaced, upsert) {
        if (upsert) {
            console.log('[lib/bundle/index.js] Added ' + bundle.name + ' to DB');
        } else {
            console.log('[lib/bundle/index.js] Updated ' + bundle.name + '\'s DB entry');
        }
    });
};

Bundles.prototype.remove = function(bundlename) {
    // options set to {} since the default for multi is false
    db.remove({ name: bundlename }, {}, function (err, numRemoved) {
        console.log('[lib/bundle/index.js] ' + bundlename + ' has been removed from the DB');
    });
};

watcher.on('bundleChanged', function (name) {
    var bundle = Parser.parse(name);

    // If nodecg.json is missing from the bundle dir, bundle will equal false
    if (bundle) {
        console.log('[lib/bundle/index.js] ' + name + ' was changed, and has been reloaded from disk');
        self.add(bundle);
    } else {
        console.log('[lib/bundle/index.js] ' + name + '\'s nodecg.json can no longer be found on disk, assuming the bundle has been deleted or moved');
        self.remove(name);
    }
});

module.exports = exports = new Bundles();
@@ -278,17 +278,17 @@
 equire('
-Q
+q
 ');%0A%0A// 

Fix "Q" dependency on linux (case-sensitive 'require')