"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var express_1 = require("express");
var url_1 = require("url");
var common_1 = require("./common");
var handler_file_1 = require("./handler.file");
var handler_redirect_1 = require("./handler.redirect");
var WebApp = (function () {
    function WebApp(options) {
        this.isStarted = false;
        this.router = express_1.Router();
        this._render = [];
        this.get = this.restHandler('get');
        this.put = this.restHandler('put');
        this.post = this.restHandler('post');
        this.delete = this.restHandler('delete');
        this.dev = optionValue('dev', common_1.constants.IS_DEV, options);
        this.port = optionValue('port', 3000, options);
        this.silent = optionValue('silent', false, options);
        this.staticPath = optionValue('static', './static', options);
        this.dir = optionValue('dir', './lib', options);
    }
    WebApp.init = function (options) {
        if (options === void 0) { options = {}; }
        return new WebApp(options);
    };
    Object.defineProperty(WebApp.prototype, "server", {
        get: function () {
            if (!this._server) {
                var nextApp = common_1.next({ dev: this.dev, dir: this.dir });
                var expressApp = common_1.express
                    .app()
                    .use(common_1.bodyParser.json({}))
                    .use(common_1.cookieParser())
                    .use(express_1.static(common_1.fsPath.resolve(this.staticPath)))
                    .use(common_1.cors({}))
                    .use(this.router);
                this._server = {
                    express: expressApp,
                    next: nextApp,
                };
            }
            return this._server;
        },
        enumerable: true,
        configurable: true
    });
    WebApp.prototype.restHandler = function (verb) {
        var _this = this;
        return function (url, handler) {
            _this.router[verb](url, handler);
            return _this;
        };
    };
    WebApp.prototype.use = function () {
        var _this = this;
        var handlers = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            handlers[_i] = arguments[_i];
        }
        handlers
            .filter(function (item) { return !(item instanceof WebApp); })
            .map(function (item) { return item; })
            .forEach(function (handler) { return _this.router.use(handler); });
        handlers
            .filter(function (item) { return item instanceof WebApp; })
            .map(function (app) { return app; })
            .forEach(function (app) {
            _this.router.use(app.router);
            _this._render = _this._render.concat(app._render);
        });
        return this;
    };
    WebApp.prototype.redirect = function (fromPath, toPath) {
        return this.use(handler_redirect_1.redirectHandler(fromPath, toPath));
    };
    WebApp.prototype.file = function (urlPath, filePath) {
        return this.use(handler_file_1.fileHandler(urlPath, filePath));
    };
    WebApp.prototype.static = function (urlPath, dirPath) {
        var middleware = express_1.static(common_1.fsPath.resolve(dirPath));
        this.router.use(urlPath, middleware);
        return this;
    };
    WebApp.prototype.render = function (urlPath, pagePath) {
        this._render = this._render.concat([{ urlPath: urlPath, pagePath: pagePath }]);
        return this;
    };
    WebApp.prototype.start = function (port) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var handle;
            var _this = this;
            return tslib_1.__generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (this.isStarted) {
                            return [2, this];
                        }
                        this.isStarted = true;
                        this._render.forEach(function (_a) {
                            var urlPath = _a.urlPath, pagePath = _a.pagePath;
                            _this.router.get(urlPath, function (req, res) {
                                var url = url_1.parse(req.url, true);
                                var pathname = pagePath || urlPath;
                                var query = tslib_1.__assign({}, req.params, req.query);
                                _this.server.next.render(req, res, pathname, query, url);
                            });
                        });
                        handle = this.server.next.getRequestHandler();
                        this.router.get('*', function (req, res) { return handle(req, res); });
                        return [4, this.server.next.prepare()];
                    case 1:
                        _a.sent();
                        port = port === undefined ? this.port : port;
                        return [4, listen(this, this.server.express, port)];
                    case 2:
                        _a.sent();
                        return [2, this];
                }
            });
        });
    };
    return WebApp;
}());
exports.WebApp = WebApp;
function optionValue(key, defaultValue, options) {
    return options && options[key] !== undefined
        ? options[key]
        : defaultValue;
}
var listen = function (app, express, port) {
    return new Promise(function (resolve, reject) {
        express.listen(port, function (err) {
            if (err) {
                reject(err);
            }
            else {
                logStarted(app, port);
                resolve();
            }
        });
    });
};
var logStarted = function (app, port) {
    if (app.silent) {
        return;
    }
    var PACKAGE = require(common_1.fsPath.resolve('./package.json'));
    var LIB_PACKAGE = require(common_1.fsPath.join(__dirname, '../../package.json'));
    common_1.log.info("> Ready on " + common_1.log.cyan('localhost') + ":" + common_1.log.magenta(port));
    common_1.log.info();
    common_1.log.info.gray("  name:    " + common_1.log.white(PACKAGE.name) + "@" + PACKAGE.version);
    common_1.log.info.gray("  dev:     " + app.dev);
    common_1.log.info.gray("  dir:     " + app.dir);
    common_1.log.info.gray("  static:  " + app.staticPath);
    common_1.log.info.gray("  react:   " + common_1.React.version);
    common_1.log.info.gray("  next:    " + LIB_PACKAGE.dependencies.next);
    var routes = common_1.express.routes(app.router);
    if (routes.length > 0) {
        common_1.log.info();
        common_1.log.info.cyan("  Routes:");
        routes
            .map(function (route) { return route.methods.map(function (method) { return ({ method: method, path: route.path }); }); })
            .reduce(function (acc, next) { return acc.concat(next); }, [])
            .forEach(function (route) {
            var method = (route.method + "     ").substr(0, 8);
            common_1.log.info("  " + common_1.log.magenta(method) + " " + route.path);
        });
    }
    common_1.log.info();
};
//# sourceMappingURL=WebApp.js.map