/**

 __
(  )   _____  ___   ___  ____  ____ 
 )(   (  _  )/ __) / __)( ___)(  _ \
 )(__  )(_)(( (_-.( (_-. )__)  )   /
(____)(_____)\___/ \___/(____)(_)\_)
                        By Mike & Nike
                                                  
This file is part of Sparc by Mike & Nike.
Widgets is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, 
either version 3 of the License, or (at your option) any later version.
Widgets is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
See the GNU General Public License for more details.
Get your copy of the GNU General Public License at <https://www.gnu.org/licenses/>. 
 * @category Core
 * @subcategory Libraries
 * @class
 * @todo extract from app (this is just a hook for window.console)
 * @param {object} nativeConsole a reference to the native browser console (Typically window.console )
 * @param {object} config 
*/
app.logger = function(oldCons, config){
    const appendErr = (data) => {
        data['errId'] = crypto.randomUUID()
        app.latestErrors.push(data)
        let maxentries = config.latestErrsMax || 10;
        while(app.latestErrors.length > maxentries) app.latestErrors.shift()
    }

    const getCircularReplacer = () => {
        const seen = new WeakSet();
        return (key, value) => {
          if (typeof value === "object" && value !== null) {
            if (seen.has(value)) {
              return;
            }
            seen.add(value);
          }
          return value;
        };
    };
    const formater = function(err, args, color){
        var splitter = function(stkLine, mode){
            if(mode=='chrome'){
                var buf = stkLine.substr(0,stkLine.indexOf(' ('));
                var funcName = buf.substr(buf.lastIndexOf('.')+1);
                var buf = stkLine.substr(stkLine.lastIndexOf('/')+1);
                var scriptname = buf.substr(0,buf.indexOf('.js')+3);
                var lincol = buf.substr(buf.indexOf(':')+1).split(':');  
            } else {
                var funcName = stkLine.substr(0,stkLine.indexOf('@'));
                if(funcName.indexOf('/')>-1) funcName = funcName.substr(0,funcName.indexOf('/'));
                var buf = stkLine.substr(stkLine.lastIndexOf('/')+1);
                var scriptname = buf.substr(0,buf.indexOf('.js')+3);
                var lincol = buf.substr(buf.indexOf(':')+1).split(':');
            }
            return([funcName, scriptname, lincol]);
        }
        var lines = err.stack.split('\n'); var nice_stack=[];
        var funcName, scriptname, lincol;
        if(lines[0].toLowerCase()=='error'){ // Chrome & Edge style
            [funcName, scriptname, lincol] = splitter(lines[2], 'chrome');
            lines.shift();lines.shift();
            for(var line of lines) nice_stack.push(splitter(line, 'chrome'));
        } else { // Firefox style
            [funcName, scriptname, lincol] = splitter(lines[1], 'ff');
            lines.shift();
            for(var line of lines) nice_stack.push(splitter(line, 'ff'));
        }
        var msg = args[0];
        args[0] = `${args[0]} %c${funcName} @ ${scriptname} : ${lincol}`;
        args.splice(1,0,'background-color:'+color+';color:#FFF;font-weight:bold;float:right;padding:2px 5px 2px 5px;border-radius:4px;');
        return([args, msg, nice_stack]);
    }
    return {
        nativeConsoleAPI:'', //noooo, the console is NOT changed... or is it ;-)
        trace: oldCons.trace,
        log: function(...args){
            if(typeof(args[0])!='string') args.unshift('');
            var nice_stack, msg;
            var err = new Error();
            [args, msg, nice_stack] = formater(err, args, '#070');
            oldCons.log(...args);
        },
        info: function (...args) {
            if(typeof(args[0])!='string') args.unshift('');
            var nice_stack, msg;
            var err = new Error();
            [args, msg, nice_stack] = formater(err, args, '#070');
            oldCons.info(...args);
        },
        warn: function (...args) {
            if(typeof(args[0])!='string') args.unshift('');
            var nice_stack, msg;
            var err = new Error();
            var msgData = (args.length>1) ? args.slice(1) : '';
            [args, msg, nice_stack] = formater(err, args, '#C90');           
            oldCons.warn(...args);
            if(config.levels.indexOf('warn')<0) return;
            let data = {'level':'WARNING',
                        'message': msg,
                        'messageData' : msgData,
                        'user': app.User,
                        'timestamp':(new Date).toISOString().replace(/[A-Z]/g,' ').trim() ,
                        'url': document.location.toString(),
                        'stacktrace' : nice_stack,
                    };
            if(config.postUrl.startsWith('https://')){
                fetch(config.postUrl, {
                    'method': 'POST',
                    'body' : JSON.stringify(data, getCircularReplacer()),
                    'headers': {'Content-type': 'application/json; charset=UTF-8'}
                })
            }
            appendErr(data);
        },
        error: function (...args) {
            if(typeof(args[0])!='string') args.unshift('');
            var nice_stack, msg;
            var err = new Error();
            var msgData = (args.length>1) ? args.slice(1) : '';
            [args, msg, nice_stack] = formater(err, args, '#900');            
            oldCons.error(...args);
            if(config.levels.indexOf('err')<0) return;
            let data = {'level':'ERROR',
                        'message': msg,
                        'messageData' : msgData,
                        'user': app.User,
                        'timestamp':(new Date).toISOString().replace(/[A-Z]/g,' ').trim() ,
                        'url': document.location.toString(),
                        'stacktrace' : nice_stack,
                    };
            if(config.postUrl.startsWith('https://')){
                fetch(config.postUrl, {
                    'method': 'POST',
                    'body' : JSON.stringify(data, getCircularReplacer()),
                    'headers': {'Content-type': 'application/json; charset=UTF-8'}
                })
            }
            appendErr(data);
        }
    };
};
