// Generated by CoffeeScript 1.9.2
(function() {
  var clone, falafel, fs, isRootDir, loadConfig, merge, path, skipFile, through;

  path = require('path');

  fs = require('fs');

  through = require('through');

  falafel = require('falafel');

  loadConfig = require('./loadConfig');

  skipFile = require('./skipFile');

  exports.loadTransformConfig = loadConfig.loadTransformConfig;

  exports.loadTransformConfigSync = loadConfig.loadTransformConfigSync;

  exports.skipFile = skipFile;

  isRootDir = function(filename) {
    return filename === path.resolve(filename, '/');
  };

  merge = function(a, b) {
    var answer, key;
    if (a == null) {
      a = {};
    }
    if (b == null) {
      b = {};
    }
    answer = {};
    for (key in a) {
      answer[key] = a[key];
    }
    for (key in b) {
      answer[key] = b[key];
    }
    return answer;
  };

  clone = function(a) {
    var answer, key;
    if (!a) {
      return a;
    }
    answer = {};
    for (key in a) {
      answer[key] = a[key];
    }
    return answer;
  };

  exports.makeStringTransform = function(transformName, options, transformFn) {
    var transform;
    if (options == null) {
      options = {};
    }
    if (transformFn == null) {
      transformFn = options;
      options = {};
    }
    transform = function(file, config) {
      var configData, content, end, ref, write;
      configData = transform.configData != null ? transform.configData : loadConfig.loadTransformConfigSync(transformName, file, options);
      if (config != null) {
        configData = (ref = clone(configData)) != null ? ref : {
          config: {}
        };
        configData.config = merge(configData.config, config);
        if (configData.config.appliesTo) {
          configData.appliesTo = configData.config.appliesTo;
          delete configData.config.appliesTo;
        }
      }
      if (skipFile(file, configData, options)) {
        return through();
      }
      content = '';
      write = function(buf) {
        return content += buf;
      };
      end = function() {
        var err, handleError, transformOptions;
        handleError = (function(_this) {
          return function(error) {
            var suffix;
            suffix = " (while " + transformName + " was processing " + file + ")";
            if (error instanceof Error && error.message) {
              error.message += suffix;
            } else {
              error = new Error("" + error + suffix);
            }
            return _this.emit('error', error);
          };
        })(this);
        try {
          transformOptions = {
            file: file,
            configData: configData,
            config: configData != null ? configData.config : void 0,
            opts: configData != null ? configData.config : void 0
          };
          return transformFn.call(this, content, transformOptions, (function(_this) {
            return function(err, transformed) {
              if (err) {
                return handleError(err);
              }
              _this.queue(String(transformed));
              return _this.queue(null);
            };
          })(this));
        } catch (_error) {
          err = _error;
          return handleError(err);
        }
      };
      return through(write, end);
    };
    transform.configure = function(config, configOptions) {
      var answer;
      if (configOptions == null) {
        configOptions = {};
      }
      answer = exports.makeStringTransform(transformName, options, transformFn);
      answer.setConfig(config, configOptions);
      return answer;
    };
    transform.setConfig = function(config, configOptions) {
      var configDir, configFile;
      if (configOptions == null) {
        configOptions = {};
      }
      configFile = configOptions.configFile || null;
      configDir = configOptions.configDir || (configFile ? path.dirname(configFile) : null);
      if (!config) {
        this.configData = null;
      } else {
        this.configData = {
          config: config,
          configFile: configFile,
          configDir: configDir,
          cached: false
        };
        if (config.appliesTo) {
          this.configData.appliesTo = config.appliesTo;
          delete config.appliesTo;
        }
      }
      return this;
    };
    return transform;
  };

  exports.makeFalafelTransform = function(transformName, options, transformFn) {
    var falafelOptions, ref, transform;
    if (options == null) {
      options = {};
    }
    if (transformFn == null) {
      transformFn = options;
      options = {};
    }
    falafelOptions = (ref = options.falafelOptions) != null ? ref : {};
    transform = exports.makeStringTransform(transformName, options, function(content, transformOptions, done) {
      var pending, transformCb, transformErr, transformed;
      transformErr = null;
      pending = 1;
      transformed = null;
      transformCb = function(err) {
        if (err && !transformErr) {
          transformErr = err;
          done(err);
        }
        if (transformErr) {
          return;
        }
        pending--;
        if (pending === 0) {
          return done(null, transformed);
        }
      };
      transformed = falafel(content, falafelOptions, function(node) {
        var err;
        pending++;
        try {
          return transformFn(node, transformOptions, transformCb);
        } catch (_error) {
          err = _error;
          return transformCb(err);
        }
      });
      return transformCb(transformErr, transformed);
    });
    transform.configure = function(config, configOptions) {
      var answer;
      if (configOptions == null) {
        configOptions = {};
      }
      answer = exports.makeFalafelTransform(transformName, options, transformFn);
      answer.setConfig(config, configOptions);
      return answer;
    };
    return transform;
  };

  exports.makeRequireTransform = function(transformName, options, transformFn) {
    var evaluateArguments, ref, transform;
    if (options == null) {
      options = {};
    }
    if (transformFn == null) {
      transformFn = options;
      options = {};
    }
    evaluateArguments = (ref = options.evaluateArguments) != null ? ref : true;
    transform = exports.makeFalafelTransform(transformName, options, function(node, transformOptions, done) {
      var arg, args, dirname, varNames, vars;
      if (node.type === 'CallExpression' && node.callee.type === 'Identifier' && node.callee.name === 'require') {
        if (evaluateArguments) {
          dirname = path.dirname(transformOptions.file);
          varNames = ['__filename', '__dirname', 'path', 'join'];
          vars = [transformOptions.file, dirname, path, path.join];
          args = node["arguments"].map(function(arg) {
            var err, t;
            t = "return " + (arg.source());
            try {
              return Function(varNames, t).apply(null, vars);
            } catch (_error) {
              err = _error;
              return arg.source();
            }
          });
        } else {
          args = (function() {
            var i, len, ref1, results;
            ref1 = node["arguments"];
            results = [];
            for (i = 0, len = ref1.length; i < len; i++) {
              arg = ref1[i];
              results.push(arg.source());
            }
            return results;
          })();
        }
        return transformFn(args, transformOptions, function(err, transformed) {
          if (err) {
            return done(err);
          }
          if (transformed != null) {
            node.update(transformed);
          }
          return done();
        });
      } else {
        return done();
      }
    });
    transform.configure = function(config, configOptions) {
      var answer;
      if (configOptions == null) {
        configOptions = {};
      }
      answer = exports.makeRequireTransform(transformName, options, transformFn);
      answer.setConfig(config, configOptions);
      return answer;
    };
    return transform;
  };

  exports.runTransform = function(transform, file, options, done) {
    var doTransform;
    if (options == null) {
      options = {};
    }
    if (done == null) {
      done = options;
      options = {};
    }
    doTransform = function(content) {
      var data, err, throughStream;
      data = "";
      err = null;
      throughStream = options.config != null ? transform(file, options.config) : transform(file);
      throughStream.on("data", function(d) {
        return data += d;
      });
      throughStream.on("end", function() {
        if (!err) {
          return done(null, data);
        }
      });
      throughStream.on("error", function(e) {
        err = e;
        return done(err);
      });
      throughStream.write(content);
      return throughStream.end();
    };
    if (options.content) {
      return process.nextTick(function() {
        return doTransform(options.content);
      });
    } else {
      return fs.readFile(file, "utf-8", function(err, content) {
        if (err) {
          return done(err);
        }
        return doTransform(content);
      });
    }
  };

}).call(this);
