import lodash from 'lodash';

/*
 * Copyright (c) 2022.
 * Author Peter Placzek (tada5hi)
 * For the full copyright and license information,
 * view the LICENSE file that was distributed with this source code.
 */ function parseArgsToDataAndLocale(data, locale, alt) {
    alt = alt || {};
    alt.data = alt.data || {};
    alt.locale = alt.locale || 'en';
    if (typeof data === 'string' && typeof locale === 'undefined') {
        return [
            {},
            data
        ];
    }
    data = typeof data === 'string' ? {} : data;
    return [
        data || alt.data,
        locale || alt.locale
    ];
}

/*
 * Copyright (c) 2021.
 * Author Peter Placzek (tada5hi)
 * For the full copyright and license information,
 * view the LICENSE file that was distributed with this source code.
 */ // eslint-disable-next-line @typescript-eslint/ban-types
function hasOwnProperty(obj, prop) {
    return Object.prototype.hasOwnProperty.call(obj, prop);
}

/*
 * Copyright (c) 2022.
 * Author Peter Placzek (tada5hi)
 * For the full copyright and license information,
 * view the LICENSE file that was distributed with this source code.
 */ function isLineRecord(value) {
    if (typeof value !== 'object') {
        return false;
    }
    const ob = value;
    const keys = Object.keys(ob);
    for(let i = 0; i < keys.length; i++){
        /* istanbul ignore next */ if (typeof ob[keys[i]] !== 'string' && !isLineRecord(ob[keys[i]])) {
            return false;
        }
    }
    return true;
}

/*
 * Copyright (c) 2022.
 * Author Peter Placzek (tada5hi)
 * For the full copyright and license information,
 * view the LICENSE file that was distributed with this source code.
 */ function toArray(input) {
    return Array.isArray(input) ? input : [
        input
    ];
}

/*
 * Copyright (c) 2022.
 * Author Peter Placzek (tada5hi)
 * For the full copyright and license information,
 * view the LICENSE file that was distributed with this source code.
 */ function asyncGeneratorStep$2(gen, resolve, reject, _next, _throw, key, arg) {
    try {
        var info = gen[key](arg);
        var value = info.value;
    } catch (error) {
        reject(error);
        return;
    }
    if (info.done) {
        resolve(value);
    } else {
        Promise.resolve(value).then(_next, _throw);
    }
}
function _asyncToGenerator$2(fn) {
    return function() {
        var self = this, args = arguments;
        return new Promise(function(resolve, reject) {
            var gen = fn.apply(self, args);
            function _next(value) {
                asyncGeneratorStep$2(gen, resolve, reject, _next, _throw, "next", value);
            }
            function _throw(err) {
                asyncGeneratorStep$2(gen, resolve, reject, _next, _throw, "throw", err);
            }
            _next(undefined);
        });
    };
}
function _extends() {
    _extends = Object.assign || function(target) {
        for(var i = 1; i < arguments.length; i++){
            var source = arguments[i];
            for(var key in source){
                if (Object.prototype.hasOwnProperty.call(source, key)) {
                    target[key] = source[key];
                }
            }
        }
        return target;
    };
    return _extends.apply(this, arguments);
}
class AbstractIlingo {
    // ----------------------------------------------------
    setDirectory(directory, extend = false) {
        this.directories = [
            ...extend ? this.directories : [],
            ...toArray(directory)
        ];
    }
    getDirectory() {
        if (this.directories.length > 0) {
            return this.directories[0];
        }
        return undefined;
    }
    getDirectories() {
        return this.directories;
    }
    // ----------------------------------------------------
    setLocale(key) {
        this.locale = key;
    }
    getLocale() {
        return this.locale || 'en';
    }
    // ----------------------------------------------------
    set(key, value, locale) {
        const [group, line] = this.parse(key);
        locale = locale || this.getLocale();
        this.initLines(group, locale);
        this.cache[locale][group][line] = value;
    }
    // ----------------------------------------------------
    get(input, dataOrLocale, locale) {
        var _this = this;
        return _asyncToGenerator$2(function*() {
            const parsed = parseArgsToDataAndLocale(dataOrLocale, locale, {
                locale: _this.getLocale()
            });
            if (!input.includes('.')) {
                return _this.formatMessage(input, parsed[0] || {});
            }
            const [file, line] = _this.parse(input);
            if (!parsed[1] || typeof _this.cache[parsed[1]] === 'undefined' || typeof _this.cache[parsed[1]][file] === 'undefined') {
                yield _this.loadGroup(file, parsed[1]);
            }
            const message = _this.getMessage(file, line, parsed[1]);
            return _this.formatMessage(message || line, parsed[0] || {});
        })();
    }
    getSync(input, dataOrLocale, locale) {
        const parsed = parseArgsToDataAndLocale(dataOrLocale, locale, {
            locale: this.getLocale()
        });
        if (!input.includes('.')) {
            return this.formatMessage(input, parsed[0] || {});
        }
        const [group, line] = this.parse(input);
        if (!parsed[1] || typeof this.cache[parsed[1]] === 'undefined' || typeof this.cache[parsed[1]][group] === 'undefined') {
            this.loadGroupSync(group, parsed[1]);
        }
        const message = this.getMessage(group, line, parsed[1]);
        return this.formatMessage(message || line, parsed[0] || {});
    }
    // ----------------------------------------------------
    parse(key) {
        const group = key.substring(0, key.indexOf('.'));
        const line = key.substring(group.length + 1);
        return [
            group,
            line
        ];
    }
    // ----------------------------------------------------
    getMessage(group, line, locale) {
        locale = locale || this.getLocale();
        if (typeof this.cache[locale] === 'undefined' || typeof this.cache[locale][group] === 'undefined') {
            return undefined;
        }
        if (typeof this.cache[locale][group][line] === 'string') {
            return this.cache[locale][group][line];
        }
        let current;
        let output;
        const parts = line.split('.');
        for(let i = 0; i < parts.length; i++){
            if (typeof current === 'undefined') {
                current = this.cache[locale][group];
            }
            output = isLineRecord(current) ? current[parts[i]] : undefined;
            if (typeof output === 'string') {
                return output;
            }
            if (isLineRecord(output)) {
                current = output;
            }
        }
        return undefined;
    }
    formatMessage(message, args) {
        const compiled = lodash.template(message, {
            interpolate: /{{([\s\S]+?)}}/g
        });
        return compiled(args);
    }
    // ------------------------------------------
    isLoaded(group, locale) {
        locale = locale || this.getLocale();
        this.loaded[locale] = this.loaded[locale] || [];
        return this.loaded[locale].indexOf(group) !== -1;
    }
    setIsLoaded(group, locale) {
        locale = locale || this.getLocale();
        this.loaded[locale] = this.loaded[locale] || [];
        this.loaded[locale].push(group);
    }
    resetIsLoaded() {
        this.loaded = {};
    }
    // ------------------------------------------
    initLines(group, locale) {
        locale = locale || this.getLocale();
        if (typeof this.cache[locale] === 'undefined') {
            this.cache[locale] = {};
        }
        if (typeof this.cache[locale][group] === 'undefined') {
            this.cache[locale][group] = {};
        }
    }
    setLines(group, lines, locale) {
        locale = locale || this.getLocale();
        this.initLines(group, locale);
        this.cache[locale][group] = lines;
    }
    addLines(group, lines, locale) {
        locale = locale || this.getLocale();
        this.initLines(group, locale);
        this.cache[locale][group] = _extends({}, this.cache[locale][group], lines);
    }
    // ------------------------------------------
    setCache(data, extend = true) {
        if (!extend) {
            this.resetCache();
        }
        const localeKeys = Object.keys(data);
        for(let i = 0; i < localeKeys.length; i++){
            const localeGroups = Object.keys(data[localeKeys[i]]);
            for(let j = 0; j < localeGroups.length; j++){
                if (extend) {
                    this.addLines(localeGroups[j], data[localeKeys[i]][localeGroups[j]], localeKeys[i]);
                } else {
                    this.setLines(localeGroups[j], data[localeKeys[i]][localeGroups[j]], localeKeys[i]);
                }
            }
        }
    }
    getCache() {
        return this.cache;
    }
    resetCache() {
        this.cache = {};
        this.resetIsLoaded();
    }
    // ----------------------------------------------------
    constructor(options){
        this.cache = {};
        this.loaded = {};
        options = options || {};
        this.directories = options.directory ? toArray(options.directory) : [];
        this.locale = options.locale || 'en';
        if (options.cache) {
            this.setCache(options.cache);
        }
    }
}

/*
 * Copyright (c) 2022.
 * Author Peter Placzek (tada5hi)
 * For the full copyright and license information,
 * view the LICENSE file that was distributed with this source code.
 */ function asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, key, arg) {
    try {
        var info = gen[key](arg);
        var value = info.value;
    } catch (error) {
        reject(error);
        return;
    }
    if (info.done) {
        resolve(value);
    } else {
        Promise.resolve(value).then(_next, _throw);
    }
}
function _asyncToGenerator$1(fn) {
    return function() {
        var self = this, args = arguments;
        return new Promise(function(resolve, reject) {
            var gen = fn.apply(self, args);
            function _next(value) {
                asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, "next", value);
            }
            function _throw(err) {
                asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, "throw", err);
            }
            _next(undefined);
        });
    };
}
class Ilingo extends AbstractIlingo {
    loadGroup(file, locale) {
        var _this = this;
        return _asyncToGenerator$1(function*() {
            _this.setIsLoaded(file, locale);
            return {};
        })();
    }
    loadGroupSync(file, locale) {
        this.setIsLoaded(file, locale);
        return {};
    }
    // eslint-disable-next-line no-useless-constructor,@typescript-eslint/no-useless-constructor
    constructor(options){
        super(options);
    }
}

const instances = {};
function useIlingo(options, key) {
    key = key || 'default';
    if (Object.prototype.hasOwnProperty.call(instances, key)) {
        return instances[key];
    }
    const instance = new Ilingo(options);
    instances[key] = instance;
    return instance;
}

/*
 * Copyright (c) 2022.
 * Author Peter Placzek (tada5hi)
 * For the full copyright and license information,
 * view the LICENSE file that was distributed with this source code.
 */ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
    try {
        var info = gen[key](arg);
        var value = info.value;
    } catch (error) {
        reject(error);
        return;
    }
    if (info.done) {
        resolve(value);
    } else {
        Promise.resolve(value).then(_next, _throw);
    }
}
function _asyncToGenerator(fn) {
    return function() {
        var self = this, args = arguments;
        return new Promise(function(resolve, reject) {
            var gen = fn.apply(self, args);
            function _next(value) {
                asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
            }
            function _throw(err) {
                asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
            }
            _next(undefined);
        });
    };
}
function lang(input, dataOrLocale, locale) {
    return _lang.apply(this, arguments);
}
function _lang() {
    _lang = _asyncToGenerator(function*(input, dataOrLocale, locale) {
        return useIlingo().get(input, dataOrLocale, locale);
    });
    return _lang.apply(this, arguments);
}
function langSync(input, dataOrLocale, locale) {
    return useIlingo().getSync(input, dataOrLocale, locale);
}

export { AbstractIlingo, Ilingo, hasOwnProperty, isLineRecord, lang, langSync, parseArgsToDataAndLocale, toArray, useIlingo };
//# sourceMappingURL=index.mjs.map
