const {
    Worker, isMainThread, parentPort, workerData
} = require('worker_threads');

const log4js = require("log4js");

class LoggerWrapper{
    worker = null;

    constructor(logConfig){
        this.worker = new Worker(__filename, {
            workerData: logConfig
        });
    }

    trace(logContent,...args){
        this.worker.postMessage({level:'trace', logContent: logContent, args: args});
    }

    debug(logContent,...args){
        this.worker.postMessage({level:'debug', logContent: logContent, args: args});
    }

    info(logContent,...args){
        this.worker.postMessage({level:'info', logContent: logContent, args: args});
    }

    warn(logContent,...args){
        this.worker.postMessage({level:'warn', logContent: logContent, args: args});
    }

    error(logContent,...args){
        this.worker.postMessage({level:'error', logContent: logContent, args: args});
    }

    fatal(logContent,...args){
        this.worker.postMessage({level:'fatal', logContent: logContent, args: args});
    }

    exit(){
        this.worker.postMessage({command:'exit'});
    }
}

let loggerWrapper = null;

if(!isMainThread){
    log4js.configure(workerData);
    let realLogger = log4js.getLogger(workerData.category);
    realLogger.level = "debug";

    parentPort.on('message',(msg)=>{
        if(msg.command == 'exit'){
            exit();
            return;
        }
        switch(msg.level){
            case "trace":
                realLogger.trace(msg.logContent, ... msg.args);
                break;
            case "debug":
                realLogger.debug(msg.logContent, ... msg.args);
                break;
            case "info":
                realLogger.info(msg.logContent, ... msg.args);
                break;
            case "warn":
                realLogger.warn(msg.logContent, ... msg.args);
                break;
            case "error":
                realLogger.error(msg.logContent, ... msg.args);
                break;
            case "fatal":
                realLogger.fatal(msg.logContent, ... msg.args);
                break;
        }
    });
}

function exit(){
    //@ts-ignore
    if(process._getActiveRequests().length > 0){
        setTimeout(exit, 1000);
    }
    else{
        process.exit();
    }
}

function getLogger(config) {
    if(!loggerWrapper && isMainThread){
        loggerWrapper = new LoggerWrapper(config);
    }
    return loggerWrapper;
}

module.exports = {getLogger}