// Generated by CoffeeScript 1.10.0
var File, fs, nodefn, path, semver,
  bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

fs = require('graceful-fs');

path = require('path');

nodefn = require('when/node');

semver = require('semver');

File = (function() {

  /**
   * @class
   * @name File
   * @param {String} path The path to the file. This will be resolved to an
     absolute path, so even if you change your cwd you can still access the same
     file.
   * @param {String} [options.base=./] Used for relative pathing. This will not
     be resolved to an absolute path. Typically where a glob starts.
   */
  function File(path1, options) {
    var ref;
    this.path = path1;
    if (options == null) {
      options = {};
    }
    this._processOptionsObject = bind(this._processOptionsObject, this);
    this.dirname = bind(this.dirname, this);
    this.extname = bind(this.extname, this);
    this.stat = bind(this.stat, this);
    this.unlink = bind(this.unlink, this);
    this.rename = bind(this.rename, this);
    this.append = bind(this.append, this);
    this.write = bind(this.write, this);
    this.read = bind(this.read, this);
    this._resolvePaths = bind(this._resolvePaths, this);
    this.base = (ref = options.base) != null ? ref : './';
    this._resolvePaths();
  }


  /**
   * Normalize & resolve paths. Call if the File.path changes
   * @function
   * @name _resolvePaths
   * @private
   */

  File.prototype._resolvePaths = function() {
    this.path = path.resolve(this.base, this.path);
    return this.relative = path.relative(this.base, this.path);
  };


  /**
   * Read from the file
   * @function
   * @name read
   * @param {String|null} [options.encoding=null]
   * @param {String} [options.flag='r']
   * @return {Promise}
   */

  File.prototype.read = function(options) {
    if (options == null) {
      options = {};
    }
    return nodefn.call(fs.readFile, this.path, this._processOptionsObject(options));
  };


  /**
   * Write `data` to the file
   * @function
   * @name write
   * @param {String|Buffer} data
   * @param {String|null} [options.encoding='utf8'] ignored if data is a
     buffer
   * @param {Number} [options.mode=438] default is 0666 in Octal
   * @param {String} [options.flag='w']
   * @return {Promise}
   */

  File.prototype.write = function(data, options) {
    if (options == null) {
      options = {};
    }
    return nodefn.call(fs.writeFile, this.path, data, this._processOptionsObject(options));
  };


  /**
   * Append `data` to the file
   * @function
   * @name append
   * @param {String|Buffer} data
   * @param {String|null} [options.encoding='utf8'] ignored if data is a
     buffer
   * @param {Number} [options.mode=438] default is 0666 in Octal
   * @param {String} [options.flag='w']
   * @return {Promise}
   */

  File.prototype.append = function(data, options) {
    if (options == null) {
      options = {};
    }
    return nodefn.call(fs.appendFile, this.path, data, this._processOptionsObject(options));
  };


  /**
   * Rename the file
   * @function
   * @name rename
   * @param {String} newPath The new path for the file. Will be resolved
     relative to File.base.
   * @return {Promise}
   */

  File.prototype.rename = function(newPath) {
    newPath = path.resolve(this.base, newPath);
    return nodefn.call(fs.rename, this.path, newPath).then((function(_this) {
      return function() {
        _this.path = newPath;
        return _this._resolvePaths();
      };
    })(this));
  };


  /**
   * Delete the file
   * @function
   * @name unlink
   * @return {Promise}
   */

  File.prototype.unlink = function() {
    return nodefn.call(fs.unlink, this.path);
  };


  /**
   * Return a Stat object for the file
   * @function
   * @name stat
   * @return {Promise}
   */

  File.prototype.stat = function() {
    return nodefn.call(fs.stat, this.path);
  };


  /**
   * Get the extension of a file
   * @function
   * @name extname
   * @return {String}
   */

  File.prototype.extname = function() {
    return path.extname(this.path);
  };


  /**
   * Get the dirname of the file
   * @function
   * @name dirname
   * @return {String}
   */

  File.prototype.dirname = function() {
    return path.dirname(this.path);
  };


  /**
   * Determine if we're using the new version of the FS API that supports an
     options object.
   * @return {Boolean} True if the version is >= 0.10.0 (when the options object
     was introduced).
   */

  File.prototype._isOptionsObjectSupported = function() {
    return semver.gte(process.version, '0.10.0');
  };


  /**
   * The pre-v0.10.0 fs functions took a encoding parameter and no options
     object. This function deals with that difference.
   * @param {[type]} options [description]
   */

  File.prototype._processOptionsObject = function(options) {
    var length, optionNames;
    if (this._isOptionsObjectSupported()) {
      return options;
    } else {
      optionNames = Object.keys(options);
      length = optionNames.length;
      if (length === 0 || (length === 1 && optionNames[0] === 'encoding')) {
        return options.encoding;
      } else {
        throw new Error("Node version <= 0.10.0 only supports an encoding option. Called with " + (optionNames.join()));
      }
    }
  };

  return File;

})();

module.exports = File;
