// Copyright (c) 2026 Modelware. All rights reserved.
import { appendInlineValue, createWikiLinkElement, isUrlValue, shortLabelFromIri } from './wikilink-utils.js';
let iriLabelSnapshot;
export function setIriLabelSnapshot(snapshot) {
    if (!snapshot) {
        iriLabelSnapshot = undefined;
        return;
    }
    if (snapshot instanceof Map) {
        iriLabelSnapshot = snapshot;
        return;
    }
    iriLabelSnapshot = new Map(Object.entries(snapshot).map(([iri, label]) => [normalizeIriLabelKey(iri), String(label)]));
}
export function runWithIriLabelSnapshot(snapshot, action) {
    const previous = iriLabelSnapshot;
    setIriLabelSnapshot(snapshot);
    try {
        return action();
    }
    finally {
        iriLabelSnapshot = previous;
    }
}
/** Return the label annotation for an IRI from the snapshot, or empty string if none. No fallback to name-from-IRI. */
export function labelFromIriSnapshot(iri) {
    const normalized = normalizeIriLabelKey(iri);
    if (!normalized) {
        return '';
    }
    const labeled = iriLabelSnapshot?.get(normalized);
    return typeof labeled === 'string' ? labeled : '';
}
export function displayLabelFromIri(iri) {
    const normalized = normalizeIriLabelKey(iri);
    if (!normalized) {
        return iri;
    }
    const labeled = iriLabelSnapshot?.get(normalized);
    if (typeof labeled === 'string' && labeled.length > 0) {
        return labeled;
    }
    const fragmentIndex = normalized.lastIndexOf('#');
    if (fragmentIndex >= 0 && fragmentIndex < normalized.length - 1) {
        return decodeIriLabelSegment(normalized.slice(fragmentIndex + 1));
    }
    const withoutQuery = normalized.split('?')[0]?.replace(/\/+$/, '') ?? normalized;
    const slashIndex = withoutQuery.lastIndexOf('/');
    if (slashIndex >= 0 && slashIndex < withoutQuery.length - 1) {
        return decodeIriLabelSegment(withoutQuery.slice(slashIndex + 1));
    }
    return normalized;
}
function normalizeIriLabelKey(iri) {
    return String(iri ?? '').trim().replace(/^<|>$/g, '');
}
function decodeIriLabelSegment(value) {
    try {
        return decodeURIComponent(value);
    }
    catch {
        return value;
    }
}
export class BaseMarkdownBlockRenderer {
    createResultContainer(status) {
        const container = document.createElement('div');
        container.className = `oml-md-result oml-md-result-${status}`;
        return container;
    }
    createMessageContainer(text) {
        const message = document.createElement('div');
        message.className = 'oml-md-result-message';
        message.textContent = text;
        return message;
    }
    requestTextFileDownload(content, fallbackName = 'download', fileExtension = 'txt') {
        const filename = this.buildDownloadFileName(fallbackName, fileExtension);
        const event = new CustomEvent('md-download-file', {
            detail: { filename, content },
        });
        window.dispatchEvent(event);
    }
    buildDownloadFileName(fallbackName, fileExtension) {
        const sourceUri = document.body.getAttribute('data-source-uri') ?? '';
        let namePart = fallbackName;
        if (sourceUri) {
            const fileName = sourceUri.split('/').pop() ?? '';
            const fileStem = fileName.replace(/\.[^.]+$/, '');
            if (fileStem) {
                namePart = fileStem;
            }
        }
        const sanitized = namePart.replace(/\W+/g, '_');
        const ts = new Date().toISOString().replace(/[:.]/g, '-');
        const extension = fileExtension.replace(/^\./, '') || 'csv';
        return `${sanitized}_${ts}.${extension}`;
    }
}
export class QueryMarkdownBlockRenderer extends BaseMarkdownBlockRenderer {
    renderCellValue(raw, typedValue) {
        const value = document.createElement('span');
        value.className = 'table-value';
        const entries = typedValue?.values ?? [];
        if (entries.length > 0) {
            entries.forEach((entry, index) => {
                if (index > 0) {
                    value.appendChild(document.createTextNode(' '));
                }
                value.appendChild(this.renderValueToken(entry));
            });
            return value;
        }
        const display = this.formatCellDisplayText(raw, typedValue);
        const fragment = document.createElement('span');
        fragment.className = 'table-value-part';
        fragment.dataset.value = display;
        appendInlineValue(fragment, display);
        value.appendChild(fragment);
        return value;
    }
    formatCellDisplayText(raw, typedValue) {
        if (typedValue?.values?.length) {
            return typedValue.values.map((entry) => {
                if (entry.kind === 'iri') {
                    return shortLabelFromIri(entry.value);
                }
                if (entry.kind === 'bnode') {
                    return `_:${entry.value}`;
                }
                return entry.value;
            }).join(' ');
        }
        return raw;
    }
    getBlockSource(result) {
        return result.blockSource;
    }
    getBlockMeta(result) {
        return result.blockMeta;
    }
    getBlockRange(result) {
        return { start: result.blockLineStart, end: result.blockLineEnd };
    }
    renderValueToken(entry) {
        const fragment = document.createElement('span');
        fragment.className = 'table-value-part';
        fragment.dataset.value = entry.value;
        if (entry.kind === 'iri') {
            if (isBuiltInOntologyIri(entry.value)) {
                appendInlineValue(fragment, shortLabelFromIri(entry.value));
            }
            else {
                fragment.appendChild(createWikiLinkElement(entry.value, shortLabelFromIri(entry.value)));
            }
            return fragment;
        }
        if (entry.kind === 'bnode') {
            appendInlineValue(fragment, `_:${entry.value}`);
            return fragment;
        }
        if (isUrlValue(entry.value)) {
            const link = document.createElement('a');
            link.href = entry.value;
            link.textContent = entry.value;
            fragment.appendChild(link);
            return fragment;
        }
        appendInlineValue(fragment, entry.value);
        return fragment;
    }
}
export class CanvasMarkdownBlockRenderer extends QueryMarkdownBlockRenderer {
    canRender(result) {
        return result.status === 'ok'
            && this.canvasKinds.includes(result.kind);
    }
    renderNotImplemented(result) {
        const container = this.createResultContainer(result.status);
        const source = this.getBlockSource(result);
        const sourceHint = source && source.trim().length > 0 ? ' Query source is available to this renderer.' : '';
        container.appendChild(this.createMessageContainer(`Renderer for '${result.kind}' is not implemented yet.${sourceHint}`));
        return container;
    }
}
const BUILT_IN_ONTOLOGY_IRIS = new Set([
    'http://opencaesar.io/oml',
    'http://www.w3.org/2001/XMLSchema',
    'http://www.w3.org/1999/02/22-rdf-syntax-ns',
    'http://www.w3.org/2000/01/rdf-schema',
    'http://www.w3.org/2002/07/owl',
    'http://www.w3.org/2003/11/swrl',
    'http://www.w3.org/2003/11/swrlb',
]);
function ontologyLookupKeyFromIri(value) {
    const iri = String(value ?? '').trim().replace(/^<|>$/g, '');
    if (!iri || !/^[A-Za-z][A-Za-z0-9+.-]*:[^\s]+$/.test(iri)) {
        return undefined;
    }
    const hashIndex = iri.indexOf('#');
    if (hashIndex >= 0) {
        return normalizeOntologyLookupKey(iri.slice(0, hashIndex + 1));
    }
    const schemeIndex = iri.indexOf('://');
    const slashIndex = iri.lastIndexOf('/');
    if (slashIndex > schemeIndex + 2) {
        return normalizeOntologyLookupKey(iri.slice(0, slashIndex + 1));
    }
    return normalizeOntologyLookupKey(iri);
}
function normalizeOntologyLookupKey(value) {
    return value.trim().replace(/^<|>$/g, '').replace(/[\/#]+$/, '');
}
function isBuiltInOntologyIri(iri) {
    const key = ontologyLookupKeyFromIri(iri);
    if (!key) {
        return false;
    }
    return BUILT_IN_ONTOLOGY_IRIS.has(normalizeOntologyLookupKey(key));
}
//# sourceMappingURL=renderer.js.map