const http = require("http")
    ,https = require("https")
    ,clientSession = require("client-sessions")

    ,Url = require("./url.js").Url
    ,config = require("../config.js")
    ,sessionManager = require("./session.js").SessionManager
    ,AccountController = require("./controller/accountController.js").AccountController
    ,ApiController = require("./controller/apiController.js").ApiController
    ,MultiChatManager = require("./multichatManager.js").MultiChatManager
    ,AccountManager = require("./models/accounts.js").accountManager
    ,Slack = require("./slack.js").Slack
    ,slackManager = require("./slackManager.js").SlackManager
    ,FaviconWriter = require("./faviconWriter.js").FaviconWriter;

function Server() {
    var ctx = this;

    this.httpServ = http.createServer(function(req, res) {
        res.ended = false;
        res.on('end', () => {
            res.ended = true;
        });
        ctx.onRequest(req, res);
    });
    this.httpServ.listen(config.port, ctx.onListen);
}

Server.parseCookies = function(req) {
    var cookies = req.headers.cookie
    ,cookieObj = null;

    if (cookies) {
    cookieObj = {};
        cookies = cookies.split(";");
    for (var cookieIndex =0, nbCookies =cookies.length; cookieIndex < nbCookies; cookieIndex++) {
        var cookieParts = cookies[cookieIndex].indexOf("=")
        ,cookieKey = null
        ,cookieValue = null;

            if (cookieParts === -1) {
        cookieKey = cookies[cookieIndex].trim();
        } else {
        cookieKey = cookies[cookieIndex].substr(0, cookieParts).trim();
        cookieValue = cookies[cookieIndex].substr(cookieParts +1).trim();
        }
        cookieObj[cookieKey] = cookieValue;
    }
    }
    return cookieObj;
};

Server.stringifyCookies = function(cookies) {
    var cookieString = "";
    for (var cookieKey in cookies) {
    cookieString += cookieString;
    if (cookies[cookieString] !== null) {
        cookieString += "=";
    }
    cookieString += "; ";
    }
    return cookieString;
};

Server.prototype.onListen = function() {
    console.log("onListen");
};

Server.prototype.execTemplate = function(template, req, res) {
    var resp = template.exec(req, res, this);
    if (resp && resp.body) {
        if (resp.status)
            res.writeHeader(resp.status);
        res.end(resp.body);
    }
    // else something is running asynchronously, let template close request later..
};

Server.prototype.execRequest = function(req, res) {
    if (req.urlObj.isTemplate() && req.urlObj.template.needLogin === false) {
        return this.execTemplate(req.urlObj.template, req, res);
    } else if (req.urlObj.isPublic()) {
        if (!config.isDebug)
            res.setHeader('Cache-Control', 'private, max-age=' +15 * 60);
        res.setHeader('Content-Length', req.urlObj.serve.stat.size);
        res.writeHeader("200");
        req.urlObj.getReadStream().pipe(res, { end: true });
        sessionManager.saveSession(req.session);
        return; // async pipe will close when finished
    } else if (!req.account) {
        res.writeHeader("302", { Location: "login" });
        res.end();
    } else if (req.urlObj.isTemplate()) {
        return this.execTemplate(req.urlObj.template, req, res);
    } else if (req.urlObj.match(["favicon.png"])) {
        if (!config.isDebug)
            res.setHeader('Cache-Control', 'private, max-age=' +15 * 60);
        var unreadHi = (req.urlObj.queryTokens.h && req.urlObj.queryTokens.h[0]) ? parseInt(req.urlObj.queryTokens.h[0], 10) : 0
            ,unread = (req.urlObj.queryTokens.m && req.urlObj.queryTokens.m[0]) ? parseInt(req.urlObj.queryTokens.m[0], 10) : 0;
        FaviconWriter.write(unreadHi, unread, (buf) => {
            res.writeHeader("200");
            res.end(buf);
        });
        sessionManager.saveSession(req.session);
        return;
    } else {
        // Api / dynamic content
        var apiSuccess = false;

        res.chatContext = new MultiChatManager();
        res.chatContext.push(slackManager.lazyGet(req.session, req.reqT));

        if (req.urlObj.urlParts[0] === "account") {
            AccountController.onRequest(req, res, this);
        } else if (req.urlObj.urlParts[0] === "api") {
            ApiController.onRequest(req, res, this);
        } else {
            this.execTemplate(require('./template/_404.js'), req, res);
        }
    }
};

Server.prototype.onRequest = function(req, res) {
    req.reqT = Date.now();
    req.cookies = Server.parseCookies(req);
    req.session = sessionManager.forRequest(req);
    req.urlObj = new Url(req.url);
    req.account = null;
    if (req.session) {
        var self = this;
        AccountManager.fromId(req.session.accountId, (acc) => {
            req.account = acc;
            self.execRequest(req, res);
        });
    } else {
        this.execRequest(req, res);
    }
};

module.exports.HttpServ = Server;

