import { module, test } from '../qunit';
import moment from '../../moment';
import each from '../helpers/each';
import indexOf from '../../lib/utils/index-of';

module('locale', {
    setup: function () {
        // TODO: Remove once locales are switched to ES6
        each(
            [
                {
                    name: 'en-gb',
                    data: {},
                },
                {
                    name: 'en-ca',
                    data: {},
                },
                {
                    name: 'es',
                    data: {
                        relativeTime: {
                            past: 'hace %s',
                            s: 'unos segundos',
                            d: 'un día',
                        },
                        months: 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split(
                            '_'
                        ),
                    },
                },
                {
                    name: 'fr',
                    data: {},
                },
                {
                    name: 'fr-ca',
                    data: {},
                },
                {
                    name: 'it',
                    data: {},
                },
                {
                    name: 'zh-cn',
                    data: {
                        months: '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split(
                            '_'
                        ),
                    },
                },
            ],
            function (locale) {
                if (moment.locale(locale.name) !== locale.name) {
                    moment.defineLocale(locale.name, locale.data);
                }
            }
        );
        moment.locale('en');
    },
});

test('library getters and setters', function (assert) {
    var r = moment.locale('en');

    assert.equal(r, 'en', 'locale should return en by default');
    assert.equal(moment.locale(), 'en', 'locale should return en by default');

    moment.locale('fr');
    assert.equal(
        moment.locale(),
        'fr',
        'locale should return the changed locale'
    );

    moment.locale('en-gb');
    assert.equal(
        moment.locale(),
        'en-gb',
        'locale should return the changed locale'
    );

    moment.locale('en');
    assert.equal(moment.locale(), 'en', 'locale should reset');

    moment.locale('does-not-exist');
    assert.equal(moment.locale(), 'en', 'locale should reset');

    moment.locale('EN');
    assert.equal(moment.locale(), 'en', 'Normalize locale key case');

    moment.locale('EN_gb');
    assert.equal(moment.locale(), 'en-gb', 'Normalize locale key underscore');
});

test('library setter array of locales', function (assert) {
    assert.equal(
        moment.locale(['non-existent', 'fr', 'also-non-existent']),
        'fr',
        'passing an array uses the first valid locale'
    );
    assert.equal(
        moment.locale(['es', 'fr', 'also-non-existent']),
        'es',
        'passing an array uses the first valid locale'
    );
});

test('library setter locale substrings', function (assert) {
    assert.equal(moment.locale('fr-crap'), 'fr', 'use substrings');
    assert.equal(
        moment.locale('fr-does-not-exist'),
        'fr',
        'uses deep substrings'
    );
    assert.equal(
        moment.locale('fr-CA-does-not-exist'),
        'fr-ca',
        'uses deepest substring'
    );
});

test('library getter locale array and substrings', function (assert) {
    assert.equal(
        moment.locale(['en-CH', 'fr']),
        'en',
        'prefer root locale to shallower ones'
    );
    assert.equal(
        moment.locale(['en-gb-leeds', 'en-CA']),
        'en-gb',
        'prefer root locale to shallower ones'
    );
    assert.equal(
        moment.locale(['en-fake', 'en-CA']),
        'en-ca',
        'prefer alternatives with shared roots'
    );
    assert.equal(
        moment.locale(['en-fake', 'en-fake2', 'en-ca']),
        'en-ca',
        'prefer alternatives with shared roots'
    );
    assert.equal(
        moment.locale(['fake-CA', 'fake-MX', 'fr']),
        'fr',
        'always find something if possible'
    );
    assert.equal(
        moment.locale(['fake-CA', 'fake-MX', 'fr']),
        'fr',
        'always find something if possible'
    );
    assert.equal(
        moment.locale(['fake-CA', 'fake-MX', 'fr-fake-fake-fake']),
        'fr',
        'always find something if possible'
    );
    assert.equal(
        moment.locale(['en', 'en-CA']),
        'en',
        'prefer earlier if it works'
    );
});

test('library ensure inheritance', function (assert) {
    moment.locale('made-up', {
        // I put them out of order
        months: 'February_March_April_May_June_July_August_September_October_November_December_January'.split(
            '_'
        ),
        // the rest of the properties should be inherited.
    });

    assert.equal(
        moment([2012, 5, 6]).format('MMMM'),
        'July',
        'Override some of the configs'
    );
    assert.equal(
        moment([2012, 5, 6]).format('MMM'),
        'Jun',
        'But not all of them'
    );
});

test('library ensure inheritance LT L LL LLL LLLL', function (assert) {
    var locale = 'test-inherit-lt';

    moment.defineLocale(locale, {
        longDateFormat: {
            LT: '-[LT]-',
            L: '-[L]-',
            LL: '-[LL]-',
            LLL: '-[LLL]-',
            LLLL: '-[LLLL]-',
        },
        calendar: {
            sameDay: '[sameDay] LT',
            nextDay: '[nextDay] L',
            nextWeek: '[nextWeek] LL',
            lastDay: '[lastDay] LLL',
            lastWeek: '[lastWeek] LLLL',
            sameElse: 'L',
        },
    });

    moment.locale('es');

    assert.equal(
        moment().locale(locale).calendar(),
        'sameDay -LT-',
        'Should use instance locale in LT formatting'
    );
    assert.equal(
        moment().add(1, 'days').locale(locale).calendar(),
        'nextDay -L-',
        'Should use instance locale in L formatting'
    );
    assert.equal(
        moment().add(-1, 'days').locale(locale).calendar(),
        'lastDay -LLL-',
        'Should use instance locale in LL formatting'
    );
    assert.equal(
        moment().add(4, 'days').locale(locale).calendar(),
        'nextWeek -LL-',
        'Should use instance locale in LLL formatting'
    );
    assert.equal(
        moment().add(-4, 'days').locale(locale).calendar(),
        'lastWeek -LLLL-',
        'Should use instance locale in LLLL formatting'
    );
});

test('library localeData', function (assert) {
    moment.locale('en');

    var jan = moment([2000, 0]);

    assert.equal(
        moment.localeData().months(jan),
        'January',
        'no arguments returns global'
    );
    assert.equal(
        moment.localeData('zh-cn').months(jan),
        '一月',
        'a string returns the locale based on key'
    );
    assert.equal(
        moment.localeData(moment().locale('es')).months(jan),
        'enero',
        "if you pass in a moment it uses the moment's locale"
    );
});

test('library deprecations', function (assert) {
    test.expectedDeprecations('moment.lang');
    moment.lang('dude', { months: ['Movember'] });
    assert.equal(moment.locale(), 'dude', 'setting the lang sets the locale');
    assert.equal(moment.lang(), moment.locale());
    assert.equal(
        moment.langData(),
        moment.localeData(),
        'langData is localeData'
    );
    moment.defineLocale('dude', null);
});

test('defineLocale', function (assert) {
    moment.locale('en');
    moment.defineLocale('dude', { months: ['Movember'] });
    assert.equal(moment().locale(), 'dude', 'defineLocale also sets it');
    assert.equal(
        moment().locale('dude').locale(),
        'dude',
        'defineLocale defines a locale'
    );
    moment.defineLocale('dude', null);
});

test('locales', function (assert) {
    moment.defineLocale('dude', { months: ['Movember'] });
    assert.equal(
        true,
        !!~indexOf.call(moment.locales(), 'dude'),
        'locales returns an array of defined locales'
    );
    assert.equal(
        true,
        !!~indexOf.call(moment.locales(), 'en'),
        'locales should always include english'
    );
    moment.defineLocale('dude', null);
});

test('library convenience', function (assert) {
    moment.locale('something', { week: { dow: 3 } });
    moment.locale('something');
    assert.equal(
        moment.locale(),
        'something',
        'locale can be used to create the locale too'
    );
    moment.defineLocale('something', null);
});

test('firstDayOfWeek firstDayOfYear locale getters', function (assert) {
    moment.locale('something', { week: { dow: 3, doy: 4 } });
    moment.locale('something');
    assert.equal(moment.localeData().firstDayOfWeek(), 3, 'firstDayOfWeek');
    assert.equal(moment.localeData().firstDayOfYear(), 4, 'firstDayOfYear');
    moment.defineLocale('something', null);
});

test('instance locale method', function (assert) {
    moment.locale('en');

    assert.equal(
        moment([2012, 5, 6]).format('MMMM'),
        'June',
        'Normally default to global'
    );
    assert.equal(
        moment([2012, 5, 6]).locale('es').format('MMMM'),
        'junio',
        'Use the instance specific locale'
    );
    assert.equal(
        moment([2012, 5, 6]).format('MMMM'),
        'June',
        'Using an instance specific locale does not affect other moments'
    );
});

test('instance locale method with array', function (assert) {
    var m = moment().locale(['non-existent', 'fr', 'also-non-existent']);
    assert.equal(
        m.locale(),
        'fr',
        'passing an array uses the first valid locale'
    );
    m = moment().locale(['es', 'fr', 'also-non-existent']);
    assert.equal(
        m.locale(),
        'es',
        'passing an array uses the first valid locale'
    );
});

test('instance getter locale substrings', function (assert) {
    var m = moment();

    m.locale('fr-crap');
    assert.equal(m.locale(), 'fr', 'use substrings');

    m.locale('fr-does-not-exist');
    assert.equal(m.locale(), 'fr', 'uses deep substrings');
});

test('instance locale persists with manipulation', function (assert) {
    moment.locale('en');

    assert.equal(
        moment([2012, 5, 6]).locale('es').add({ days: 1 }).format('MMMM'),
        'junio',
        'With addition'
    );
    assert.equal(
        moment([2012, 5, 6]).locale('es').day(0).format('MMMM'),
        'junio',
        'With day getter'
    );
    assert.equal(
        moment([2012, 5, 6]).locale('es').endOf('day').format('MMMM'),
        'junio',
        'With endOf'
    );
});

test('instance locale persists with cloning', function (assert) {
    moment.locale('en');

    var a = moment([2012, 5, 6]).locale('es'),
        b = a.clone();

    assert.equal(b.format('MMMM'), 'junio', 'using moment.fn.clone()');
    assert.equal(b.format('MMMM'), 'junio', 'using moment()');
});

test('duration locale method', function (assert) {
    moment.locale('en');

    assert.equal(
        moment.duration({ seconds: 44 }).humanize(),
        'a few seconds',
        'Normally default to global'
    );
    assert.equal(
        moment.duration({ seconds: 44 }).locale('es').humanize(),
        'unos segundos',
        'Use the instance specific locale'
    );
    assert.equal(
        moment.duration({ seconds: 44 }).humanize(),
        'a few seconds',
        'Using an instance specific locale does not affect other durations'
    );
});

test('duration locale persists with cloning', function (assert) {
    moment.locale('en');

    var a = moment.duration({ seconds: 44 }).locale('es'),
        b = moment.duration(a);

    assert.equal(b.humanize(), 'unos segundos', 'using moment.duration()');
});

test("changing the global locale doesn't affect existing duration instances", function (assert) {
    var mom = moment.duration();
    moment.locale('fr');
    assert.equal('en', mom.locale());
});

test('duration deprecations', function (assert) {
    test.expectedDeprecations('moment().lang()');
    assert.equal(
        moment.duration().lang(),
        moment.duration().localeData(),
        'duration.lang is the same as duration.localeData'
    );
});

test('from and fromNow with invalid date', function (assert) {
    assert.equal(
        moment(NaN).from(),
        'Invalid date',
        'moment.from with invalid moment'
    );
    assert.equal(
        moment(NaN).fromNow(),
        'Invalid date',
        'moment.fromNow with invalid moment'
    );
});

test('from relative time future', function (assert) {
    var start = moment([2007, 1, 28]);

    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ s: 44 })),
        'in a few seconds',
        '44 seconds = a few seconds'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ s: 45 })),
        'in a minute',
        '45 seconds = a minute'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ s: 89 })),
        'in a minute',
        '89 seconds = a minute'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ s: 90 })),
        'in 2 minutes',
        '90 seconds = 2 minutes'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ m: 44 })),
        'in 44 minutes',
        '44 minutes = 44 minutes'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ m: 45 })),
        'in an hour',
        '45 minutes = an hour'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ m: 89 })),
        'in an hour',
        '89 minutes = an hour'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ m: 90 })),
        'in 2 hours',
        '90 minutes = 2 hours'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ h: 5 })),
        'in 5 hours',
        '5 hours = 5 hours'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ h: 21 })),
        'in 21 hours',
        '21 hours = 21 hours'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ h: 22 })),
        'in a day',
        '22 hours = a day'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ h: 35 })),
        'in a day',
        '35 hours = a day'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ h: 36 })),
        'in 2 days',
        '36 hours = 2 days'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ d: 1 })),
        'in a day',
        '1 day = a day'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ d: 5 })),
        'in 5 days',
        '5 days = 5 days'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ d: 25 })),
        'in 25 days',
        '25 days = 25 days'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ d: 26 })),
        'in a month',
        '26 days = a month'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ d: 30 })),
        'in a month',
        '30 days = a month'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ d: 45 })),
        'in a month',
        '45 days = a month'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ d: 47 })),
        'in 2 months',
        '47 days = 2 months'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ d: 74 })),
        'in 2 months',
        '74 days = 2 months'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ d: 78 })),
        'in 3 months',
        '78 days = 3 months'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ M: 1 })),
        'in a month',
        '1 month = a month'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ M: 5 })),
        'in 5 months',
        '5 months = 5 months'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ d: 315 })),
        'in 10 months',
        '315 days = 10 months'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ d: 344 })),
        'in a year',
        '344 days = a year'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ d: 345 })),
        'in a year',
        '345 days = a year'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ d: 548 })),
        'in 2 years',
        '548 days = in 2 years'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ y: 1 })),
        'in a year',
        '1 year = a year'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).subtract({ y: 5 })),
        'in 5 years',
        '5 years = 5 years'
    );
});

test('from relative time past', function (assert) {
    var start = moment([2007, 1, 28]);

    assert.equal(
        start.from(moment([2007, 1, 28]).add({ s: 44 })),
        'a few seconds ago',
        '44 seconds = a few seconds'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ s: 45 })),
        'a minute ago',
        '45 seconds = a minute'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ s: 89 })),
        'a minute ago',
        '89 seconds = a minute'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ s: 90 })),
        '2 minutes ago',
        '90 seconds = 2 minutes'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ m: 44 })),
        '44 minutes ago',
        '44 minutes = 44 minutes'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ m: 45 })),
        'an hour ago',
        '45 minutes = an hour'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ m: 89 })),
        'an hour ago',
        '89 minutes = an hour'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ m: 90 })),
        '2 hours ago',
        '90 minutes = 2 hours'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ h: 5 })),
        '5 hours ago',
        '5 hours = 5 hours'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ h: 21 })),
        '21 hours ago',
        '21 hours = 21 hours'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ h: 22 })),
        'a day ago',
        '22 hours = a day'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ h: 35 })),
        'a day ago',
        '35 hours = a day'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ h: 36 })),
        '2 days ago',
        '36 hours = 2 days'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ d: 1 })),
        'a day ago',
        '1 day = a day'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ d: 5 })),
        '5 days ago',
        '5 days = 5 days'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ d: 25 })),
        '25 days ago',
        '25 days = 25 days'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ d: 26 })),
        'a month ago',
        '26 days = a month'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ d: 30 })),
        'a month ago',
        '30 days = a month'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ d: 43 })),
        'a month ago',
        '43 days = a month'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ d: 46 })),
        '2 months ago',
        '46 days = 2 months'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ d: 74 })),
        '2 months ago',
        '75 days = 2 months'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ d: 76 })),
        '3 months ago',
        '76 days = 3 months'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ M: 1 })),
        'a month ago',
        '1 month = a month'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ M: 5 })),
        '5 months ago',
        '5 months = 5 months'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ d: 315 })),
        '10 months ago',
        '315 days = 10 months'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ d: 344 })),
        'a year ago',
        '344 days = a year'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ d: 345 })),
        'a year ago',
        '345 days = a year'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ d: 548 })),
        '2 years ago',
        '548 days = 2 years'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ y: 1 })),
        'a year ago',
        '1 year = a year'
    );
    assert.equal(
        start.from(moment([2007, 1, 28]).add({ y: 5 })),
        '5 years ago',
        '5 years = 5 years'
    );
});

test('instance locale used with from', function (assert) {
    moment.locale('en');

    var a = moment([2012, 5, 6]).locale('es'),
        b = moment([2012, 5, 7]);

    assert.equal(a.from(b), 'hace un día', 'preserve locale of first moment');
    assert.equal(
        b.from(a),
        'in a day',
        'do not preserve locale of second moment'
    );
});

test('instance localeData', function (assert) {
    moment.defineLocale('dude', { week: { dow: 3 } });
    assert.equal(moment().locale('dude').localeData()._week.dow, 3);
    moment.defineLocale('dude', null);
});

test('month name callback function', function (assert) {
    function fakeReplace(m, format) {
        if (/test/.test(format)) {
            return 'test';
        }
        if (m.date() === 1) {
            return 'date';
        }
        return 'default';
    }

    moment.locale('made-up-2', {
        months: fakeReplace,
        monthsShort: fakeReplace,
        weekdays: fakeReplace,
        weekdaysShort: fakeReplace,
        weekdaysMin: fakeReplace,
    });

    assert.equal(
        moment().format('[test] dd ddd dddd MMM MMMM'),
        'test test test test test test',
        'format month name function should be able to access the format string'
    );
    assert.equal(
        moment([2011, 0, 1]).format('dd ddd dddd MMM MMMM'),
        'date date date date date',
        'format month name function should be able to access the moment object'
    );
    assert.equal(
        moment([2011, 0, 2]).format('dd ddd dddd MMM MMMM'),
        'default default default default default',
        'format month name function should be able to access the moment object'
    );
});

test('changing parts of a locale config', function (assert) {
    test.expectedDeprecations('defineLocaleOverride');

    moment.locale('partial-lang', {
        months: 'a b c d e f g h i j k l'.split(' '),
    });

    assert.equal(
        moment([2011, 0, 1]).format('MMMM'),
        'a',
        'should be able to set locale values when creating the localeuage'
    );

    moment.locale('partial-lang', {
        monthsShort: 'A B C D E F G H I J K L'.split(' '),
    });

    assert.equal(
        moment([2011, 0, 1]).format('MMMM MMM'),
        'a A',
        'should be able to set locale values after creating the localeuage'
    );

    moment.defineLocale('partial-lang', null);
});

test('start/endOf week feature for first-day-is-monday locales', function (assert) {
    moment.locale('monday-lang', {
        week: {
            dow: 1, // Monday is the first day of the week
        },
    });

    moment.locale('monday-lang');
    assert.equal(
        moment([2013, 0, 1]).startOf('week').day(),
        1,
        'for locale monday-lang first day of the week should be monday'
    );
    assert.equal(
        moment([2013, 0, 1]).endOf('week').day(),
        0,
        'for locale monday-lang last day of the week should be sunday'
    );
    moment.defineLocale('monday-lang', null);
});

test('meridiem parsing', function (assert) {
    moment.locale('meridiem-parsing', {
        meridiemParse: /[bd]/i,
        isPM: function (input) {
            return input === 'b';
        },
    });

    moment.locale('meridiem-parsing');
    assert.equal(
        moment('2012-01-01 3b', 'YYYY-MM-DD ha').hour(),
        15,
        'Custom parsing of meridiem should work'
    );
    assert.equal(
        moment('2012-01-01 3d', 'YYYY-MM-DD ha').hour(),
        3,
        'Custom parsing of meridiem should work'
    );
    moment.defineLocale('meridiem-parsing', null);
});

test('invalid date formatting', function (assert) {
    moment.locale('has-invalid', {
        invalidDate: 'KHAAAAAAAAAAAN!',
    });

    assert.equal(moment.invalid().format(), 'KHAAAAAAAAAAAN!');
    assert.equal(moment.invalid().format('YYYY-MM-DD'), 'KHAAAAAAAAAAAN!');
    moment.defineLocale('has-invalid', null);
});

test('return locale name', function (assert) {
    var registered = moment.locale('return-this', {});

    assert.equal(registered, 'return-this', 'returns the locale configured');
    moment.defineLocale('return-this', null);
});

test("changing the global locale doesn't affect existing instances", function (assert) {
    var mom = moment();
    moment.locale('fr');
    assert.equal('en', mom.locale());
});

test('setting a language on instance returns the original moment for chaining', function (assert) {
    test.expectedDeprecations('moment().lang()');
    var mom = moment();

    assert.equal(
        mom.lang('fr'),
        mom,
        'setting the language (lang) returns the original moment for chaining'
    );
    assert.equal(
        mom.locale('it'),
        mom,
        'setting the language (locale) returns the original moment for chaining'
    );
});

test('lang(key) changes the language of the instance', function (assert) {
    test.expectedDeprecations('moment().lang()');
    var m = moment().month(0);
    m.lang('fr');
    assert.equal(m.locale(), 'fr', 'm.lang(key) changes instance locale');
});

test('moment#locale(false) resets to global locale', function (assert) {
    var m = moment();

    moment.locale('fr');
    m.locale('it');

    assert.equal(moment.locale(), 'fr', 'global locale is it');
    assert.equal(m.locale(), 'it', 'instance locale is it');
    m.locale(false);
    assert.equal(m.locale(), 'fr', 'instance locale reset to global locale');
});

test("moment().locale with missing key doesn't change locale", function (assert) {
    assert.equal(
        moment().locale('boo').localeData(),
        moment.localeData(),
        'preserve global locale in case of bad locale id'
    );
});

test("moment().lang with missing key doesn't change locale", function (assert) {
    test.expectedDeprecations('moment().lang()');
    assert.equal(
        moment().lang('boo').localeData(),
        moment.localeData(),
        'preserve global locale in case of bad locale id'
    );
});

test('when in strict mode with inexact parsing, treat periods in short weekdays literally, not as the regex-period', function (assert) {
    moment.defineLocale('periods-in-short-weekdays', {
        weekdays: 'Monday_Tuesday_Wednesday_Thursday_Friday_Saturday_Sunday'.split(
            '_'
        ),
        weekdaysShort: 'mon_t...s_wed_thurs_fri_sat_sun'.split('_'),
        weekdaysParseExact: false,
    });

    moment().locale('periods-in-short-weekdays');
    assert.equal(moment('thurs', 'ddd', true).format('dddd'), 'Thursday');
});

test('when in strict mode with inexact parsing, treat periods in full weekdays literally, not as the regex-period', function (assert) {
    moment.defineLocale('periods-in-full-weekdays', {
        weekdays: 'Monday_T....day_Wednesday_Thursday_Friday_Saturday_Sunday'.split(
            '_'
        ),
        weekdaysShort: 'mon_tues_wed_thurs_fri_sat_sun'.split('_'),
        weekdaysParseExact: false,
    });

    moment().locale('periods-in-full-weekdays');
    assert.equal(moment('Thursday', 'dddd', true).format('ddd'), 'thurs');
});

test('when in strict mode with inexact parsing, treat periods in min-weekdays literally, not as the regex-period', function (assert) {
    moment.defineLocale('periods-in-min-weekdays', {
        weekdays: 'Monday_Tuesday_Wednesday_Thursday_Friday_Saturday_Sunday'.split(
            '_'
        ),
        weekdaysMin: 'mon_t...s_wed_thurs_fri_sat_sun'.split('_'),
        weekdaysParseExact: false,
    });

    moment().locale('periods-in-min-weekdays');
    assert.equal(moment('thurs', 'dd', true).format('dddd'), 'Thursday');
});

// TODO: Enable this after fixing pl months parse hack hack
// test('monthsParseExact', function (assert) {
//     var locale = 'test-months-parse-exact';

//     moment.defineLocale(locale, {
//         monthsParseExact: true,
//         months: 'A_AA_AAA_B_B B_BB  B_C_C-C_C,C2C_D_D+D_D`D*D'.split('_'),
//         monthsShort: 'E_EE_EEE_F_FF_FFF_G_GG_GGG_H_HH_HHH'.split('_')
//     });

//     assert.equal(moment('A', 'MMMM', true).month(), 0, 'parse long month 0 with MMMM');
//     assert.equal(moment('AA', 'MMMM', true).month(), 1, 'parse long month 1 with MMMM');
//     assert.equal(moment('AAA', 'MMMM', true).month(), 2, 'parse long month 2 with MMMM');
//     assert.equal(moment('B B', 'MMMM', true).month(), 4, 'parse long month 4 with MMMM');
//     assert.equal(moment('BB  B', 'MMMM', true).month(), 5, 'parse long month 5 with MMMM');
//     assert.equal(moment('C-C', 'MMMM', true).month(), 7, 'parse long month 7 with MMMM');
//     assert.equal(moment('C,C2C', 'MMMM', true).month(), 8, 'parse long month 8 with MMMM');
//     assert.equal(moment('D+D', 'MMMM', true).month(), 10, 'parse long month 10 with MMMM');
//     assert.equal(moment('D`D*D', 'MMMM', true).month(), 11, 'parse long month 11 with MMMM');

//     assert.equal(moment('E', 'MMM', true).month(), 0, 'parse long month 0 with MMM');
//     assert.equal(moment('EE', 'MMM', true).month(), 1, 'parse long month 1 with MMM');
//     assert.equal(moment('EEE', 'MMM', true).month(), 2, 'parse long month 2 with MMM');

//     assert.equal(moment('A', 'MMM').month(), 0, 'non-strict parse long month 0 with MMM');
//     assert.equal(moment('AA', 'MMM').month(), 1, 'non-strict parse long month 1 with MMM');
//     assert.equal(moment('AAA', 'MMM').month(), 2, 'non-strict parse long month 2 with MMM');
//     assert.equal(moment('E', 'MMMM').month(), 0, 'non-strict parse short month 0 with MMMM');
//     assert.equal(moment('EE', 'MMMM').month(), 1, 'non-strict parse short month 1 with MMMM');
//     assert.equal(moment('EEE', 'MMMM').month(), 2, 'non-strict parse short month 2 with MMMM');
// });
