import formatMessage from 'format-message';
import * as config from './config';
import * as constants from './constants';

const defaultBrandId = '0';
const icuTemplates = {
    en_US: "=0 '{'{other}'}' =1'{'{one}'}' other'{'{other}'}'",
    en_ZZ: "=0 '{'{other}'}' =1'{'{one}'}' other'{'{other}'}'",
    en_GB: "=0 '{'{other}'}' =1'{'{one}'}' other'{'{other}'}'",
    en_AU: "=0 '{'{other}'}' =1'{'{one}'}' other'{'{other}'}'",
    fr_CA: "=0 '{'{one}'}' =1'{'{one}'}' other'{'{other}'}'",
    fr_FR: "=0 '{'{one}'}' =1'{'{one}'}' other'{'{other}'}'",
    de_DE: "=0 '{'{other}'}' =1'{'{one}'}' other'{'{other}'}'",
    es_ES: "=0 '{'{other}'}' =1'{'{one}'}' other'{'{other}'}'",
    it_IT: "=0 '{'{other}'}' =1'{'{one}'}' other'{'{other}'}'",
    es_419: "=0 '{'{other}'}' =1'{'{one}'}' other'{'{other}'}'",
    ja_JP: "=0 '{'{one}'}' =1'{'{one}'}' other'{'{one}'}'",
    pt_BR: "=0 '{'{one}'}' =1'{'{one}'}' other'{'{other}'}'",
    zh_CN: "=0 '{'{other}'}' =1'{'{other}'}' other'{'{other}'}'",
    zh_TW: "=0 '{'{other}'}' =1'{'{other}'}' other'{'{other}'}'",
    zh_HK: "=0 '{'{other}'}' =1'{'{other}'}' other'{'{other}'}'"
};

function isValidKeysByReg(reg, obj) {
    let keys = Object.keys(obj);

    let hasInvalidKey = Object.keys(obj).some(function(key) {
        return !reg.test(key);
    });

    return keys.length > 0 && !hasInvalidKey;
}

function isBrandedMessageResource(obj) {
    return isValidKeysByReg(/^0$|^\d{4}$|^\d{2}$/, obj);
}

function isPluralMessageResource(obj) {
    return isValidKeysByReg(/^one$|^other$|^many$/, obj);
}

function covertMessageResourceToICUString(obj) {
    const lang = config.isConfigInitialized() ? config.getConfig().userLanguage : null;
    const icuMsgFormat = (lang && icuTemplates[lang]) || icuTemplates['en_US'];

    let msg = formatMessage(icuMsgFormat, obj);

    return '{count, plural, ' + msg + '}';
}

/**
 * TODO rename. actually is formatMessage not a translate
 * @param {string|object} str
 * @param {object} [args]
 * @return {string}
 */
function translate(str: string | object, args?) {
    if (!str) {
        return constants.notTranslatedPrefix;
    }

    if (typeof str === 'object') {
        if (isBrandedMessageResource(str)) {
            const brandId = config.isConfigInitialized()
                ? config.getConfig().brandId
                : defaultBrandId;
            str = str[brandId] || str[defaultBrandId];
        } else if (isPluralMessageResource(str)) {
            //TODO Support both brand and plural at the same time
            let errorMessage =
                'You are using translate() to handle plural strings, args should be an object like {count:1} or a number.';
            if (!args && args !== 0) {
                throw new Error(errorMessage);
            }
            if (!isNaN(args)) {
                args = {count: args};
            }
            if (!args.hasOwnProperty('count')) {
                throw new Error(errorMessage);
            }
            str = covertMessageResourceToICUString(str);
        } else {
            throw new Error('Object ' + JSON.stringify(str) + ' is not a valid message resource.');
        }
    }

    if (typeof str === 'string' && str.indexOf(constants.notTranslatedPrefix + ':') === 0) {
        str = str.replace(constants.notTranslatedPrefix + ':', '');
    }

    return formatMessage(str, args);
}

export default translate;
export {translate};
