/**
 * Copyright JS Foundation and other contributors, http://js.foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * @ignore
 **/

/**
 * Internationalization utilities
 * @mixin @node-red/util_i18n
 */

var i18n = require("i18next");

var when = require("when");
var path = require("path");
var fs = require("fs");

var defaultLang = "en-US";

var resourceMap = {};
var resourceCache = {};
var initPromise;

/**
 * Register multiple message catalogs with i18n.
 * @memberof @node-red/util_i18n
 */
function registerMessageCatalogs(catalogs) {
    var promises = catalogs.map(function(catalog) {
        return registerMessageCatalog(catalog.namespace,catalog.dir,catalog.file);
    });
    return when.settle(promises);
}

/**
 * Register a message catalog with i18n.
 * @memberof @node-red/util_i18n
 */
function registerMessageCatalog(namespace,dir,file) {
    return initPromise.then(function() {
        return new Promise((resolve,reject) => {
            resourceMap[namespace] = { basedir:dir, file:file};
            i18n.loadNamespaces(namespace,function() {
                resolve();
            });
        });
    });
}

function mergeCatalog(fallback,catalog) {
    for (var k in fallback) {
        if (fallback.hasOwnProperty(k)) {
            if (!catalog[k]) {
                catalog[k] = fallback[k];
            } else if (typeof fallback[k] === 'object') {
                mergeCatalog(fallback[k],catalog[k]);
            }
        }
    }
}

var MessageFileLoader = {
    type: "backend",
    init: function(services, backendOptions, i18nextOptions) {},
    read: function(lng, ns, callback) {
        if (resourceMap[ns]) {
            var file = path.join(resourceMap[ns].basedir,lng,resourceMap[ns].file);
            //console.log(file);
            fs.readFile(file,"utf8",function(err,content) {
                if (err) {
                    callback(err);
                } else {
                    try {
                        resourceCache[ns] = resourceCache[ns]||{};
                        resourceCache[ns][lng] = JSON.parse(content.replace(/^\uFEFF/, ''));
                        //console.log(resourceCache[ns][lng]);
                        if (lng !== defaultLang) {
                            mergeCatalog(resourceCache[ns][defaultLang],resourceCache[ns][lng]);
                        }
                        callback(null, resourceCache[ns][lng]);
                    } catch(e) {
                        callback(e);
                    }
                }
            });
        } else {
            callback(new Error("Unrecognised namespace"));
        }
    }

}

function getCurrentLocale() {
    var env = process.env;
    for (var name of ['LC_ALL', 'LC_MESSAGES', 'LANG']) {
        if (name in env) {
            var val = env[name];
            return val.substring(0, 2);
        }
    }
    return undefined;
}

function init() {
    if (!initPromise) {
        // Keep this as a 'when' promise as top-level red.js uses 'otherwise'
        // and embedded users of NR may have copied that.
        initPromise = when.promise((resolve,reject) => {
            i18n.use(MessageFileLoader);
            var opt = {
                // debug: true,
                defaultNS: "runtime",
                ns: [],
                fallbackLng: defaultLang,
                interpolation: {
                    unescapeSuffix: 'HTML',
                    escapeValue: false,
                    prefix: '__',
                    suffix: '__'
                }
            };
            var lang = getCurrentLocale();
            if (lang) {
                opt.lng = lang;
            }
            i18n.init(opt ,function() {
                resolve();
            });
        });
    }
}


/**
 * Gets a message catalog.
 * @name catalog
 * @function
 * @memberof @node-red/util_i18n
 */
function getCatalog(namespace,lang) {
    var result = null;
    lang = lang || defaultLang;
    if (resourceCache.hasOwnProperty(namespace)) {
        result = resourceCache[namespace][lang];
        if (!result) {
            var langParts = lang.split("-");
            if (langParts.length == 2) {
                result = resourceCache[namespace][langParts[0]];
            }
        }
    }
    return result;
}

var obj = module.exports = {
    init: init,
    registerMessageCatalog: registerMessageCatalog,
    registerMessageCatalogs: registerMessageCatalogs,
    catalog: getCatalog,
    /**
     * The underlying i18n library for when direct access is really needed
     */
    i: i18n,
    /**
     * The default language of the runtime
     */
    defaultLang: defaultLang
}

/**
 * Perform a message catalog lookup.
 * @name _
 * @function
 * @memberof @node-red/util_i18n
 */
obj['_'] = function() {
    //var opts = {};
    //if (def) {
    //    opts.defaultValue = def;
    //}
    //console.log(arguments);
    var res = i18n.t.apply(i18n,arguments);
    return res;
}