import i18n from 'i18next';
import Backend from 'i18next-chained-backend';
import XHR from 'i18next-xhr-backend';
import LocalStorageBackend from 'i18next-localstorage-backend'
import LanguageDetector from 'i18next-browser-languagedetector';
import {reactI18nextModule} from 'react-i18next';

import config from '../i18n.json';

i18n
// load translation using xhr -> see /public/locales
// learn more: https://github.com/i18next/i18next-xhr-backend
    .use(Backend)
    // detect user language
    // learn more: https://github.com/i18next/i18next-browser-languageDetector
    .use(LanguageDetector)
    // pass the i18n instance to the react-i18next components.
    // Alternative use the I18nextProvider: https://react.i18next.com/components/i18nextprovider
    .use(reactI18nextModule)
    // init i18next
    // for all options read: https://www.i18next.com/overview/configuration-options
    .init({
        allLanguages: config.allLanguages,
        defaultLanguage: config.defaultLanguage,
        fallbackLng: process.env.NODE_ENV === 'production' ? config.defaultLanguage : null,
        debug: config.debug,

        defaultNS: 'common',
        interpolation: {
            escapeValue: false, // not needed for react as it escapes by default
        },

        // special options for react-i18next
        // learn more: https://react.i18next.com/components/i18next-instance
        react: {
            wait: true
        },

        detection: {
            order: ['path', 'localStorage'],

            lookupLocalStorage: 'i18nextLng',
            lookupFromPathIndex: 0,

            // cache user language on
            caches: ['localStorage'],
            excludeCacheFor: ['cimode'], // languages to not persist (cookie, localStorage)
        },

        backend: {
            backends: [
                LocalStorageBackend,  // primary
                XHR                   // fallback
            ],
            backendOptions: [{
                // prefix for stored languages
                prefix: 'i18next_res_',

                // expiration
                //expirationTime: 7 * 24 * 60 * 60 * 1000,
                //expirationTime: 60 * 60 * 1000,
                expirationTime: 60,

                // language versions
                versions: {}
            }, {
                // path where resources get loaded from, or a function
                // returning a path:
                // function(lngs, namespaces) { return customPath; }
                // the returned path will interpolate lng, ns if provided like giving a static path
                loadPath: '/locale/{{lng}}/{{ns}}.json',

                // path to post missing resources
                //addPath: 'locales/add/{{lng}}/{{ns}}',

                // your backend server supports multiloading
                // /locales/resources.json?lng=de+en&ns=ns1+ns2
                allowMultiLoading: false, // set loadPath: '/locales/resources.json?lng={{lng}}&ns={{ns}}' to adapt to multiLoading

                // parse data after it has been fetched
                // in example use https://www.npmjs.com/package/json5
                // here it removes the letter a from the json (bad idea)
                /*parse: function(data) {
                    return data.replace(/a/g, '');
                },*/

                // allow cross domain requests
                crossDomain: false,

                // allow credentials on cross domain requests
                withCredentials: false,

                // define a custom xhr function
                // can be used to support XDomainRequest in IE 8 and 9
                //
                // 'url' will be passed the value of 'loadPath'
                // 'options' will be this entire options object
                // 'callback' is a function that takes two parameters, 'data' and 'xhr'.
                //            'data' should be the key:value translation pairs for the
                //            requested language and namespace, or null in case of an error.
                //            'xhr' should be a status object, e.g. { status: 200 }
                // 'data' will be a key:value object used when saving missing translations
                /*ajax: function(url, options, callback, data) {
                    console.log('url');
                },*/

                // adds parameters to resource URL. 'example.com' -> 'example.com?v=1.3.5'
                //queryStringParams: {v: '1.3.5'}
            }]
        }
    });

// add allLanguages prop, as i18n doesn't have such a thing on its own / i18n.languages only returns loaded languages
i18n.allLanguages = config.allLanguages;

export default i18n;

// to have one instance everywhere
const event = {
    list: {}
};

/**
 * The global theme got the themeprovider in BaseApp, the state of it controls the applied theme, to be able to change the theme from where ever, `provide` the state setting function and add `exec` on e.g. a button onClick
 */
const i18nProvider = {
    on: (name, handler) => {
        let rnd = Math.random().toString(36).substring(7);

        if('undefined' === typeof event.list[name]) {
            // none existing, init
            event.list[name] = {};
        } else if(event.list[name].hasOwnProperty(rnd)) {
            // when id already exists, start again to create new
            return i18nProvider.on(name, handler);
        }

        event.list[name][rnd] = handler;

        return rnd;
    },
    trigger: (name, payload = []) => {
        if(event.list[name]) {
            for(let id in event.list[name]) {
                if(event.list[name].hasOwnProperty(id)) {
                    event.list[name][id](payload);
                }
            }
        }
    },
    off: (name, id) => {
        if(event.list[name] && event.list[name].hasOwnProperty(id)) {
            delete event.list[name][id];
        }
    }
};

export {i18nProvider};
