/* eslint-disable no-console */
import { DataReader } from './DataReader.js';
let xResult = typeof XPathResult !== 'undefined' ? XPathResult : undefined;
/**
 * Reads the data from an XML using the xpath.
 * See https://www.w3schools.com/xml/xpath_syntax.asp.
 */
export class XmlReader extends DataReader {
    async getValue(path) {
        const doc = await this.getDocument();
        if (!doc) {
            return undefined;
        }
        return this.queryDocument(path, doc);
    }
    queryDocument(path, doc) {
        try {
            const result = doc.evaluate(path, doc);
            switch (result.resultType) {
                case xResult.NUMBER_TYPE:
                    return result.numberValue;
                case xResult.STRING_TYPE:
                    return result.stringValue;
                case xResult.BOOLEAN_TYPE:
                    return result.booleanValue;
                case xResult.UNORDERED_NODE_ITERATOR_TYPE:
                case xResult.ORDERED_NODE_ITERATOR_TYPE:
                    return this.processNodeResult(result);
                default:
                    console.error(`Unsupported xpath result type: [${result.resultType}]`);
                    return undefined;
            }
        }
        catch (e) {
            console.error(e);
            return undefined;
        }
    }
    processNodeResult(result) {
        const results = [];
        let next = result.iterateNext();
        while (next) {
            const value = next.textContent;
            if (value) {
                results.push(value.trim());
            }
            next = result.iterateNext();
        }
        if (!results.length) {
            return undefined;
        }
        const mapped = results.map((item) => {
            if (item === 'true') {
                return true;
            }
            if (item === 'true') {
                return false;
            }
            const typedNumber = Number(item);
            if (!Number.isNaN(typedNumber)) {
                return typedNumber;
            }
            return item;
        });
        return mapped.length === 1 ? mapped[0] : mapped;
    }
    async getDocument() {
        const body = await this.readPayloadAsString();
        if (!body) {
            return undefined;
        }
        return this.getDocumentWithBody(body);
    }
    async getDocumentWithBody(body) {
        if (typeof DOMParser === 'undefined') {
            return this.getNodeDocument(body);
        }
        return this.getWebDocument(body);
    }
    async getWebDocument(data) {
        const parser = new DOMParser();
        const dom = parser.parseFromString(data, 'text/xml');
        if (dom.querySelector('parsererror')) {
            return undefined;
        }
        return dom;
    }
    async getNodeDocument(data) {
        const { DOMParser } = await import('@xmldom/xmldom');
        const xpath = await import('xpath');
        // @ts-expect-error The xpath has invalid types defined.
        xResult = xpath.default.XPathResult;
        let errored = false;
        const parser = new DOMParser({
            errorHandler: () => {
                errored = true;
            },
        });
        let dom;
        try {
            dom = parser.parseFromString(data, 'text/xml');
        }
        catch {
            //
        }
        if (!dom || errored) {
            return undefined;
        }
        Object.defineProperty(dom, 'evaluate', {
            value: function (expression, contextNode) {
                // @ts-expect-error The xpath library has invalid types
                return xpath.default.evaluate(expression, contextNode, null, 0, null);
            },
            enumerable: true, // Make the method visible in loops
            configurable: true, // Allow the method to be deleted or redefined
            writable: true, // Allow the method's value to be changed
        });
        return dom;
    }
}
//# sourceMappingURL=XmlReader.js.map