import React from 'react';
import {
    _t,
    _tDom,
    TranslatedString,
    setLanguage,
    setMissingEntryGenerator,
    substitute,
} from '../../src/languageHandler';
import { stubClient } from '../test-utils';
describe('languageHandler', function() {
    const basicString = 'Rooms';
    const selfClosingTagSub = 'Accept  to continue:';
    const textInTagSub = 'Upgrade to your own domain';
    const plurals = 'and %(count)s others...';
    const variableSub = 'You are now ignoring %(userId)s';
    type TestCase = [string, string, Record, Record, TranslatedString];
    const testCasesEn: TestCase[] = [
        ['translates a basic string', basicString, {}, undefined, 'Rooms'],
        [
            'handles plurals when count is 0',
            plurals,
            { count: 0 },
            undefined,
            'and 0 others...',
        ],
        [
            'handles plurals when count is 1',
            plurals,
            { count: 1 },
            undefined,
            'and one other...',
        ],
        [
            'handles plurals when count is not 1',
            plurals,
            { count: 2 },
            undefined,
            'and 2 others...',
        ],
        [
            'handles simple variable substitution',
            variableSub,
            { userId: 'foo' },
            undefined,
            'You are now ignoring foo',
        ],
        [
            'handles simple tag substitution',
            selfClosingTagSub,
            {},
            { 'policyLink': () => 'foo' },
            'Accept foo to continue:',
        ],
        ['handles text in tags', textInTagSub, {}, { 'a': (sub) => `x${sub}x` }, 'xUpgradex to your own domain'],
        [
            'handles variable substitution with React function component',
            variableSub,
            { userId: () => foo },
            undefined,
            // eslint-disable-next-line react/jsx-key
            You are now ignoring foo,
        ],
        [
            'handles variable substitution with react node',
            variableSub,
            { userId: foo },
            undefined,
            // eslint-disable-next-line react/jsx-key
            You are now ignoring foo,
        ],
        [
            'handles tag substitution with React function component',
            selfClosingTagSub,
            {},
            { 'policyLink': () => foo },
            // eslint-disable-next-line react/jsx-key
            Accept foo to continue:,
        ],
    ];
    describe('when translations exist in language', () => {
        beforeEach(function(done) {
            stubClient();
            setLanguage('en').then(done);
            setMissingEntryGenerator(key => key.split("|", 2)[1]);
        });
        it('translates a string to german', function(done) {
            setLanguage('de').then(function() {
                const translated = _t(basicString);
                expect(translated).toBe('Räume');
            }).then(done);
        });
        it.each(testCasesEn)("%s", async (_d, translationString, variables, tags, result) => {
            expect(_t(translationString, variables, tags)).toEqual(result);
        });
        it('replacements in the wrong order', function() {
            const text = '%(var1)s %(var2)s';
            expect(_t(text, { var2: 'val2', var1: 'val1' })).toBe('val1 val2');
        });
        it('multiple replacements of the same variable', function() {
            const text = '%(var1)s %(var1)s';
            expect(substitute(text, { var1: 'val1' })).toBe('val1 val1');
        });
        it('multiple replacements of the same tag', function() {
            const text = 'Click here to join the discussion! or here';
            expect(substitute(text, {}, { 'a': (sub) => `x${sub}x` }))
                .toBe('xClick herex to join the discussion! xor herex');
        });
    });
    describe('for a non-en language', () => {
        beforeEach(async () => {
            stubClient();
            await setLanguage('lv');
            // counterpart doesnt expose any way to restore default config
            // missingEntryGenerator is mocked in the root setup file
            // reset to default here
            const counterpartDefaultMissingEntryGen =
                function(key) { return 'missing translation: ' + key; };
            setMissingEntryGenerator(counterpartDefaultMissingEntryGen);
        });
        // mocked lv has only `"Uploading %(filename)s and %(count)s others|one"`
        const lvExistingPlural = 'Uploading %(filename)s and %(count)s others';
        const lvNonExistingPlural = '%(spaceName)s and %(count)s others';
        describe('pluralization', () => {
            const pluralCases = [
                [
                    'falls back when plural string exists but not for for count',
                    lvExistingPlural,
                    { count: 2, filename: 'test.txt' },
                    undefined,
                    'Uploading test.txt and 2 others',
                ],
                [
                    'falls back when plural string does not exists at all',
                    lvNonExistingPlural,
                    { count: 2, spaceName: 'test' },
                    undefined,
                    'test and 2 others',
                ],
            ] as TestCase[];
            describe('_t', () => {
                it('translated correctly when plural string exists for count', () => {
                    expect(_t(
                        lvExistingPlural,
                        { count: 1, filename: 'test.txt' }, undefined)).toEqual('Качване на test.txt и 1 друг');
                });
                it.each(pluralCases)(
                    "%s",
                    async (_d, translationString, variables, tags, result) => {
                        expect(_t(translationString, variables, tags)).toEqual(result);
                    },
                );
            });
            describe('_tDom()', () => {
                it('translated correctly when plural string exists for count', () => {
                    expect(_tDom(
                        lvExistingPlural,
                        { count: 1, filename: 'test.txt' }, undefined)).toEqual('Качване на test.txt и 1 друг');
                });
                it.each(pluralCases)(
                    "%s and translates with fallback locale, attributes fallback locale",
                    async (_d, translationString, variables, tags, result) => {
                        expect(_tDom(translationString, variables, tags)).toEqual({ result });
                    },
                );
            });
        });
        describe('when a translation string does not exist in active language', () => {
            describe('_t', () => {
                it.each(testCasesEn)(
                    "%s and translates with fallback locale",
                    async (_d, translationString, variables, tags, result) => {
                        expect(_t(translationString, variables, tags)).toEqual(result);
                    },
                );
            });
            describe('_tDom()', () => {
                it.each(testCasesEn)(
                    "%s and translates with fallback locale, attributes fallback locale",
                    async (_d, translationString, variables, tags, result) => {
                        expect(_tDom(translationString, variables, tags)).toEqual({ result });
                    },
                );
            });
        });
    });
});