'use strict';

let connect = require('connect'),
    http = require('http'),
    serveStatic = require('serve-static'),
    serveIndex = require('serve-index'),
    moment = require('moment'),
    livereload = require('livereload'),
    connectLivereload = require('connect-livereload'),
    webpackDevMiddleware = require("webpack-dev-middleware");

let Manager = require('../modules/manager.js');

exports.usage = "开发服务";

exports.setOptions = (optimist) => {
    optimist.alias('s', 'https');
    optimist.describe('s', '使用https协议');
    optimist.alias('p', 'port');
    optimist.describe('p', '端口');
    optimist.alias('m', 'middlewares');
    optimist.describe('m', '加载项目中间件');
    optimist.alias('l', 'livereload');
    optimist.describe('l', '实时自动刷新');
};

exports.run = (options) => {
    let app = connect(),
        cwd = options.cwd,
        hot = options.h || options.hot,
        middlewares = options.m || options.middlewares,
        https = options.s || options.https,
        enableLivereload = options.l || options.livereload,
        port = options.p || options.port || 80;

    let middlewareCache = {};

    if (middlewares) {
        middlewares.split('|').forEach((proName) => {
            let pro = Manager.getProject(sysPath.join(cwd, proName));
            if (pro.check() && Array.isArray(pro.middlewares)) {
                pro.middlewares.forEach((mw) => app.use(mw));
            }
        })
    }

    // logger
    app.use(() => {
        const dateFormat = 'YY.MM.DD HH:mm:ss';
        const parse = function(req, res, format) {
            const status = (function() {
        		switch (true) {
        			case 500 <= res.statusCode:
        				return '\x1b[31m';
        			case 400 <= res.statusCode:
        				return '\x1b[33m';
        			case 300 <= res.statusCode:
        				return '\x1b[36m';
        			case 200 <= res.statusCode:
        				return '\x1b[32m';
        		}
        	})();

            let contentLength = res._contentLength || '';
            if(contentLength){
                contentLength = contentLength > 1024
                                ? (contentLength / 1024).toFixed(2) + 'kB '
                                : contentLength + 'bytes ';
            }

        	format = format.replace(/%date/g, "\x1b[90m" + '[' + (moment().format(dateFormat)) + ']' + "\x1b[0m");
        	format = format.replace(/%method/g, "\x1b[35m" + (req.method.toUpperCase()) + "\x1b[0m");
        	format = format.replace(/%url/g, "\x1b[90m" + decodeURI(req.originalUrl) + "\x1b[0m");
        	format = format.replace(/%status/g, "" + status + res.statusCode + "\x1b[0m");
            format = format.replace(/%route/g, "\x1b[90m" + (req.route ? req.route.path + ' ' : '\x1b[31m') + "\x1b[0m");
        	format = format.replace(/%contentLength/g, "\x1b[90m" + contentLength + '\x1b[31m' + "\x1b[0m");
        	format = format.replace(/%(date|time)/g, "\x1b[90m" + (new Date - req._startTime) + "ms\x1b[0m");
        	return format;
        };

        return (req, res, next) => {
            const end = res.end;
        	req._startTime = new Date;

        	res.end = (chunk, encoding) => {
        		res.end = end;
        		res.end(chunk, encoding);
                const format = '%date %status %method %url (%route%contentLength%time)'
        		const message = parse(req, res, format);
        		return process.nextTick(() => {
        			return info(message);
        		});
        	};
        	return next();
        };
    }());

    app.use((req, res, next) => {
        let url = req.url,
            keys = url.split('/');

        if (keys[2] == 'prd') {
            let projectName = keys[1],
                projectCwd = sysPath.join(cwd, projectName),
                middleware = middlewareCache[projectName];

            if (!middleware) {
                let project = Manager.getProject(projectCwd);
                if (project.check()) {
                    let compiler = project.getServerCompiler();
                    middleware = middlewareCache[projectName] = webpackDevMiddleware(compiler, {noInfo: true});
                } else {
                    next();
                    return;
                }
            }
            req.url = '/' + keys.slice(3).join('/').replace(/(\@[\d\w]+)?\.(js|css)/, '.$2');
            middleware(req, res, next);
        } else {
            next();
        }
    });

    if(enableLivereload){
        livereload.createServer().watch(cwd);
        app.use(connectLivereload({port: 35729}));
    }

    app.use(serveStatic(cwd, {
        redirect: false,
        index: false
    }));

    app.use(serveIndex(cwd));

    http.createServer(app).listen(port, () => {
        warn('Listening on port ' + port);
    });

    // 权限降级
    if (process.env['SUDO_UID']) {
        process.setuid(parseInt(process.env['SUDO_UID']));
    }
};

@@ -4072,23 +4072,661 @@
 r, %7B
-noInfo: true%7D);
+quiet: true%7D);%0A%0A                    // %E8%BE%93%E5%87%BAserver%E8%BF%90%E8%A1%8C%E4%B8%AD error/warning %E4%BF%A1%E6%81%AF%0A                    compiler.watch(%7B%7D, function(err, stats) %7B%0A                        const statsInfo = stats.toJson(%7BerrorDetails: true%7D),%0A                            logMethods = %7B%0A                                errors: error,%0A                                warnings: warn%0A                            %7D;%0A%0A                        Object.keys(logMethods).map((typeId) =%3E %7B%0A                            statsInfo%5BtypeId%5D.map((logInfo) =%3E %7B%0A                                logMethods%5BtypeId%5D(logInfo);%0A                            %7D);%0A                        %7D);%0A                    %7D);%0A
 %0A   

优化error/warning log信息