#!/usr/bin/env node

var fs = require('fs'),
    beautify = require('./beautify').js_beautify,
    config,
    options;

// only node v0.5+ can require json
if (parseFloat(process.version.substr(1)) < 0.5) {
    config  = JSON.parse(fs.readFileSync(__dirname + '/config/defaults.json', 'utf8'));
    options = JSON.parse(fs.readFileSync(__dirname + '/config/options.json', 'utf8'));
} else {
    config  = require('./config/defaults.json');
    options = require('./config/options.json');
}

var argv = require('optimist')
        .usage("Reformat JS files in idiomatic style.\n\nUsage:\n  $0 [options] path/to/file [...]")
        .options(options)
        .check(function (argv) {
            if (argv.file) {
                if (Array.isArray(argv.file)) {
                    // might pass multiple -f args
                    argv._ = argv._.concat(argv.file);
                }
                else if ('string' === typeof argv.file) {
                    // `cat foo.js | cli.js -f -`, avoid ['-', true]
                    argv._.push(argv.file);
                }
            }

            if ('string' === typeof argv.outfile && !argv._.length) {
                // use outfile as input when no other files passed in args
                argv._.push(argv.outfile);
                // operation is now an implicit overwrite
                argv.replace = true;
            }

            if (!argv._.length) {
                throw 'Must define at least one file.';
            }

            argv._.forEach(function (filepath) {
                try {
                    if (filepath !== "-") {
                        fs.statSync(filepath);
                    }
                } catch (err) {
                    throw 'Unable to open path "' + filepath + '"';
                }
            });
        })
        .argv;

if (argv["indent-with-tabs"]) {
    argv["indent-size"] = 1;
    argv["indent-char"] = "\t";
}

// translate dashed argv into weird python underscored keys,
// avoiding single character aliases.
Object.keys(argv).forEach(function (key) {
    if (key.length > 1) {
        config[key.replace(/-/g, '_')] = argv[key];
    }
});

argv._.forEach(function (filepath) {
    var data = '',
        input;

    if (filepath === '-') {
        input = process.stdin;
        input.resume();
        input.setEncoding('utf8');
    } else {
        input = fs.createReadStream(filepath, { encoding: 'utf8' });
    }

    input.on('data', function (chunk) {
        data += chunk;
    });

    input.on('end', function () {
        var pretty = beautify(data, config),
            output;

        // -o passed with no value overwrites
        if (config.outfile === true || config.replace) {
            config.outfile = filepath;
        }

        if (config.outfile) {
            output = fs.createWriteStream(config.outfile, {
                flags: "w",
                encoding: "utf8",
                mode: 0644
            });
        } else {
            output = process.stdout;
        }

        // ensure newline at end of beautified output
        pretty += '\n';

        output.write(pretty);

        if (config.outfile) {
            output.end();
        }
    });
});

@@ -2156,16 +2156,153 @@
  %7D%0A%7D);%0A%0A
+function onOutputError(err) %7B%0A    if (err.code === 'EACCES') %7B%0A        console.error(err.path + %22 is not writable. Skipping!%22);%0A    %7D%0A%7D%0A%0A
 argv._.f
@@ -3083,32 +3083,117 @@
 %0A            %7D);
+%0A%0A            // catch possible errors%0A            output.on('error', onOutputError);
 %0A        %7D else 
@@ -3321,16 +3321,51 @@
  '%5Cn';%0A%0A
+        if (output.writable) %7B%0A    
         
@@ -3383,24 +3383,28 @@
 e(pretty);%0A%0A
+    
         if (
@@ -3413,32 +3413,36 @@
 nfig.outfile) %7B%0A
+    
             outp
@@ -3447,24 +3447,38 @@
 tput.end();%0A
+            %7D%0A
         %7D%0A  

Check for writability of output file, skipping if error caught.