import {
    assertionFrom,
    stringify,
    Assertable,
    Assertion,
    Dictionary,
    Facet,
    Ref,
    Turn,
} from '@syndicate-lang/core';

export message type LogEntry(timestamp: string, detail: Dictionary<Ref>) = Symbol.for('log');

export let logTarget: Ref | null = null;
export let logId: Assertion | null = null;
export let logService: Assertion | null = null;
export let logFacet: Facet | null = null;

export function setupLog(target: Ref, id?: Assertable, service?: Assertable) {
    logTarget = target;
    logId = (id !== null && id !== void 0) ? assertionFrom(id) : null;
    logService = (service !== null && service !== void 0) ? assertionFrom(service) : null;
    logFacet = Turn.activeFacet;
}

export function log(... values: Assertable[]) {
    console.log(... values);
    logValues(values);
}

export function logValues(values: Assertable[]) {
    if (logFacet !== null && logFacet.isLive) {
        logFacet.turn(() => {
            if (logTarget === null) return;
            at logTarget {
                const d = new Dictionary<Ref>();
                if (logId !== null) d.set(Symbol.for('pid'), logId);
                if (logService !== null) d.set(Symbol.for('service'), logService);
                d.set(Symbol.for('line'), values.map(v => typeof(v) === 'string' ? v : stringify(v)).join(' '));
                send message LogEntry((new Date()).toISOString(), d);
            }
        });
    }
}

const oldConsoleError = console.error;
console.error = (... values: any[]) => {
    oldConsoleError(... values);
    logValues(['ERROR', ... values.map(v => '' + v)]);
};
