const http = require("http");
const jsl = require("svjsl");
const fs = require("fs-extra");
const crypto = require("crypto");
const settings = require("../settings");

jsl.unused([http]);


var previousDaemonHash;
var tokenList;

/**
 * Initializes the auth module
 */
const init = () => {
    return new Promise(resolve => {
        fs.exists(settings.auth.tokenListFile, exists => {
            if(!exists)
                fs.writeFileSync(settings.auth.tokenListFile, JSON.stringify([], null, 4));
            
            refreshTokens();
            setInterval(() => daemonInterval(), settings.auth.daemonInterval);
            return resolve();
        });
    });
};

/**
 * To be called on interval to check if the tokens should be refreshed
 */
function daemonInterval()
{
    let tokenFileRaw = fs.readFileSync(settings.auth.tokenListFile).toString();
    let tokenHash = crypto.createHash("md5").update(tokenFileRaw).digest("hex");

    if(previousDaemonHash == undefined)
        return;
    else if(previousDaemonHash != tokenHash)
    {
        previousDaemonHash = tokenHash;
        refreshTokens();
    }
}

/**
 * Refreshes the auth tokens in memory
 */
function refreshTokens()
{
    try
    {
        let tokens = JSON.parse(fs.readFileSync(settings.auth.tokenListFile).toString());
        tokenList = tokens;
    }
    catch(err)
    {
        tokenList = [];
        fs.writeFileSync(settings.auth.tokenListFile, JSON.stringify([], null, 4));
    }
}

/**
 * @typedef {Object} Authorization
 * @prop {Boolean} isAuthorized
 * @prop {String} token
 */

/**
 * Checks if the requester has provided an auth header and if the auth header is valid
 * @param {http.IncomingMessage} req 
 * @param {http.ServerResponse} [res] If not provided, users will not get the `Token-Valid` response header
 * @returns {Authorization}
 */
const authByHeader = (req, res) => {
    let isAuthorized = false;
    let requestersToken = "";

    if(req.headers && req.headers[settings.auth.tokenHeaderName])
    {
        if(Array.isArray(tokenList) && tokenList.length > 0)
        {
            tokenList.forEach(tokenObj => {
                if(tokenObj.token == req.headers[settings.auth.tokenHeaderName].toString())
                {
                    requestersToken = req.headers[settings.auth.tokenHeaderName].toString();
                    isAuthorized = true;
                }
            });
        }

        if(res && typeof res.setHeader == "function")
            res.setHeader(settings.auth.tokenValidHeader, (isAuthorized ? "1" : "0"));
    }

    return {
        isAuthorized: isAuthorized,
        token: requestersToken
    };
};

module.exports = { init, authByHeader };
