/*
 * Copyright 2013, All Rights Reserved.
 *
 * Code licensed under the BSD License:
 * https://github.com/node-gh/gh/blob/master/LICENSE.md
 *
 * @author Eduardo Lundgren <eduardolundgren@gmail.com>
 */

var async = require('async'),
    base = require('./base'),
    clc = require('cli-color'),
    exec = require('child_process').exec,
    logger = require('./logger');

exports.invoke = function(path, scope, opt_callback) {
    var after = exports.getHooksFromPath(path + '.after'),
        before = exports.getHooksFromPath(path + '.before'),
        afterOperations = [],
        beforeOperations = [],
        context;

    context = exports.createContext(scope);

    after.forEach(function(cmd) {
        afterOperations.push(exports.wrapCommand_(cmd, context));
    });

    before.forEach(function(cmd) {
        beforeOperations.push(exports.wrapCommand_(cmd, context));
    });

    async.series(beforeOperations, function() {
        opt_callback && opt_callback(function() {
            async.series(afterOperations);
        });
    });
};

exports.createContext = function(scope) {
    var config = base.getGlobalConfig();

    return {
        options: scope.options,
        signature: config.signature
    };
};

exports.getHooksArrayFromPath_ = function(path, opt_config) {
    var keys = path.split('.'),
        key = keys.shift(),
        hooks;

    opt_config = opt_config || base.getGlobalConfig();

    hooks = opt_config.hooks || {};

    while (hooks[key]) {
        hooks = hooks[key];
        key = keys.shift();
    }

    return Array.isArray(hooks) ? hooks : [];
};

exports.getHooksFromPath = function(path) {
    var hooks,
        plugins = base.getPlugins(),
        pluginHooks = [];

    // First, load all core hooks for the specified path.
    hooks = exports.getHooksArrayFromPath_(path);

    // Second, search all installed plugins and load the hooks for each into
    // core hooks array.
    plugins.forEach(function(plugin) {
        var config = base.getPluginConfig(plugin),
            pluginConfig;

        if (config.plugins && !base.isPluginIgnored(plugin)) {
            pluginConfig = config.plugins.jira;

            if (pluginConfig) {
                pluginHooks = pluginHooks.concat(
                    exports.getHooksArrayFromPath_(path, pluginConfig));
            }
        }
    });

    return hooks.concat(pluginHooks);
};

exports.exec_ = function(cmd, cwd, log, callback) {
    exec(cmd, {
            cwd: cwd,
            stdio: 'inherit'
        },
        function(error, stdout) {
            if (log) {
                logger.log(stdout);
            }

            if (error) {
                logger.custom('[error]', clc.redBright, logger.getErrorMessage(error));
            }
            callback();
        });
};

exports.wrapCommand_ = function(cmd, context) {
    return function(callback) {
        var raw = cmd,
            log = false;

        if (typeof raw === 'object') {
            raw = cmd.cmd;
            log = cmd.log;
        }

        raw = logger.compileTemplate(raw, context);
        if (raw) {
            logger.log('[hook]', raw.trim());
            exports.exec_(raw, process.cwd(), log, callback);
        }
        else {
            callback && callback();
        }
    };
};

@@ -333,16 +333,60 @@
 ).exec,%0A
+    spawn = require('child_process').spawn,%0A
     logg
@@ -2468,13 +2468,31 @@
 md, 
+opt_args, opt_
 cwd, 
+opt_
 log,
@@ -2500,24 +2500,165 @@
 callback) %7B%0A
+    var spawned;%0A%0A    if (opt_args) %7B%0A        spawned = spawn(cmd, opt_args, %7B%0A            stdio: 'inherit'%0A        %7D);%0A    %7D%0A    else %7B%0A    
     exec(cmd
@@ -2677,13 +2677,21 @@
     
+    
 cwd: 
+opt_
 cwd,
@@ -2695,32 +2695,36 @@
 wd,%0A            
+    
 stdio: 'inherit'
@@ -2716,32 +2716,36 @@
 tdio: 'inherit'%0A
+    
         %7D,%0A     
@@ -2747,16 +2747,20 @@
         
+    
 function
@@ -2773,20 +2773,31 @@
 , stdout
-) %7B%0A
+, stdin) %7B%0A    
         
@@ -2804,16 +2804,20 @@
     if (
+opt_
 log) %7B%0A 
@@ -2823,32 +2823,36 @@
                 
+   
+ 
 logger.log(stdou
@@ -2846,22 +2846,36 @@
 ger.log(
-stdout
+error, stdout, stdin
 );%0A     
@@ -2873,35 +2873,43 @@
 n);%0A            
-%7D%0A%0A
+    %7D%0A%0A    
             if (
@@ -2913,24 +2913,28 @@
 f (error) %7B%0A
+    
             
@@ -3013,34 +3013,42 @@
 ));%0A            
-%7D%0A
+    %7D%0A    
             call
@@ -3059,27 +3059,37 @@
 ();%0A        
-%7D);
+    %7D);%0A    %7D
 %0A%7D;%0A%0Aexports
@@ -3173,25 +3173,63 @@
     var 
-raw = cmd
+args,%0A            raw = cmd,%0A            rawLog
 ,%0A      
@@ -3303,21 +3303,23 @@
     
-raw
+args
  = cmd.
-cmd
+args
 ;%0A  
@@ -3343,16 +3343,69 @@
 md.log;%0A
+            raw = cmd.cmd;%0A            rawLog = raw;%0A
         
@@ -3459,16 +3459,17 @@
 ntext);%0A
+%0A
         
@@ -3475,24 +3475,105 @@
  if (raw) %7B%0A
+            if (args) %7B%0A                rawLog += args.join(' ');%0A            %7D%0A%0A
             
@@ -3596,16 +3596,19 @@
 k%5D', raw
+Log
 .trim())
@@ -3639,16 +3639,22 @@
 ec_(raw,
+ args,
  process

Allow hooks to inherit stdio - Fix #191