text: var util = require('util');
  var fs = require('../../util/fs');
  var path = require('path');
  var mout = require('mout');
  var Q = require('q');
  var junk = require('junk');
  var Resolver = require('./Resolver');
  var copy = require('../../util/copy');
  var extract = require('../../util/extract');
  var createError = require('../../util/createError');
  
  function FsResolver(decEndpoint, config, logger) {
      Resolver.call(this, decEndpoint, config, logger);
  
      // Ensure absolute path
      this._source = path.resolve(this._config.cwd, this._source);
  
      // If target was specified, simply reject the promise
      if (this._target !== '*') {
          throw createError('File system sources can\'t resolve targets', 'ENORESTARGET');
      }
  
      // If the name was guessed
      if (this._guessedName) {
          // Remove extension
          this._name = this._name.substr(0, this._name.length - path.extname(this._name).length);
      }
  }
  
  util.inherits(FsResolver, Resolver);
  mout.object.mixIn(FsResolver, Resolver);
  
  // -----------------
  
  FsResolver.isTargetable = function () {
      return false;
  };
  
  // TODO: Should we store latest mtimes in the resolution and compare?
  //       This would be beneficial when copying big files/folders
  
  // TODO: There's room for improvement by using streams if the source
  //       is an archive file, by piping read stream to the zip extractor
  //       This will likely increase the complexity of code but might worth it
  FsResolver.prototype._resolve = function () {
      return this._copy()
      .then(this._extract.bind(this))
      .then(this._rename.bind(this));
  };
  
  // -----------------
  
  FsResolver.prototype._copy = function () {
      var that = this;
  
      return Q.nfcall(fs.stat, this._source)
      .then(function (stat) {
          var dst;
          var copyOpts;
          var promise;
  
          that._sourceStat = stat;
          copyOpts = { mode: stat.mode };
  
          // If it's a folder
          if (stat.isDirectory()) {
              dst = that._tempDir;
  
              // Read the bower.json inside the folder, so that we
              // copy only the necessary files if it has ignore specified
              promise = that._readJson(that._source)
              .then(function (json) {
                  copyOpts.ignore = json.ignore;
                  return copy.copyDir(that._source, dst, copyOpts);
              })
              .then(function () {
                  // Resolve to null because it's a dir
  
              });
          // Else it's a file
          } else {
              dst = path.join(that._tempDir, path.basename(that._source));
              promise = copy.copyFile(that._source, dst, copyOpts)
              .then(function () {
                  return dst;
              });
          }
  
          that._logger.action('copy', that._source, {
              src: that._source,
              dst: dst
          });
  
          return promise;
      });
  };
  
  FsResolver.prototype._extract = function (file) {
      if (!file || !extract.canExtract(file)) {
          return Q.resolve();
      }
  
      this._logger.action('extract', path.basename(this._source), {
          archive: file,
          to: this._tempDir
      });
  
      return extract(file, this._tempDir);
  };
  
  FsResolver.prototype._rename = function () {
      return Q.nfcall(fs.readdir, this._tempDir)
      .then(function (files) {
          var file;
          var oldPath;
          var newPath;
  
          // Remove any OS specific files from the files array
          // before checking its length
          files = files.filter(junk.isnt);
  
          // Only rename if there's only one file and it's not the json
          if (files.length === 1 && !/^(bower|component)\.json$/.test(files[0])) {
              file = files[0];
              this._singleFile = 'index' + path.extname(file);
              oldPath = path.join(this._tempDir, file);
              newPath = path.join(this._tempDir, this._singleFile);
  
              return Q.nfcall(fs.rename, oldPath, newPath);
          }
      }.bind(this));
  };
  
  FsResolver.prototype._savePkgMeta = function (meta) {
      // Store main if is a single file
      if (this._singleFile) {
          meta.main = this._singleFile;
      }
  
      return Resolver.prototype._savePkgMeta.call(this, meta);
  };
  
  module.exports = FsResolver;
  