var fs = require('fs-extra');
var path = require('path');
var schemes = require('./schemes.js');
var semver = require('semver');

module.exports = {
  extractDependencies: function(dependencies) {
    var pkgs = [];
    Object.keys(dependencies || {}).forEach(function(k) {
      var expression = dependencies[k];
      var name = k, scheme, pos = expression.indexOf(':');
      if( ~pos ) {
        scheme = expression.substring(0, pos);
        expression = expression.substring(pos + 1);
      }
    
      scheme = scheme || schemes.default();
    
      // is version
      if( ~['*', 'latest'].indexOf(expression) ) {
        pkgs.push(scheme + ':' + k);
      } else if( semver.validRange(expression) ) {
        pkgs.push(scheme + ':' + k + '@' + expression);
      } else {
        pkgs.push(scheme + ':' + name + '[' + expression + ']');
      }
    });
    return pkgs;
  },
  parseExpression: function(expression) {
    var alias = (function() {
      var pos = expression.indexOf('[');
      if( ~pos ) return expression.substring(0, pos);
    })();
  
    if( alias ) {
      expression = (function() {
        expression = expression.substring(expression.indexOf('[') + 1)
        expression = expression.substring(0, expression.lastIndexOf(']'));
        return expression;
      })();
    }
  
    var scheme = (function() {
      if( alias && ~alias.indexOf(':') ) return alias.substring(0, alias.indexOf(':'));
      if( expression && ~expression.indexOf(':') ) return expression.substring(0, expression.indexOf(':'));
    })();
  
    if( alias && ~alias.indexOf(':') ) alias = alias.substring(alias.indexOf(':') + 1);
    if( expression && ~expression.indexOf(':') ) expression = expression.substring(expression.indexOf(':') + 1);
  
    return {
      scheme: scheme || schemes.default(),
      alias: alias,
      expression: expression
    }
  },
  extractPaths: (function() {
    var ignores = ['.', '..', 'npm-debug.log', '.DS_Store', '.git', '.gitignore', '.lock-wscript', '.hg', '.svn', 'CVS'];
    
    return function(basedir, excludes) {
      var dirs = [], files = [], excludes = excludes || [];
    
      function visit(dir, nomore) {
        var list = fs.readdirSync(dir);
        list.forEach(function(filename) {
          if( ~ignores.indexOf(filename) ) return;
          if( ~excludes.indexOf(filename) ) return;
          if( filename.startsWith('._') || filename.endsWith('.swp') || filename.endsWith('.log') || filename.startsWith('.wafpickle') ) return;
          
          var file = path.join(dir, filename);
          var stat = fs.statSync(file);
          if( stat.isDirectory() ) dirs.push(file.substring(basedir.length)), !nomore && visit(file, ~['node_modules', 'web_modules'].indexOf(filename));
          else if( stat.isFile() ) files.push(file.substring(basedir.length));
        });
      }
      
      visit(basedir);
      
      return {
        basedir: basedir,
        directories: dirs,
        files: files
      }
    }
  })(),
  visitSubPackages: function(basedir, listener) {
    var founds = [];
    
    function visit(dir) {
      function visitpkgs(subpkgdir) {
        if( fs.existsSync(subpkgdir) ) {
          var list = fs.readdirSync(subpkgdir);
          list.forEach(function(filename) {
            var pkgdir = path.join(subpkgdir, filename);
            var stat = fs.statSync(pkgdir);
            if( filename[0] === '.' || !stat.isDirectory() ) return;
            
            if( filename[0] === '@' ) {  // private npm
              fs.readdirSync(pkgdir).forEach(function(_filename) {
                var _pkgdir = path.join(pkgdir, _filename);
                founds.push(_pkgdir);
                listener && listener({
                  name: '@' + filename + '/' + _filename,
                  directory: _pkgdir,
                  parent: dir
                });
                visit(_pkgdir);
              });
            } else {
              founds.push(pkgdir);
              listener && listener({
                name: filename,
                directory: pkgdir,
                parent: dir
              });
              visit(pkgdir);
            }
          });
        }
      }
      
      visitpkgs(path.join(dir, 'node_modules'));
      visitpkgs(path.join(dir, 'web_modules'));
    }
    
    visit(basedir);
    return founds;
  }
};
@@ -123,16 +123,358 @@
 ver');%0A%0A
+function endsWith(str, word) %7B%0A  if( !str %7C%7C !word ) return false;%0A  if( str === word ) return true;%0A  var i = str.lastIndexOf(word);%0A  return i %3E 0 && i === str.length - word.length;%0A%7D%0A%0Afunction startsWith(str, word) %7B%0A  if( !str %7C%7C !word ) return false;%0A  if( str === word ) return true;%0A  return str.indexOf(word) === 0 ? true : false;%0A%7D%0A%0A
 module.e
@@ -2704,25 +2704,16 @@
     if( 
-filename.
 startsWi
@@ -2719,64 +2719,76 @@
 ith(
-'._') %7C%7C filename.endsWith('.swp') %7C%7C filename.endsWith(
+filename, '._') %7C%7C endsWith(filename, '.swp') %7C%7C endsWith(filename, 
 '.lo
@@ -2798,17 +2798,8 @@
  %7C%7C 
-filename.
 star
@@ -2805,16 +2805,26 @@
 rtsWith(
+filename, 
 '.wafpic

Fix supports old nodejs versions