/**
 * server.js
 * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
 *
 * Contact:
 * Sungmin Kim <sm.art.kim@samsung.com>
 * Jonghwan Park <iwin100.park@samsung.com>
 * Kitae Kim <kt920.kim@samsung.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Contributors:
 * - S-Core Co., Ltd
**/

var express = require('express.io');
var httpProxy = require('http-proxy');

var dibs = require('../../core/dibs.js');
var db = require('../../lib/db-connection.js');
var app = require('./controllers/app.js');
var userCtrl = require('./controllers/user.js');
var jobCtrl = require('./controllers/job.js');
var distCtrl = require('./controllers/distribution.js');
var projectCtrl = require('./controllers/project.js');
var serverCtrl = require('./controllers/server.js');
var serverConfigCtrl = require('./controllers/serverconfig.js');
var pluginCtrl = require('./controllers/plugin.js');
var statisticsCtrl = require('./controllers/statistics.js');
var releaseCtrl = require('./controllers/release.js');
var approvalCtrl = require('./controllers/approval.js');
var log = require('./controllers/log.js');

module.exports.createServer = function (serverId) {
    WebServer.prototype = dibs.BaseServer.createServer(serverId, 'web');
    return new WebServer();
};

function WebServer() {
    var self = this;
    var server = express();
    this.name = 'web';
    this.logger = null;

    this.sessionStore = new express.session.MemoryStore();

    //Logger format for DIBS
    express.logger.format('dibs', function (tokens, req, res) {
        var status = res.statusCode;
        var len = parseInt(res.getHeader('Content-Length'), 10);
        var color = 32;

        if (status >= 500) {
            color = 31;
        } else if (status >= 400) {
            color = 33;
        } else if (status >= 300) {
            color = 36;
        }

        len = isNaN(len) ? '' : len = ' - ' + len;

        return res.statusCode +
            req.ip + ' ' +
            req.method + ' ' +
            req.originalUrl + ' ' +
            res.statusCode + ' ' +
            (new Date() - req._startTime) + 'ms' + len + ' ';
    });

    // Logger stream to DIBS
    var dibsLogStream = {
        write: function (data) {
            var status = data.slice(0, 3);
            var message = data.slice(3);

            //remove new line
            message = message.replace(/\n/g, '');

            if (status < 400) {
                self.log.info(message);
            } else if (status >= 500) {
                self.log.error(message);
            } else if (status >= 400) {
                self.log.warn(message);
            }
        }
    };


    // CALLBACK: for creating server's default configuration
    this.getDefaultConfiguration = function (baseConfig) {
        var defaultConfig = baseConfig;
        defaultConfig.web_port = 3277;
        return defaultConfig;
    };


    this.OnServerStarting = function (callback) {
        callback(null);
    };

    this.OnServerStarted = function (callback) {
        startWeb(self.config.get('web_port'));

        self.dbConn = db.createDBConnectionPool();
        callback(null);
    };


    var startWeb = function (port) {
        self.log.info('Start web server - listen: ' + port);
        server.http().io();

        var proxy = httpProxy.createProxyServer({});

        // http
        server.use(express.logger({
            format: 'dibs',
            stream: dibsLogStream
        }));
        server.use('/upload', function (req, res) {
            var repos = dibs.getServersByType('repo');
            if (repos.length === 0) {
                res.status(503).send(JSON.stringify(new Error('No repository server')));
            } else {
                var host = repos[0].host;
                var webPort = repos[0].config.get('web_port');
                proxy.web(req, res, {
                    target: 'http://' + host + ':' + webPort + '/upload'
                });
            }
        });
        server.use('/repository', function (req, res) {
            var repos = dibs.getServersByType('repo');
            if (repos.length === 0) {
                res.status(503).send(JSON.stringify(new Error('No repository server')));
            } else {
                var host = repos[0].host;
                var webPort = repos[0].config.get('web_port');

                proxy.web(req, res, {
                    target: 'http://' + host + ':' + webPort + '/repository'
                });
            }
        });
        server.use('/plugins', express.static(__dirname + '/../../web-plugins'));
        server.use(express.static(__dirname + '/app'));
        server.use(express.bodyParser({
            limit: 1024 * 1024 * 1024 * 4
        })); // Max file size is 4G
        server.use(express.methodOverride());
        // setting session
        server.use(express.cookieParser());
        server.use(express.session({
            secret: 'tizen',
            store: self.sessionStore
        }));
        server.use(app.router.middleware);
        server.use(userCtrl.router.middleware);
        server.use(jobCtrl.router.middleware);
        server.use(distCtrl.router.middleware);
        server.use(projectCtrl.router.middleware);
        server.use(serverCtrl.router.middleware);
        server.use(serverConfigCtrl.router.middleware);
        server.use(pluginCtrl.router.middleware);
        server.use(statisticsCtrl.router.middleware);
        server.use(releaseCtrl.router.middleware);
        server.use(approvalCtrl.router.middleware);
        // web socket
        server.io.enable('browser client etag');
        server.io.set('log level', 3);
        server.io.route('log', log.route);

        // start
        server.listen(port);
    };
}

/**
 * @function createServer
 * @param {string} serverId - serverId
 * @returns {string}
 * @memberOf module:servers/web/server
 */


/**
 * @module servers/web/server
 */
