/*
 * Utility functions and classes
 * Created by: Michael Pastushkov <michael@pastushkov.com>
 */

'use strict';

const config = require('config');
const date = require('date-and-time');
const Formats = require('./formats');

const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
let log_level = config.general.log_level | 0;
let logcat_listeners = [];

function log(msg, level = 2, error = false, req) {

    if (level > log_level)
        return;

    let dst = Formats.DateTimeShort(new Date());
    
    if (config.server_api.cluster_enabled && log_level > 2)
        dst += ` ${process.pid}`;

    let str = msg;
    if (typeof msg == 'object') {
        str = JSON.stringify(msg);
        if (level < 5 && str.length > 100)
            str = str.substring(0, 100) + ' ...';
    }

    if (req && req.headers['user-agent'])
        str = `[${req.headers['user-agent']}]: ${str}`;

    if (error)
        console.error(dst + ' ' + str);
    else
        console.log(dst + ' ' + str);

    // Logcat
    for (let l of logcat_listeners)
        l(dst + ' ' + str);
}

async function set_log_level(level) {
    log_level = level;
}

function log_error(err, req) {
    if (err.stack && err.message) {
        log(err.stack, 0, true, req);
    } else {
        log(err, 0, true, req);
    }
}

function get_ip(req) {
    return req.headers['x-forwarded-for'] || req.socket.remoteAddress || null;
}

function is_empty(object) {
    return !object || Object.keys(object).length == 0
}

// Random string generator
function randomString(length, type) {
    let str = '';
    let len = type == "numeric" ? 10 : chars.length;
    for (let i = 0; i < length; i++) {
        str += chars.charAt(Math.floor(Math.random() * len));
    }
    return str;
}

// Converting CSV buffer (usually from file upload)
// to array of objects
function convert_csv(buf) {

    let arr = [];
    let txt = buf.toString();
    let lns = txt.split('\n');

    // Convert csv into array of objects
    let fields;
    for (let i = 0; i < lns.length; i++) {
        if (!lns[i])
            continue;
        let elems = lns[i].split(',');
        elems = elems.map(elem => {
            return elem.trim();
        });
        if (i == 0) {
            fields = elems;
        } else {
            // Scan through data and create records
            rec = {};
            for (let j = 0; j < fields.length; j++) {
                rec[fields[j]] = elems[j];
            }
            arr.push(rec);
        }
    }

    return arr;
}

function remove_whitespace(s) {
    return s.replace(/\s+/g, ' ').trim();
}

function add_logcat(listener) {
    logcat_listeners.push(listener);
}

function remove_logcat(listener) {
    for (let i = logcat_listeners.length-1; i >= 0; i--)
        if (logcat_listeners[i] === listener)
            logcat_listeners.splice(i, 1);
}

function parse(json) {
    try {
        return JSON.parse(json);
    } catch (e) {
        log(e.message, 4);
        return null;
    }
}

module.exports.set_log_level = set_log_level;
module.exports.log = log;
module.exports.log_error = log_error;
module.exports.get_ip = get_ip;
module.exports.is_empty = is_empty;
module.exports.randomString = randomString;
module.exports.convert_csv = convert_csv;
module.exports.remove_whitespace = remove_whitespace;
module.exports.add_logcat = add_logcat;
module.exports.remove_logcat = remove_logcat;
module.exports.parse = parse;