/**
 * Provides utils methods for Node.js
 */
var spawn = require('child_process').spawn;
var exec = require('child_process').exec;
var path = require('path');
var fs = require('fs');

// VARS
var nodeBinPath = path.join(process.cwd(), "node_modules", "bin");

/**
 * Methods
 */

/**
 *
 * @param {string}      cmd
 * @param {string[]}    args
 * @param {object}      [options]   process.spawn options
 * @param {function}    callback
 */
function runWithProgress(cmd, args, options, callback) {
    var errData;

    if (typeof options === 'function' && callback === undefined) {
        callback = options;
        options = undefined;
    }

    cmd = cmd + (process.platform === 'win32' ? '.cmd' : '');

    cmd = spawn(cmd, args, options);

    cmd.stderr.setEncoding('utf8');

    cmd.stdout.setEncoding('utf8');
    cmd.stdout.on('data', function (data) {
        console.log(data.trim());
    });

    cmd.stderr.on('data', function (data) {
        errData += data;
        console.log(data);
    });

    cmd.on('close', function (code) {
        console.log('');
        callback(code, errData);
    });
}

function runExec(cmd, args, callback) {
    exec(
        cmd + (process.platform === 'win32' ? '.cmd' : '') + ' ' + args,
        function (err, stdout, stderr) {
            if (err) {
                console.log(stderr);
                callback(1, err);
            } else {
                if (stdout) {
                    console.log(stdout);
                }
                callback(0);
            }
        });
}


/*--- NPM BIN runner utils ---*/

/**
 * Run process from Npm Bin path
 */
function runNpmBinWithProgress(cmd, args, options, callback) {
    return runWithProgress(nodeBinPath + '/' + cmd, args, options, callback);
}

function runNpmBinExec(cmd, args, callback) {
    return runExec(nodeBinPath + '/' + cmd, args, callback);
}

/*--- UTILS ---*/

/**
 * Checks if file is present in the local Npm Bin
 *
 * @param cmd {String} Executable to check
 * @returns {boolean}
 */
function isPresentInNpmBin(cmd) {
    try {
        var fileName = cmd + (process.platform === 'win32' ? '.cmd' : '');
        return !!fs.lstatSync(nodeBinPath + '/' + fileName);
    } catch (err) {
        return false;
    }
}


/*--- EXPORTS ---*/
module.exports = {
    runWithProgress: runWithProgress,
    runExec: runExec,

    runNpmBinWithProgress: runNpmBinWithProgress,
    runNpmBinExec: runNpmBinExec,

    isPresentInNpmBin: isPresentInNpmBin
};