"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.computeSpeech = computeSpeech;
exports.computeMarkup = computeMarkup;
exports.recomputeMarkup = recomputeMarkup;
exports.addSpeech = addSpeech;
exports.addModality = addModality;
exports.addPrefix = addPrefix;
exports.retrievePrefix = retrievePrefix;
exports.connectMactions = connectMactions;
exports.connectAllMactions = connectAllMactions;
exports.retrieveSummary = retrieveSummary;
const AuralRendering = require("../audio/aural_rendering.js");
const DomUtil = require("../common/dom_util.js");
const XpathUtil = require("../common/xpath_util.js");
const enrich_attr_js_1 = require("../enrich_mathml/enrich_attr.js");
const speech_rule_engine_js_1 = require("../rule_engine/speech_rule_engine.js");
const semantic_tree_js_1 = require("../semantic_tree/semantic_tree.js");
const WalkerUtil = require("../walker/walker_util.js");
function computeSpeech(xml) {
    return speech_rule_engine_js_1.SpeechRuleEngine.getInstance().evaluateNode(xml);
}
function recomputeSpeech(semantic) {
    const tree = semantic_tree_js_1.SemanticTree.fromNode(semantic);
    return computeSpeech(tree.xml());
}
function computeMarkup(tree) {
    const descrs = computeSpeech(tree);
    return AuralRendering.markup(descrs);
}
function recomputeMarkup(semantic) {
    const descrs = recomputeSpeech(semantic);
    return AuralRendering.markup(descrs);
}
function addSpeech(mml, semantic, snode) {
    const sxml = DomUtil.querySelectorAllByAttrValue(snode, 'id', semantic.id.toString())[0];
    const speech = sxml
        ? AuralRendering.markup(computeSpeech(sxml))
        : recomputeMarkup(semantic);
    mml.setAttribute(enrich_attr_js_1.Attribute.SPEECH, speech);
}
function addModality(mml, semantic, modality) {
    const markup = recomputeMarkup(semantic);
    mml.setAttribute(modality, markup);
}
function addPrefix(mml, semantic) {
    const speech = retrievePrefix(semantic);
    if (speech) {
        mml.setAttribute(enrich_attr_js_1.Attribute.PREFIX, speech);
    }
}
function retrievePrefix(semantic) {
    const descrs = computePrefix(semantic);
    return AuralRendering.markup(descrs);
}
function computePrefix(semantic) {
    const tree = semantic_tree_js_1.SemanticTree.fromRoot(semantic);
    const nodes = XpathUtil.evalXPath('.//*[@id="' + semantic.id + '"]', tree.xml());
    let node = nodes[0];
    if (nodes.length > 1) {
        node = nodeAtPosition(semantic, nodes) || node;
    }
    return node
        ? speech_rule_engine_js_1.SpeechRuleEngine.getInstance().runInSetting({
            modality: 'prefix',
            domain: 'default',
            style: 'default',
            strict: true,
            speech: true
        }, function () {
            return speech_rule_engine_js_1.SpeechRuleEngine.getInstance().evaluateNode(node);
        })
        : [];
}
function nodeAtPosition(semantic, nodes) {
    const node = nodes[0];
    if (!semantic.parent) {
        return node;
    }
    const path = [];
    while (semantic) {
        path.push(semantic.id);
        semantic = semantic.parent;
    }
    const pathEquals = function (xml, path) {
        while (path.length &&
            path.shift().toString() === xml.getAttribute('id') &&
            xml.parentNode &&
            xml.parentNode.parentNode) {
            xml = xml.parentNode.parentNode;
        }
        return !path.length;
    };
    for (let i = 0, xml; (xml = nodes[i]); i++) {
        if (pathEquals(xml, path.slice())) {
            return xml;
        }
    }
    return node;
}
function connectMactions(node, mml, stree) {
    const mactions = DomUtil.querySelectorAll(mml, 'maction');
    for (let i = 0, maction; (maction = mactions[i]); i++) {
        const aid = maction.getAttribute('id');
        const span = DomUtil.querySelectorAllByAttrValue(node, 'id', aid)[0];
        if (!span) {
            continue;
        }
        const lchild = maction.childNodes[1];
        const mid = lchild.getAttribute(enrich_attr_js_1.Attribute.ID);
        let cspan = WalkerUtil.getBySemanticId(node, mid);
        if (cspan && cspan.getAttribute(enrich_attr_js_1.Attribute.TYPE) !== 'dummy') {
            continue;
        }
        cspan = span.childNodes[0];
        if (cspan.getAttribute('sre-highlighter-added')) {
            continue;
        }
        const pid = lchild.getAttribute(enrich_attr_js_1.Attribute.PARENT);
        if (pid) {
            cspan.setAttribute(enrich_attr_js_1.Attribute.PARENT, pid);
        }
        cspan.setAttribute(enrich_attr_js_1.Attribute.TYPE, 'dummy');
        cspan.setAttribute(enrich_attr_js_1.Attribute.ID, mid);
        cspan.setAttribute('role', 'treeitem');
        cspan.setAttribute('aria-level', lchild.getAttribute('aria-level'));
        const cst = DomUtil.querySelectorAllByAttrValue(stree, 'id', mid)[0];
        cst.setAttribute('alternative', mid);
    }
}
function connectAllMactions(mml, stree) {
    const mactions = DomUtil.querySelectorAll(mml, 'maction');
    for (let i = 0, maction; (maction = mactions[i]); i++) {
        const lchild = maction.childNodes[1];
        const mid = lchild.getAttribute(enrich_attr_js_1.Attribute.ID);
        const cst = DomUtil.querySelectorAllByAttrValue(stree, 'id', mid)[0];
        cst.setAttribute('alternative', mid);
    }
}
function retrieveSummary(node, options = {}) {
    const descrs = computeSummary(node, options);
    return AuralRendering.markup(descrs);
}
function computeSummary(node, options = {}) {
    const preOption = options.locale ? { locale: options.locale } : {};
    return node
        ? speech_rule_engine_js_1.SpeechRuleEngine.getInstance().runInSetting(Object.assign(preOption, {
            modality: 'summary',
            strict: false,
            speech: true
        }), function () {
            return speech_rule_engine_js_1.SpeechRuleEngine.getInstance().evaluateNode(node);
        })
        : [];
}
