/*!
 * React Native Globalize
 *
 * Copyright 2015-2020 Josh Swan
 * Released under the MIT license
 * https://github.com/joshswan/react-native-globalize/blob/master/LICENSE
 */
import { Fragment, createElement, isValidElement, } from 'react';
/**
 * The globalize core library only supports number/string replacement values when formatting
 * messages. To support React Element values, a random UID token that does not conflict with other
 * parts of the string is used as a placeholder during message formatting. The formatted message
 * can then be broken up into parts based on the tokens and the React Element(s) inserted.
 * @param getMessageFormatter The normal Globalize messageFormatter function
 */
export function enhanceMessageFormatter(getMessageFormatter, config) {
    return (id, options = {}) => {
        let formatter;
        try {
            formatter = getMessageFormatter(id);
        }
        catch (e) {
            const msgId = Array.isArray(id) ? id.join('/') : id;
            config.onError(`Error processing message ${msgId}.`, e);
            if (typeof options.defaultMessage === 'string') {
                return () => options.defaultMessage;
            }
            return () => msgId;
        }
        return (values = {}) => {
            const uid = Math.floor(Math.random() * 0x10000000000).toString(16);
            const tokenRegexp = new RegExp(`(@__ELEMENT-${uid}-\\d+__@)`, 'g');
            const generateToken = (() => {
                let counter = 0;
                return () => `@__ELEMENT-${uid}-${counter++}__@`; // eslint-disable-line no-plusplus
            })();
            const tokenizedValues = {};
            const elements = {};
            Object.keys(values).forEach((key) => {
                const index = key;
                const value = values[index];
                if (isValidElement(value)) {
                    const token = generateToken();
                    tokenizedValues[key] = token;
                    elements[token] = value;
                }
                else {
                    tokenizedValues[key] = value;
                }
            });
            const nodes = formatter(tokenizedValues)
                .split(tokenRegexp)
                .filter((part) => !!part)
                .map((part) => elements[part] || part);
            if (nodes.length === 1 && typeof nodes[0] === 'string') {
                return nodes[0];
            }
            return createElement(Fragment, null, ...nodes);
        };
    };
}
export function formatMessage(config, getMessageFormatter, id, values = {}, options) {
    try {
        return getMessageFormatter(id, options)(values);
    }
    catch (e) {
        const msgId = Array.isArray(id) ? id.join('/') : id;
        config.onError(`Error formatting message ${msgId}.`, e);
        return String(msgId);
    }
}
