import { LogType } from "../types.js";
const filterToFunction = (item)=>{
    if ('string' == typeof item) {
        const regExp = new RegExp(`[\\\\/]${item.replace(/[-[\]{}()*+?.\\^$|]/g, '\\$&')}([\\\\/]|$|!|\\?)`);
        return (ident)=>regExp.test(ident);
    }
    if (item && 'object' == typeof item && 'function' == typeof item.test) return (ident)=>item.test(ident);
    if ('function' == typeof item) return item;
    if ('boolean' == typeof item) return ()=>item;
};
const LogLevel = {
    none: 6,
    false: 6,
    error: 5,
    warn: 4,
    info: 3,
    log: 2,
    true: 2,
    verbose: 1
};
const createConsoleLogger = ({ level = 'info', debug = false, console })=>{
    const debugFilters = 'boolean' == typeof debug ? [
        ()=>debug
    ] : [
        ...Array.isArray(debug) ? debug : [
            debug
        ]
    ].map(filterToFunction);
    const loglevel = LogLevel[`${level}`] || 0;
    const logger = (name, type, args)=>{
        const labeledArgs = ()=>{
            if (Array.isArray(args)) {
                if (args.length > 0 && 'string' == typeof args[0]) return [
                    `[${name}] ${args[0]}`,
                    ...args.slice(1)
                ];
                return [
                    `[${name}]`,
                    ...args
                ];
            }
            return [];
        };
        const debug = debugFilters.some((f)=>f(name));
        switch(type){
            case LogType.debug:
                if (!debug) return;
                if ('function' == typeof console.debug) console.debug(...labeledArgs());
                else console.log(...labeledArgs());
                break;
            case LogType.log:
                if (!debug && loglevel > LogLevel.log) return;
                console.log(...labeledArgs());
                break;
            case LogType.info:
                if (!debug && loglevel > LogLevel.info) return;
                console.info(...labeledArgs());
                break;
            case LogType.warn:
                if (!debug && loglevel > LogLevel.warn) return;
                console.warn(...labeledArgs());
                break;
            case LogType.error:
                if (!debug && loglevel > LogLevel.error) return;
                console.error(...labeledArgs());
                break;
            case LogType.trace:
                if (!debug) return;
                console.trace();
                break;
            case LogType.groupCollapsed:
                if (!debug && loglevel > LogLevel.log) return;
                if (!debug && loglevel > LogLevel.verbose) {
                    if ('function' == typeof console.groupCollapsed) console.groupCollapsed(...labeledArgs());
                    else console.log(...labeledArgs());
                    break;
                }
            case LogType.group:
                if (!debug && loglevel > LogLevel.log) return;
                if ('function' == typeof console.group) console.group(...labeledArgs());
                else console.log(...labeledArgs());
                break;
            case LogType.groupEnd:
                if (!debug && loglevel > LogLevel.log) return;
                if ('function' == typeof console.groupEnd) console.groupEnd();
                break;
            case LogType.time:
                {
                    if (!debug && loglevel > LogLevel.log) return;
                    const [label, start, end] = args;
                    const ms = 1000 * start + end / 1000000;
                    const msg = `[${name}] ${label}: ${ms} ms`;
                    if ('function' == typeof console.logTime) console.logTime(msg);
                    else console.log(msg);
                    break;
                }
            case LogType.profile:
                if ('function' == typeof console.profile) console.profile(...labeledArgs());
                break;
            case LogType.profileEnd:
                if ('function' == typeof console.profileEnd) console.profileEnd(...labeledArgs());
                break;
            case LogType.clear:
                if (!debug && loglevel > LogLevel.log) return;
                if ('function' == typeof console.clear) console.clear();
                break;
            case LogType.status:
                if (!debug && loglevel > LogLevel.info) return;
                if ('function' == typeof console.status) if (args && 0 !== args.length) console.status(...labeledArgs());
                else console.status();
                else if (args && 0 !== args.length) console.info(...labeledArgs());
                break;
            default:
                throw new Error(`Unexpected LogType ${type}`);
        }
    };
    return logger;
};
export default createConsoleLogger;
