// Generated by CoffeeScript 1.12.4
var CSON, extractOptsAndCallback, fsUtil, pathUtil, requireFresh;

fsUtil = require('safefs');

pathUtil = require('path');

extractOptsAndCallback = require('extract-opts');

requireFresh = require('requirefresh');

CSON = (function() {
  function CSON() {}

  CSON.prototype.ensureErrorType = function(err) {
    if (err instanceof Error) {
      return err;
    } else {
      return this.ensureErrorType(err);
    }
  };

  CSON.prototype.complete = function(result, next) {
    if (next) {
      if (result instanceof Error) {
        next(result);
      } else {
        next(null, result);
      }
      return this;
    } else {
      return result;
    }
  };

  CSON.prototype.getOptions = function(opts) {
    if (opts == null) {
      opts = {};
    }
    if (opts.format == null) {
      opts.format = null;
    }
    if (opts.filename == null) {
      opts.filename = null;
    }
    if (opts.filename) {
      opts.filename = pathUtil.resolve(opts.filename);
      if (opts.format == null) {
        opts.format = this.getFormat(opts.filename);
      }
    }
    if (opts.json == null) {
      opts.json = true;
    }
    if (opts.cson == null) {
      opts.cson = true;
    }
    if (opts.javascript == null) {
      opts.javascript = false;
    }
    if (opts.coffeescript == null) {
      opts.coffeescript = false;
    }
    return opts;
  };

  CSON.prototype.getFormat = function(file) {
    switch (pathUtil.extname(file)) {
      case '.json':
        return 'json';
      case '.cson':
        return 'cson';
      case '.coffee':
        return 'coffeescript';
      case '.js':
        return 'javascript';
      default:
        return null;
    }
  };

  CSON.prototype.action = function(args) {
    var action, data, next, opts, prefix, ref, ref1, result, suffix;
    action = args.action, prefix = args.prefix, suffix = args.suffix, data = args.data, opts = args.opts, next = args.next;
    if (suffix == null) {
      suffix = '';
    }
    ref = extractOptsAndCallback(opts, next), opts = ref[0], next = ref[1];
    switch (action) {
      case 'requireFile':
      case 'parseFile':
        if (opts.filename == null) {
          opts.filename = data;
        }
    }
    opts = this.getOptions(opts);
    if ((ref1 = opts.format) === null || ref1 === 'cson') {
      if (opts.cson === true) {
        result = this[prefix + 'CSON' + suffix](data, opts);
      } else {
        result = new Error("CSON." + action + ": Desired format is CSON however CSON is disabled by an option");
      }
    } else if (opts.format === 'json') {
      if (opts.json === true) {
        result = this[prefix + 'JSON' + suffix](data, opts);
      } else {
        result = new Error("CSON." + action + ": Desired format is JSON however JSON is disabled by an option");
      }
    } else if (opts.format === 'javascript') {
      if (opts.javascript === true) {
        result = this[prefix + 'JS' + suffix](data, opts);
      } else {
        result = new Error("CSON." + action + ": Desired format is JavaScript however JavaScript is disabled by an option");
      }
    } else if (opts.format === 'coffeescript') {
      if (opts.coffeescript === true) {
        result = this[prefix + 'CS' + suffix](data, opts);
      } else {
        result = new Error("CSON." + action + ": Desired format is CoffeeScript however CoffeeScript is disabled by an option");
      }
    } else {
      result = new Error("CSON." + action + ": Desired format is not supported");
    }
    return this.complete(result, next);
  };

  CSON.prototype.stringify = function(data, replacer, indent) {
    var opts;
    opts = {};
    opts.replacer = replacer;
    opts.indent = indent;
    return this.createCSONString(data, opts);
  };

  CSON.prototype.parse = function(data, opts, next) {
    return this.parseCSONString(data, opts, next);
  };

  CSON.prototype.load = function(data, opts, next) {
    return this.parseCSONFile(data, opts, next);
  };

  CSON.prototype.createString = function(data, opts, next) {
    return this.action({
      action: 'createString',
      prefix: 'create',
      suffix: 'String',
      data: data,
      opts: opts,
      next: next
    });
  };

  CSON.prototype.parseString = function(data, opts, next) {
    return this.action({
      action: 'parseString',
      prefix: 'parse',
      suffix: 'String',
      data: data,
      opts: opts,
      next: next
    });
  };

  CSON.prototype.parseFile = function(data, opts, next) {
    return this.action({
      action: 'parseFile',
      prefix: 'parse',
      suffix: 'File',
      data: data,
      opts: opts,
      next: next
    });
  };

  CSON.prototype.requireFile = function(data, opts, next) {
    return this.action({
      action: 'requireFile',
      prefix: 'require',
      suffix: 'File',
      data: data,
      opts: opts,
      next: next
    });
  };

  CSON.prototype.createJSONString = function(data, opts, next) {
    var err, ref, result;
    ref = extractOptsAndCallback(opts, next), opts = ref[0], next = ref[1];
    opts = this.getOptions(opts);
    if (opts.replacer == null) {
      opts.replacer = null;
    }
    if (opts.indent == null) {
      opts.indent = '  ';
    }
    try {
      result = JSON.stringify(data, opts.replacer, opts.indent);
    } catch (error) {
      err = error;
      result = this.ensureErrorType(err);
    }
    return this.complete(result, next);
  };

  CSON.prototype.createCSONString = function(data, opts, next) {
    var err, ref, result;
    ref = extractOptsAndCallback(opts, next), opts = ref[0], next = ref[1];
    opts = this.getOptions(opts);
    if (opts.replacer == null) {
      opts.replacer = null;
    }
    if (opts.indent == null) {
      opts.indent = '\t';
    }
    try {
      result = require('cson-parser').stringify(data, opts.replacer, opts.indent);
    } catch (error) {
      err = error;
      result = this.ensureErrorType(err);
    }
    return this.complete(result, next);
  };

  CSON.prototype.createCSString = function(data, opts, next) {
    var ref, result;
    ref = extractOptsAndCallback(opts, next), opts = ref[0], next = ref[1];
    result = new Error('CSON.createCS: Creating CoffeeScript code is not yet supported');
    return this.complete(result, next);

    /*
    		Potentially we could use something like the following from CSON v1
    		However the JSON.stringify gets rid of functions...
    		which is the entire point of the coffee-script mode over the CSON mode...
    		So until we figure out how to toString() an object and keep the functions intact,
    		unsafe stringifying to CSON or CS or JS won't happen.
    
    		Perhaps https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toSource
    		will be of use one day
    
    		src = "var result = #{JSON.stringify obj}"
    		result = require('js2coffee').build(src, opts).code
    		result = result.replace(/^\s*result\s*\=\s/, '')
    		if /^\s/.test(result) is false
    			result = result.trim()
    		if typeof obj is 'object'
    			unless Array.isArray(obj)
    				result = '{'+result+'}'  unless result is '{}'
    		return result
     */
  };

  CSON.prototype.createJSString = function(data, opts, next) {
    var ref, result;
    ref = extractOptsAndCallback(opts, next), opts = ref[0], next = ref[1];
    result = new Error('CSON.createJS: Creating JavaScript code is not yet supported');
    return this.complete(result, next);
  };

  CSON.prototype.parseJSONString = function(data, opts, next) {
    var err, ref, result;
    ref = extractOptsAndCallback(opts, next), opts = ref[0], next = ref[1];
    try {
      result = JSON.parse(data);
    } catch (error) {
      err = error;
      result = this.ensureErrorType(err);
    }
    return this.complete(result, next);
  };

  CSON.prototype.parseCSONString = function(data, opts, next) {
    var err, ref, result;
    ref = extractOptsAndCallback(opts, next), opts = ref[0], next = ref[1];
    try {
      result = require('cson-parser').parse(data);
    } catch (error) {
      err = error;
      result = this.ensureErrorType(err);
    }
    return this.complete(result, next);
  };

  CSON.prototype.parseJSString = function(data, opts, next) {
    var err, ref, result;
    ref = extractOptsAndCallback(opts, next), opts = ref[0], next = ref[1];
    opts = this.getOptions(opts);
    if (opts.context == null) {
      opts.context = {};
    }
    try {
      result = require('vm').runInNewContext(data, opts.context, opts);
    } catch (error) {
      err = error;
      result = this.ensureErrorType(err);
    }
    return this.complete(result, next);
  };

  CSON.prototype.parseCSString = function(data, opts, next) {
    var err, ref, result;
    ref = extractOptsAndCallback(opts, next), opts = ref[0], next = ref[1];
    opts = this.getOptions(opts);
    try {
      result = require('coffee-script')["eval"](data, opts);
    } catch (error) {
      err = error;
      result = this.ensureErrorType(err);
    }
    return this.complete(result, next);
  };

  CSON.prototype.parseJSONFile = function(file, opts, next) {
    var ref, result;
    ref = extractOptsAndCallback(opts, next), opts = ref[0], next = ref[1];
    result = fsUtil.readFileSync(file);
    if (result instanceof Error) {
      result = result;
    } else {
      result = this.parseJSONString(result.toString(), opts);
    }
    return this.complete(result, next);
  };

  CSON.prototype.parseCSONFile = function(file, opts, next) {
    var ref, result;
    ref = extractOptsAndCallback(opts, next), opts = ref[0], next = ref[1];
    result = fsUtil.readFileSync(file);
    if (result instanceof Error) {
      result = result;
    } else {
      result = this.parseCSONString(result.toString(), opts);
    }
    return this.complete(result, next);
  };

  CSON.prototype.parseJSFile = function(file, opts, next) {
    var ref, result;
    ref = extractOptsAndCallback(opts, next), opts = ref[0], next = ref[1];
    result = fsUtil.readFileSync(file);
    if (result instanceof Error) {
      result = result;
    } else {
      result = this.parseJSString(result.toString(), opts);
    }
    return this.complete(result, next);
  };

  CSON.prototype.parseCSFile = function(file, opts, next) {
    var ref, result;
    ref = extractOptsAndCallback(opts, next), opts = ref[0], next = ref[1];
    result = fsUtil.readFileSync(file);
    if (result instanceof Error) {
      result = result;
    } else {
      result = this.parseCSString(result.toString(), opts);
    }
    return this.complete(result, next);
  };

  CSON.prototype.requireJSONFile = function(file, opts, next) {
    var ref, result;
    ref = extractOptsAndCallback(opts, next), opts = ref[0], next = ref[1];
    result = this.parseJSONFile(file, opts);
    return this.complete(result, next);
  };

  CSON.prototype.requireCSONFile = function(file, opts, next) {
    var ref, result;
    ref = extractOptsAndCallback(opts, next), opts = ref[0], next = ref[1];
    result = this.parseCSONFile(file, opts);
    return this.complete(result, next);
  };

  CSON.prototype.requireJSFile = function(file, opts, next) {
    var err, ref, result;
    ref = extractOptsAndCallback(opts, next), opts = ref[0], next = ref[1];
    try {
      result = requireFresh(file);
    } catch (error) {
      err = error;
      result = this.ensureErrorType(err);
    }
    return this.complete(result, next);
  };

  CSON.prototype.requireCSFile = function(file, opts, next) {
    var err, ref, result;
    ref = extractOptsAndCallback(opts, next), opts = ref[0], next = ref[1];
    require('coffee-script/register');
    try {
      result = requireFresh(file);
    } catch (error) {
      err = error;
      result = this.ensureErrorType(err);
    }
    return this.complete(result, next);
  };

  return CSON;

})();

module.exports = new CSON();
