var copy = require('shallow-copy');
var glob = require('glob');
var uniq = require('nub');
var path = require('path');
var shasum = require('shasum');
var fs = require('fs');

module.exports = function (bundle, opts, cb) {
    var keypaths = opts.keys || opts.key || opts.k;
    if (!keypaths) keypaths = [];
    if (!Array.isArray()) keypaths = [ keypaths ];
    var defaults = opts.defaults || opts.d || {};
    
    var files = {};
    var packages = {};
    var dependencies = {};
    
    var pkgCount = {};
    var pkgFiles = {};
    var pending = 1;
    
    bundle.on('dep', function (dep) {
        var files = values(dep.deps || {});
        if (files.length === 0) return;
        var deps = {};
        files.forEach(function (file) { deps[file] = true });
        dependencies[dep.id] = deps;
    });
    
    bundle.on('package', function (file, pkg) {
        if (!pkg) pkg = {};
        var dir = path.dirname(file);
        if (!pkg.__dirname) pkg.__dirname = dir;
        var pkgid = shasum(pkg);
        packages[pkgid] = pkg;
        pkgCount[pkgid] = 0;
        pkgFiles[file] = pkgid;
        
        var globs = getKeys(keypaths, defaults, copy(pkg));
        if (typeof globs === 'string') globs = [ globs ];
        if (!globs) globs = [];
        pending ++;
        
        (function next () {
            if (globs.length === 0) return done();
            
            var gfile = path.resolve(dir, globs.shift());
            glob(gfile, function (err, exp) {
                if (err) return cb(err);
                
                exp.forEach(function (file) {
                    files[file] = pkgid;
                    pkgCount[pkgid] ++;
                });
                next();
            });
        })();
    });
    
    bundle.on('bundle', function (stream) {
        stream.on('end', done);
    });
    
    function done () {
        if (-- pending !== 0) return;
        var result = {
            packages: Object.keys(packages).reduce(function (acc, key) {
                if (pkgCount[key] > 0) acc[key] = packages[key];
                return acc;
            }, {}),
            assets: files,
            dependencies: Object.keys(dependencies).reduce(depReducer, {})
        };
        if (cb) cb(null, result);
        
        var outfile = opts.o || opts.outfile;
        if (outfile) fs.writeFile(outfile, JSON.stringify(result, null, 2));
    }
    
    function depReducer (acc, file) {
        var deps = Object.keys(dependencies[file]);
        var pkgid = pkgFiles[file];
        
        acc[pkgid] = deps
            .map(function (id) {
                if (pkgid === pkgFiles[id]) return null;
                var did = pkgFiles[id];
                if (pkgCount[did] === 0) return false;
                return pkgFiles[id];
            })
            .filter(Boolean)
        ;
        return acc;
    }
};

function getKeys (keys, defaults, pkg) {
    return uniq(keys.concat(Object.keys(defaults))).map(function (key) {
        var cur = pkg, curDef = defaults;
        if (typeof key === 'string' && /\./.test(key)) {
            key = key.split('.');
        }
        
        if (Array.isArray(key)) {
            for (var i = 0; i < key.length - 1; i++) {
                cur = cur && cur[key[i]];
                curDef = curDef && curDef[key[i]];
            }
            key = key[i];
        }
        return (cur && cur[key]) || (curDef && curDef[key]);
    }).filter(Boolean);
}

function values (obj) {
    return Object.keys(obj).map(function (key) { return obj[key] });
}

@@ -979,41 +979,8 @@
 ir;%0A
-        var pkgid = shasum(pkg);%0A
     
@@ -992,21 +992,19 @@
 ackages%5B
-pkgid
+dir
 %5D = pkg;
@@ -1021,21 +1021,19 @@
 kgCount%5B
-pkgid
+dir
 %5D = 0;%0A 
@@ -1048,37 +1048,35 @@
 kgFiles%5Bfile%5D = 
-pkgid
+dir
 ;%0A        %0A     
@@ -1583,21 +1583,19 @@
 file%5D = 
-pkgid
+dir
 ;%0A      
@@ -1617,21 +1617,19 @@
 kgCount%5B
-pkgid
+dir
 %5D ++;%0A  
@@ -1855,32 +1855,41 @@
  !== 0) return;%0A
+        %0A
         var resu
@@ -1961,23 +1961,56 @@
 n (acc, 
-key
+dir
 ) %7B%0A
+                var pkgid = dir;%0A
         
@@ -2030,19 +2030,19 @@
 kgCount%5B
-key
+dir
 %5D %3E 0) a
@@ -2044,19 +2044,21 @@
  0) acc%5B
-key
+pkgid
 %5D = pack
@@ -2062,19 +2062,19 @@
 ackages%5B
-key
+dir
 %5D;%0A     
@@ -2508,21 +2508,19 @@
     var 
-pkgid
+dir
  = pkgFi
@@ -2530,16 +2530,41 @@
 %5Bfile%5D;%0A
+        var pkgid = dir;%0A
         

index based on directories in preparation for dependency indexing