import isArray from '../utils/is-array'; import hasOwnProp from '../utils/has-own-prop'; import isUndefined from '../utils/is-undefined'; import compareArrays from '../utils/compare-arrays'; import { deprecateSimple } from '../utils/deprecate'; import { mergeConfigs } from './set'; import { Locale } from './constructor'; import keys from '../utils/keys';

import { baseConfig } from './base-config';

// internal storage for locale config files var locales = {}; var localeFamilies = {}; var globalLocale;

function normalizeLocale(key) {

return key ? key.toLowerCase().replace('_', '-') : key;

}

// pick the locale from the array // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root function chooseLocale(names) {

var i = 0, j, next, locale, split;

while (i < names.length) {
    split = normalizeLocale(names[i]).split('-');
    j = split.length;
    next = normalizeLocale(names[i + 1]);
    next = next ? next.split('-') : null;
    while (j > 0) {
        locale = loadLocale(split.slice(0, j).join('-'));
        if (locale) {
            return locale;
        }
        if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
            //the next array item is better than a shallower substring of this one
            break;
        }
        j--;
    }
    i++;
}
return null;

}

function loadLocale(name) {

var oldLocale = null;
// TODO: Find a better way to register and load all the locales in Node
if (!locales[name] && (typeof module !== 'undefined') &&
        module && module.exports) {
    try {
        oldLocale = globalLocale._abbr;
        require('./locale/' + name);
        // because defineLocale currently also sets the global locale, we
        // want to undo that for lazy loaded locales
        getSetGlobalLocale(oldLocale);
    } catch (e) { }
}
return locales[name];

}

// This function will load locale and then set the global locale. If // no arguments are passed in, it will simply return the current global // locale key. export function getSetGlobalLocale (key, values) {

var data;
if (key) {
    if (isUndefined(values)) {
        data = getLocale(key);
    }
    else {
        data = defineLocale(key, values);
    }

    if (data) {
        // moment.duration._locale = moment._locale = data;
        globalLocale = data;
    }
}

return globalLocale._abbr;

}

export function defineLocale (name, config) {

if (config !== null) {
    var parentConfig = baseConfig;
    config.abbr = name;
    if (locales[name] != null) {
        deprecateSimple('defineLocaleOverride',
                'use moment.updateLocale(localeName, config) to change ' +
                'an existing locale. moment.defineLocale(localeName, ' +
                'config) should only be used for creating a new locale ' +
                'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.');
        parentConfig = locales[name]._config;
    } else if (config.parentLocale != null) {
        if (locales[config.parentLocale] != null) {
            parentConfig = locales[config.parentLocale]._config;
        } else {
            if (!localeFamilies[config.parentLocale]) {
                localeFamilies[config.parentLocale] = [];
            }
            localeFamilies[config.parentLocale].push({
                name: name,
                config: config
            });
            return null;
        }
    }
    locales[name] = new Locale(mergeConfigs(parentConfig, config));

    if (localeFamilies[name]) {
        localeFamilies[name].forEach(function (x) {
            defineLocale(x.name, x.config);
        });
    }

    // backwards compat for now: also set the locale
    // make sure we set the locale AFTER all child locales have been
    // created, so we won't end up with the child locale set.
    getSetGlobalLocale(name);

    return locales[name];
} else {
    // useful for testing
    delete locales[name];
    return null;
}

}

export function updateLocale(name, config) {

if (config != null) {
    var locale, parentConfig = baseConfig;
    // MERGE
    if (locales[name] != null) {
        parentConfig = locales[name]._config;
    }
    config = mergeConfigs(parentConfig, config);
    locale = new Locale(config);
    locale.parentLocale = locales[name];
    locales[name] = locale;

    // backwards compat for now: also set the locale
    getSetGlobalLocale(name);
} else {
    // pass null for config to unupdate, useful for tests
    if (locales[name] != null) {
        if (locales[name].parentLocale != null) {
            locales[name] = locales[name].parentLocale;
        } else if (locales[name] != null) {
            delete locales[name];
        }
    }
}
return locales[name];

}

// returns locale data export function getLocale (key) {

var locale;

if (key && key._locale && key._locale._abbr) {
    key = key._locale._abbr;
}

if (!key) {
    return globalLocale;
}

if (!isArray(key)) {
    //short-circuit everything else
    locale = loadLocale(key);
    if (locale) {
        return locale;
    }
    key = [key];
}

return chooseLocale(key);

}

export function listLocales() {

return keys(locales);

}