var gulp = require('gulp'),
    appConfig,
    taskSettings = {};

// Magesparrow Brand Header
require('./task/magesparrow');

// Task Settings
taskSettings = {
    DEVELOPMENT_MODE: false,
    SERVE_MODE: false,
    APP_YAML: 'application.yaml',
    PROJECT_PATH: '../../../',
    THEME_CONFIG: 'theme-config.json',
    THEME_XML: 'theme.xml',
    PROJECT_KEY: '',
    WEB_ROOT: 'www',
    BLANK_THEME: '/vendor/ctidigital/',
    VENDOR_THEME_PATH: '/app/design/frontend/Cti/',
    VENDOR_THEME_POSTFIX: '-theme',
    SITES: []
};

// Current Theme Used for SERVE MODE
_currentTheme = {};

// Require/Load External tasks modules
appConfig = require('./task/appconfig')(gulp, taskSettings);

// Get/Set Configs
gulp.task(appConfig.name, appConfig.task);
gulp.task('setConfig', setConfig);
gulp.task('config', gulp.series([appConfig.name, 'setConfig']));

gulp.task('compileThemes', compileThemes);
gulp.task('developerMode', setDeveloperMode);
gulp.task('serveMode', setServeMode);
gulp.task('browserSync', browserSync);
gulp.task('watch:sass', watchSass);

gulp.task('watch', gulp.parallel('watch:sass'));

gulp.task('dev', gulp.series(['developerMode', 'config', 'compileThemes']));
gulp.task('serve', gulp.series(['serveMode', 'dev', gulp.parallel('watch', 'browserSync')]));

gulp.task('prod', gulp.series(['config', 'compileThemes']));
gulp.task('default', gulp.series(['config', 'compileThemes']));


function setDeveloperMode(done) {
    taskSettings.DEVELOPMENT_MODE = true;
    done();
}

function setServeMode(done) {
    taskSettings.SERVE_MODE = true;
    done();
}

function watchSass(done) {
    var sassPaths,
        _task,
        _SassWatchTask = require('./task/sasswatch');

    if (_currentTheme.length <= 0) {
        console.log('✖ No theme found to watch...');
        done();
    }

    sassPaths = taskSettings.PROJECT_PATH + _currentTheme[0].path + '**/{*.scss,_*.scss}';

    if (_currentTheme[0].config.sass !== false) {
        console.log('Compile SASS (Autoprefixer)...');
        if (typeof _currentTheme[0].config.sass === 'undefined') {
            _currentTheme[0].config.sass = {};
        }

        if (taskSettings.DEVELOPMENT_MODE === true) {
            _currentTheme[0].config.sass.sourceMaps = true;
            _currentTheme[0].config.sass.sassOptions = {
                'outputStyle': 'expanded'
            };
        } else {
            _currentTheme[0].config.sass.sourceMaps = false;
            _currentTheme[0].config.sass.sassOptions = {
                'outputStyle': 'compressed'
            };
        }

        _task = _SassWatchTask(gulp, taskSettings.PROJECT_PATH, _currentTheme[0].path, taskSettings.WEB_ROOT + taskSettings.BLANK_THEME, _currentTheme[0].config.sass);
    } else {
        console.log('Skipping Sass (Autoprefixer) Compilation...');
        done();
    }

    return _task.task();

   /* return gulp.watch(
        sassPaths,
        {
            events: ['add', 'change', 'addDir'],
            debounceDelay: 200
        }, gulp.series.apply(null, [_task.task]))
        .on('all', function gulpWatchEvents(event, eventPath) {
            _currentTheme[0].config.sass.src = [eventPath.replace(taskSettings.PROJECT_PATH + _currentTheme[0].path, '')];
            _task = _SassTask(gulp, taskSettings.PROJECT_PATH, _currentTheme[0].path, taskSettings.WEB_ROOT + taskSettings.BLANK_THEME, _currentTheme[0].config.sass);
    });*/
}

function browserSync(done) {
    var _task;

    if (_currentTheme.length <= 0) {
        console.log('✖ No theme found to browsersync...');
        done();
    }

    _task = require('./task/browsersync')(gulp, taskSettings.PROJECT_PATH, _currentTheme[0].path, _currentTheme[0].config.browserSync);
    _taskName = _task.name + ':' + _currentTheme[0].prefix;
    _task.task.displayName = _taskName;

    _task.task();
}

function compileThemes(done) {
    var fs = require('fs'),
        _themePath,
        _themeConfig,
        _themes = [],
        _skippedThemes = [],
        i;

    for (i = 0; i < taskSettings.SITES.length; i++) {
        _themePath = taskSettings.SITES[i].themePath;
        _themeConfig = taskSettings.PROJECT_PATH + _themePath + taskSettings.THEME_CONFIG;

        // Load `theme-config.json`, If found
        try {
            fs.accessSync(_themeConfig);
        } catch (err) {
            console.info('  ✖ No `theme-config.json` found for theme `' + taskSettings.SITES[i].prefix + '` Skipping ...');
            _skippedThemes.push(taskSettings.SITES[i].prefix);
            continue;
        }

        _themes.push({
            path: _themePath,
            config: require(_themeConfig),
            prefix: taskSettings.SITES[i].prefix
        });
    }

    console.log('\n❯ Total themes found in application.yaml: ' + taskSettings.SITES.length);
    console.log('❯ Skipped themes(' + _skippedThemes.length + '): ' + _skippedThemes.join(', '));
    console.log('❯ Themes to be compiled(' + _themes.length + '): ' + _themes.map(function (obj) {
        return obj.prefix
    }).join(', ') + '\n\n');

    if (taskSettings.SERVE_MODE === true) {
        var inquirer = require('inquirer');
        inquirer.prompt({
            type: 'list',
            name: 'prefix',
            message: 'Please select one store url from below:\n\x1b[30mThis will be used for BrowserSync proxy\x1b[0m',
            choices: _themes.map(function(object) { return {name: object['config'].browserSync.host, value:object['prefix']}; })
        }).then(function (answer) {
            _currentTheme = _themes.filter(function(object){
                return (object['prefix'] === answer.prefix)
            });
            //done();
            buildTheme(_currentTheme, done);
        });
    } else {
       buildTheme(_themes, done);
    }
}

function buildTheme(_themes, done) {
    var _taskQueue = [],
        _task,
        _taskName = '';
    for (i = 0; i < _themes.length; i++) {
        _themePath = _themes[i].path;
        _prefix = _themes[i].prefix;
        console.log('\nCompiling theme `' + _themePath + '`...');

        // Clean .tmp directory and Generated (Compiled) CSS within Theme
        console.log('Add Clean CSS task');
        _task = require('./task/themeclean')(gulp, taskSettings.PROJECT_PATH, _themePath);
        _taskName = _task.name + ':' + _prefix;
        _task.task.displayName = _taskName;
        _taskQueue.push(_task.task);

        if (_themes[i].config.favicon !== false) {
            console.log('Generate FAVICONS...');
            _task = require('./task/favicons')(gulp, taskSettings.PROJECT_PATH, _themePath, _themes[i].config.favicon);
            _taskName = _task.name + ':' + _prefix;
            _task.task.displayName = _taskName;
            _taskQueue.push(_task.task);
        } else {
            console.log('Skipping FAVICONS...');
        }

        if (_themes[i].config.sitelogo !== false) {
            console.log('Generate Site Logos...');
            _task = require('./task/sitelogo')(gulp, taskSettings.PROJECT_PATH, _themePath, _themes[i].config.sitelogo);
            _taskName = _task.name + ':' + _prefix;
            _task.task.displayName = _taskName;
            _taskQueue.push(_task.task);
        } else {
            console.log('Skipping Site Logos generation...');
        }

        if (_themes[i].config.iconfont !== false) {
            console.log('Generate Iconfonts and Sass Map');
            _task = require('./task/iconfont')(gulp, taskSettings.PROJECT_PATH, _themePath, _themes[i].config.iconfont);
            _taskName = _task.name + ':' + _prefix;
            _task.task.displayName = _taskName;
            _taskQueue.push(_task.task);
        } else {
            console.log('Skipping Iconfonts generation...');
        }


        if (_themes[i].config.imagemin !== false) {
            console.log('Compress Images...');
            if (typeof _themes[i].config.imagemin === 'undefined') {
                _themes[i].config.imagemin = {};
            }
            _task = require('./task/imagemin')(gulp, taskSettings.PROJECT_PATH, _themePath, _themes[i].config.imagemin);
            _taskName = _task.name + ':' + _prefix;
            _task.task.displayName = _taskName;
            _taskQueue.push(_task.task);
        } else {
            console.log('Skipping Image Compression...');
        }

        if (_themes[i].config.sass !== false) {
            console.log('Compile SASS (Autoprefixer)...');
            if (typeof _themes[i].config.sass === 'undefined') {
                _themes[i].config.sass = {};
            }

            if (taskSettings.DEVELOPMENT_MODE === true) {
                _themes[i].config.sass.sourceMaps = true;
                _themes[i].config.sass.sassOptions = {
                    'outputStyle': 'expanded'
                };
            } else {
                _themes[i].config.sass.sourceMaps = false;
                _themes[i].config.sass.sassOptions = {
                    'outputStyle': 'compressed'
                };
            }

            _task = require('./task/sass')(gulp, taskSettings.PROJECT_PATH, _themePath, taskSettings.WEB_ROOT + taskSettings.BLANK_THEME, _themes[i].config.sass);
            _taskName = _task.name + ':' + _prefix;
            _task.task.displayName = _taskName;
            _taskQueue.push(_task.task);
        } else {
            console.log('Skipping Sass (Autoprefixer) Compilation...');
        }

        if (_themes[i].config.jslint !== false) {
            console.log('JShint ESLint...');
            if (typeof _themes[i].config.jslint === 'undefined') {
                _themes[i].config.jslint = {};
            }

            _task = require('./task/jslint')(gulp, taskSettings.PROJECT_PATH, _themePath, _themes[i].config.jslint);
            _taskName = _task.name + ':' + _prefix;
            _task.task.displayName = _taskName;
            _taskQueue.push(_task.task);
        } else {
            console.log('Skipping JShint ESLint...');
        }

        // @todo CSS/Style stats...
    }

    return gulp.series.apply(null, _taskQueue.concat([function themeCleanAllTask(seriesDone) {
        seriesDone();
        done();
    }]))();
}


/**
 * Set the Global Configs/Settings required for tasks
 * from application (yaml/json) data
 * @param done
 * @returns {*}
 */
function setConfig(done) {
    var applicationJSON = require('./.tmp/application'),
        magentoFrameworkKey = 'magento2',
        applicationSites = [],
        applicationSitesClone = [],
        i,
        _application;

    // Set the webroot
    if (typeof applicationJSON.webroot !== 'undefined') {
        taskSettings.WEB_ROOT = applicationJSON.webroot;
    }

    // Set Project KEY
    if (typeof applicationJSON.key !== 'undefined') {
        taskSettings.PROJECT_KEY = applicationJSON.key;
    }

    console.info('✔ Set Project Path to `' + taskSettings.PROJECT_PATH + '`' ); // Set within task/appconfig.js
    console.info('✔ Set Project Key to `' + taskSettings.PROJECT_KEY + '`' );
    console.info('✔ Set Web root to `' + taskSettings.WEB_ROOT + '`' );

    // Set Multi-site Theme
    if (typeof applicationJSON.applications !== 'undefined') {
        for (i = 0; i < applicationJSON.applications.length; i++) {
            _application = applicationJSON.applications[i];
            if (typeof _application.framework !== 'undefined') {
                if (_application.framework === magentoFrameworkKey) {
                    if (typeof _application.sites !== 'undefined') {
                        if (_application.sites.length > 0) {
                            applicationSites = _application.sites;
                        }
                    }
                }
            }
        }
    }

    // Check if its single site with prefix 'www',
    // if so set the applicationSites to empty array to
    // force single site compilation
    if (applicationSites.length === 1) {
        if (applicationSites[0].prefix === 'www') {
            applicationSites = [];
        }
    }

    // Clone array and re-order based on view.xml hierarchy
    applicationSitesClone = applicationSites.slice();

    var fs = require('fs'),
        xml2js = require('xml2js'),
        _xmlParser,
        _xmlData,
        _themePath,
        _maxThemeInheritance = 3,
        _counter = 0,
        _themeMap = {},
        _themeXML;

    function insertIntoSitesAsParent(idx, themeName) {
        var _isThemeFound;
        _isThemeFound;

        themeName = themeName.replace(taskSettings.VENDOR_THEME_POSTFIX, '');
        _isThemeFound = applicationSitesClone.map(function(x) {return x.prefix; }).indexOf(themeName);

        if ((_isThemeFound !== -1 && _isThemeFound > idx) || (_isThemeFound === -1)) {
            applicationSitesClone.splice(idx, 0, {
                code: themeName,
                prefix: themeName
            });
        }
    }

    function themeTraverse(themeXMLPath, idx, callback) {
        if (_counter > _maxThemeInheritance) {
            callback('Exit traversing due to Max theme inheritance of ' + _maxThemeInheritance);
            return;
        }
        try {
            _xmlParser = new xml2js.Parser();
            _xmlData = fs.readFileSync(themeXMLPath);
        } catch (err) {
            // console.log('\nNo `theme.xml` found for theme `' + themeXMLPath + '` Skipping ...');
            callback('Theme traversing end.');
            return;
        }
        _counter++;
        _xmlParser.parseString(_xmlData, function (err, result) {
            var _parentTheme,
                _parentThemeName,
                _parentThemeXMLPath;
            if (typeof result.theme !== 'undefined') {
                if (typeof result.theme.parent !== 'undefined') {
                    _parentTheme = result.theme.parent;
                    if (typeof _parentTheme[0] !== 'undefined') {
                        if (_parentTheme[0].indexOf('magesparrow-blank') === -1) {
                            _parentThemeName = _parentTheme[0].split('/').pop();
                            _parentThemeXMLPath = taskSettings.PROJECT_PATH
                                + taskSettings.WEB_ROOT
                                + '/app/design/frontend/'
                                + _parentTheme[0] + '/'
                                + taskSettings.THEME_XML;
                            insertIntoSitesAsParent(idx, _parentThemeName);
                            themeTraverse(_parentThemeXMLPath, idx, callback);
                        }
                    }
                }
            }
        });
    }

    for (i = 0; i < applicationSites.length; i++) {
        // @todo: Check if vendor based ie composerised theme and add it in
        // Set the Theme paths (Relative from webroot and with a trailing slash)
        _themePath = taskSettings.WEB_ROOT + taskSettings.VENDOR_THEME_PATH + applicationSites[i].prefix + taskSettings.VENDOR_THEME_POSTFIX + '/';

        _themeXML = taskSettings.PROJECT_PATH + _themePath + taskSettings.THEME_XML;

        try {
            fs.accessSync(_themeXML);
        } catch (err) {
           // console.log('\nNo `theme.xml` found for theme `' + _themeXML + '` Skipping ...');
            continue;
        }

        themeTraverse(_themeXML, i, function(msg){});
    }

    // Set Single Site theme, If Multi-site is not available
    if (applicationSitesClone.length === 0) {
        applicationSitesClone.push({
            code: 'base',
            prefix: taskSettings.PROJECT_KEY
        });
        console.info('✔ Set Single site theme `' + taskSettings.PROJECT_KEY + '`' );
    } else {
        console.info('✔ Set Multi-site themes...' );
    }

    var specificTheme,
        argIdx;

    specificTheme = false;
    argIdx = process.argv.indexOf('--theme');
    if (argIdx !== -1) {
        specificTheme = process.argv[argIdx+1];
    }

    var _specificTheme = [];
    if (specificTheme !== false && specificTheme !== 'false') {
        _specificTheme = applicationSitesClone.filter(function(_themeObj){
            return (_themeObj['prefix'] === specificTheme)
        });

        if (_specificTheme.length > 0) {
            applicationSitesClone = _specificTheme;
        }
    }

    taskSettings.SITES = taskSettings.SITES.concat(applicationSitesClone);

    for (i = 0; i < taskSettings.SITES.length; i++) {
        // @todo: Check if vendor based ie composerised theme and add it in
        // Set the Theme paths (Relative from webroot and with a trailing slash)
        _themePath = taskSettings.WEB_ROOT + taskSettings.VENDOR_THEME_PATH + taskSettings.SITES[i].prefix + taskSettings.VENDOR_THEME_POSTFIX + '/';
        taskSettings.SITES[i].themePath = _themePath;
    }


    return done();
}
