var gulp = require('gulp');
var gutil = require('gulp-util');
var wrap = require('gulp-wrap');
var concat = require('gulp-concat');
var extend = require('gulp-extend');
var fs = require('fs');
var merge = require('merge-stream');
var del = require('del');
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');

// Configuration

var srcDir = './client';
var buildDir = './services/nginx/static';
var langs = ['es', 'en'];

var modules = require('./spliting/modules.json');
var webpackConfig = require('./webpack.config.js');

// Main tasks

gulp.task('build', ['clean'], function() {
    return gulp.start('routes', 'locales', 'webpack');
});

gulp.task('default', ['clean'], function() {
    return gulp.start('services', 'watch', 'routes', 'locales', 'webpack-dev-server');
});

gulp.task('client', ['clean'], function() {
    return gulp.start('watch', 'routes', 'locales', 'webpack-dev-server');
});

gulp.task('clean', function() {
    return del(`${buildDir}/*`, {force: true});
});

// Spliting

var splitingFiles = './spliting/*';

gulp.task('spliting', function(cb) {
    var importTpl = fs.readFileSync('./spliting/import.tpl.js', 'utf8');
    var requireTpl = fs.readFileSync('./spliting/require.tpl.js', 'utf8');

    for (var modName in modules) {
        var deps = modules[modName];
        var splitFile = `${srcDir}/${modName}/src/spliting.js`;

        try {
            fs.unlinkSync(splitFile);
        } catch (e) {}

        fs.appendFileSync(splitFile, importTpl);

        var i = deps.length;
        while (i--)
            fs.appendFileSync(splitFile,
				requireTpl.replace(/\$module/g, deps[i]));
    }

    cb();
});

// Webpack

gulp.task('webpack', ['spliting'], function(cb) {
    var configCopy = Object.create(webpackConfig);
    var compiler = webpack(configCopy);

    compiler.run(function(err, stats) {
        if (err) throw new gutil.PluginError('webpack', err);
        gutil.log('[webpack]', stats.toString({colors: true}));
        cb();
    });
});

gulp.task('webpack-dev-server', ['spliting'], function() {
    var configCopy = Object.create(webpackConfig);

    for (var entry in configCopy.entry) {
        configCopy.entry[entry]
            .unshift('webpack-dev-server/client?http://0.0.0.0:8081/');
    }

    var compiler = webpack(configCopy);
    new WebpackDevServer(compiler, {
        publicPath: '/',
        contentBase: buildDir,
        quiet: false,
        noInfo: false,
		// hot: true,
        stats: {
            assets: true,
            colors: true,
            version: false,
            hash: false,
            timings: true,
            chunks: false,
            chunkModules: false
        }
    }).listen(8081, '0.0.0.0', function(err) {
        if (err) throw new gutil.PluginError('webpack-dev-server', err);
    });
});

// Locale

var localeFiles = `./${srcDir}/**/locale/*.json`;

gulp.task('locales', function() {
    var streams = [];

    for (var mod in modules)
        for (var lang of langs) {
            var localeFiles = `./client/${mod}/**/locale/${lang}.json`;
            streams.push(gulp.src(localeFiles)
                .pipe(extend(`${lang}.json`))
                .pipe(gulp.dest(`${buildDir}/locale/${mod}`)));
        }

    return merge(streams);
});

// Routes

var routeFiles = `./${srcDir}/**/routes.json`;

gulp.task('routes', function() {
    function cb(file) {
        var relative = file.relative.replace(/\\/g, '/');
        var dirname = relative.match(/^(.*)\/routes\.json$/)[1];
        return {
            dirname: dirname,
            json: file.contents
        };
    }

    return gulp.src(routeFiles)
		.pipe(wrap('\n"<%=dirname%>": <%=json%>', cb))
		.pipe(concat('routes.js', {newLine: ','}))
		.pipe(wrap('var routes = {<%=contents%>\n};'))
		.pipe(gulp.dest(buildDir));
});

// Watch

gulp.task('watch', function() {
    gulp.watch(splitingFiles, ['spliting']);
    gulp.watch(routeFiles, ['routes']);
    gulp.watch(localeFiles, ['locales']);
});

// Services

gulp.task('services', function() {
    var auth = require('./services/auth/server/server.js');
    var client = require('./services/client/server/server.js');
    var server = require('./services/salix/server/server.js');

    auth.start();
    client.start();
    server.start();
});