/* global require, console, module */

var ora = require('ora'),
    Q = require('q'),
    __path = require('path'),
    exec = require('child_process').exec,
    Client = require('ssh2').Client,
    varnishcache = require('./varnishcache.js'),
    redis = require('./rediscache.js'),
    CONFIG = {},
    cacheType = 'redis', // filesystem or redis
    dockerMagentoCLI = 'cti mage:bin',
    _host,
    _stream = false,
    _conn,
    _wwwPath = '../../../../www',
    _vmPath = '../../../../vm';


function createSSHConnection() {
    'use strict';

    _conn = new Client();

    // console.log('----' + CONFIG.m2.vm);
    if (CONFIG.m2.vm === false || CONFIG.m2.vm === 'false') {
        return;
    }

    _conn.on('ready', function () {
        // console.log('SSH connection is ready');
        _conn.shell(function (err, stream) {
            if (err) {
                console.error(err);
                return false;
            }

            _stream = stream;

            _stream.on('close', function() {
                _conn.end();
            });

            return true;
        });
    }).connect({
        host: _host,
        username: 'vagrant',
        password: 'vagrant'
    });
}

/**
 * Check if config is set to use
 * Docker container
 * @returns {boolean}
 */
function isDocker() {
    'use strict';

    var _docker = false;
    if (typeof CONFIG.m2 !== 'undefined') {
        if (typeof CONFIG.m2.docker !== 'undefined') {
            if ((CONFIG.m2.docker === true || CONFIG.m2.docker === 'true')) {
                _docker = true;
            }
        }
    }

    return _docker;
}

/**
 * Clear varnish if enabled
 * @param callback
 * @private
 */
function _clearVarnishCache(callback) {
    'use strict';

    if (typeof CONFIG.m2.vm.varnish === 'undefined') {
        callback();
        return false;
    }

    if (CONFIG.m2.vm.varnish === 0) {
        callback();
        return false;
    }
    varnishcache.clean(
        _host,
        CONFIG.m2.vm.varnish_man_port,
        CONFIG.m2.vm.varnish_secret
    ).finally(function () {
        callback();
    });

    return true;
}

/**
 * Add Loader/Progress Indicator
 *
 * @param str {string}  - Information to be shown along side the loader
 */
function addLoader(str) {
    'use strict';

    return ora({text: str, spinner: 'monkey'}).start();
}

/**
 * Magento 2 - CLI Cache Clean command string with parameter to clean
 * a specific cache type
 *
 * @param cacheTypes {string} - CSV string of Magento 2 Cache types to be cleared
 * @returns {string} - Command string to clear Magento 2 cache types
 */
function getMagentoCacheCleanCommand(cacheTypes) {
    'use strict';

    return 'cd ' + _vmPath + ' && vagrant ssh -c "magento cache:clean ' + cacheTypes + '"';
}

function getMagentoCacheCleanCommand2(cacheTypes) {
    'use strict';

    if (isDocker()) {
        return dockerMagentoCLI + ' cache:clean ' + cacheTypes;
    }

    return 'magento cache:clean ' + cacheTypes;
}

/**
 * Clear Magento cache using Magento CLI
 * by SSH into Host and running the Magento CLI commands
 *
 * @param params
 * @param callback
 * @private
 */
function _clearUsingCLI(params, callback) {
    'use strict';

    var clearCacheMagentoCommand,
        spinner,
        cmdCWD = null;

    spinner = addLoader('Clearing Magento ' + params.split(' ') + ' caches please wait...');

    clearCacheMagentoCommand = getMagentoCacheCleanCommand2(params);
    if (CONFIG.m2.vm === false || CONFIG.m2.vm === 'false') {
        //_wwwPath = (CONFIG.m2.path) ? CONFIG.m2.path : _wwwPath;
        if (isDocker()) {
            cmdCWD = _wwwPath;
        } else {
            clearCacheMagentoCommand = _wwwPath + '/bin/' + clearCacheMagentoCommand;
        }

        exec(clearCacheMagentoCommand, {timeout: 80000, encoding: 'utf-8', cwd: cmdCWD}, function (error, stdout, stderr) {
            if (error) {
                spinner.fail('Failed Clearing Magento ' + params.split(' ') + ' caches.' + error);
                return;
            }

            if (stderr) {
                spinner.fail('Failed Clearing Magento ' + params.split(' ') + ' caches.' + stderr);
                return;
            }

            spinner.succeed('Cleared Magento ' + params.split(' ') + ' caches.');

            callback();
        });
    } else {
        if (_stream !== false) {
            _stream.on('data', function (data) {
                // console.log('STDOUT: ' + data);
                if (data.indexOf('Cleaned') !== -1) {
                    spinner.succeed('Cleared Magento ' + params.split(' ') + ' caches.');
                    callback();
                }
            }).stderr.on('data', function (error) {
                spinner.fail('Failed Clearing Magento ' + params.split(' ') + ' caches.' + error);
                callback();
                _stream.end();
                _stream = false;
            });

            _stream.write(clearCacheMagentoCommand + '\n');
        } else {
            clearCacheMagentoCommand = getMagentoCacheCleanCommand(params);
            exec(clearCacheMagentoCommand, {timeout: 80000, encoding: 'utf-8'}, function (error, stdout, stderr) {
                if (error) {
                    spinner.fail('Failed Clearing Magento ' + params.split(' ') + ' caches.' + error);
                    return;
                }

                if (stderr) {
                    spinner.fail('Failed Clearing Magento ' + params.split(' ') + ' caches.' + stderr);
                    return;
                }

                spinner.succeed('Cleared Magento ' + params.split(' ') + ' caches.');

                callback();
            });
        }
    }
}

/**
 * Clear Redis Tags/ID's manually by connecting to Redis on Host
 *
 * @param params
 * @param callback
 * @private
 */
function _clearUsingRedis(params, callback) {
    'use strict';

    var spinner;

    spinner = addLoader('Clearing Magento ' + params.split(' ') + ' caches please wait...');

    redis.cache.init({
        host: _host,
        port: 6379
    });

    if (params.split(' ')[0] === 'layout') {
        redis.cache.connect()
            .then(function () {
                return redis.cache.flushFullPage();
            }).then(function () {
            return redis.cache.flushLayout();
        })
            .then(function () {
                spinner.succeed('Cleared Magento ' + params.split(' ') + ' caches.');
                redis.cache.disconnect();
                _clearVarnishCache(callback);
            });
    } else if (params.split(' ')[0] === 'block_html') {
        redis.cache.connect()
            .then(function () {
                return redis.cache.flushFullPage();
            }).then(function () {
            return redis.cache.flushBlock();
        })
            .then(function() {
                spinner.succeed('Cleared Magento ' + params.split(' ') + ' caches.');
                redis.cache.disconnect();
                _clearVarnishCache(callback);
            });
    } else if (params.split(' ')[0] === 'full_page') {
        redis.cache.connect()
            .then(function () {
                return redis.cache.flushFullPage();
            })
            .then(function() {
                spinner.succeed('Cleared Magento ' + params.split(' ') + ' caches.');
                redis.cache.disconnect();
                _clearVarnishCache(callback);
            });
    }
}

/**
 * Host of VM to be used to connect
 * @param host
 * @private
 */
function _setHost(host) {
    'use strict';
    _host = host;
    createSSHConnection();
}

function _setVMPath(path) {
    'use strict';

    _vmPath = path;

    if (isDocker()) {
        _wwwPath = __path.resolve(path, '../');
    } else {
        _wwwPath = __path.resolve(path, '../www');
    }
}

function _setConfig(path) {
    'use strict';

    CONFIG = require(path + 'theme-config.json');
}

/**
 * Check if Redis can be connected to the host
 * @private
 */
function _isRedis() {
    'use strict';

    var spinner,
        _defer = Q.defer();

    spinner = addLoader('Checking caches please wait...');

    if ((CONFIG.m2.vm === false || CONFIG.m2.vm === 'false')) {
        cacheType = 'filesystem';
        if (isDocker()) {
            spinner.succeed(' Using Magento CLI cache commands for Docker');
        } else {
            spinner.succeed(' Using Magento CLI cache commands');
        }
        _defer.resolve();
    } else {
        redis.cache.init({
            host: _host,
            port: 6379
        });

        redis.cache.connect().then(function() {
            cacheType = 'redis';
            redis.cache.disconnect();
            spinner.succeed('Magento Cache using Redis');
            _defer.resolve();
        }, function () {
            cacheType = 'filesystem';
            if (isDocker()) {
                spinner.succeed(' Using Magento CLI cache commands for Docker');
            } else {
                spinner.succeed(' Using Magento CLI cache commands');
            }
            _defer.resolve();
        });
    }

    return _defer.promise;
}

/**
 * Clear Magento Cache based on cache types
 *
 * @param params
 * @param callback
 */
function _clear(params, callback) {
    'use strict';
    var _params;

    if (typeof params === 'undefined') {
        _params = '';
    } else {
        _params = params.join(' ');
    }

    if (cacheType === 'filesystem') {
        _clearUsingCLI(_params, callback);
    } else if (cacheType === 'redis') {
        _clearUsingRedis(_params, callback);
    }
}

module.exports = {
    isRedis: _isRedis,
    clear: _clear,
    setHost: _setHost,
    setVMPath: _setVMPath,
    setConfig: _setConfig
};
