import TbWContentAreaUsageInstructions from './tb-w-content-area-usage-instructions';
import TbWModuleLinks from './Components/tb-w-module-links';
import TbNullComponent from './Components/tb-null-component';
import registryProxy from './component-registry';
import { Buffer } from './../../../node_modules/buffer';
import { isSsr } from '@newland/toubiz-widget/src/env';
import store from '@newland/toubiz-widget/src/store/store.vuex';
import { storeDisplayConfig } from '@newland/toubiz-widget/src/utilities/store-config';
import VueI18n from 'vue-i18n';

global.Buffer = Buffer;

export async function initializeToubizWidgetVueApp(template = null) {

    // Fill in missing btoa method
    // @see https://stackoverflow.com/questions/23097928/node-js-throws-btoa-is-not-defined-error
    // @todo: Is this the correct place to do this?
    if (typeof btoa === 'undefined') {
        global.btoa = function(str) {
            return Buffer.from(str, 'binary').toString('base64');
        };
    }
    if (typeof atob === 'undefined') {
        global.atob = function(b64Encoded) {
            return Buffer.from(b64Encoded, 'base64').toString('binary');
        };
    }

    const [ Vue, ToubizWidget ] = await Promise.all([
        import('vue').then(mod => mod.default),
        import('@newland/toubiz-widget').then(mod => mod.default),
    ]);

    Vue.use(ToubizWidget, {
        vuexInit: false,
        initializeVuexStore: () => null,
        initializeRouter: () => null,
        registerLinkGenerators(registry) {
            registry.registerLinkGenerator(
                'article.detail',
                (route, language) => `/redirect/article/${route.params.id}/${language}`,
            );
            registry.registerLinkGenerator(
                'article.list',
                (route, language) => `/redirect/list/articles/${language}?params=${route.query.params}`,
            );
            registry.registerLinkGenerator(
                'event.detail',
                (route, language) => `/redirect/event/${route.params.id}/${language}`,
            );
            registry.registerLinkGenerator(
                'eventDate.detail',
                (route, language) => `/redirect/event/${route.params.eventId}/${language}`,
            );
            registry.registerLinkGenerator(
                'event.list',
                (route, language) => `/redirect/list/events/${language}?params=${route.query.params}`,
            );
            registry.registerLinkGenerator(
                'collection.detail',
                (route, language) => `/redirect/collection/${route.params.id}/${language}`,
            );
            registry.registerLinkGenerator(
                'collection.list',
                (route, language) => `/redirect/list/collections/${language}?params=${route.query.params}`,
            );
        },
        componentRegistration(registry) {
            registryProxy.apply(registry);
            registry.replaceComponent('tb-w-content-area-usage-instructions', TbWContentAreaUsageInstructions);
            registry.replaceComponent('tb-w-module-links', TbWModuleLinks);
            registry.replaceComponent('tb-w-corona-element-links', TbNullComponent);
        },
        errorLoggerHints: [
            {
                check: () => process.env.NODE_ENV === 'production',
                hint: `
                    Check the \`buildMode\` setting of the \`serverSide\` renderer in the
                    \`Newland.ToubizWidgetRendering\` package in order to change the build mode to \`development\`.

                    Building the app in development mode may yield additional error information.
                `,
            },
        ],
    });

    const i18n = new VueI18n({
        fallbackLocale: [ 'en', 'de' ],
        silentFallbackWarn: typeof window === 'undefined',  // isSsr,
        locale: 'de',
    });

    const VueExtended = Vue.extend({ i18n });

    return new VueExtended({
        template,
        store,
        created() {
            if (process.env.WIDGET_CONFIGURATION) {
                const config = JSON.parse(process.env.WIDGET_CONFIGURATION);
                storeDisplayConfig(config, store);
            }

            if (!isSsr()) {
                const credentials = window.ToubizWidget?.credentials;
                if (credentials) {
                    this.initializeRepositories(credentials);
                    store.commit('setApiCredentials', credentials);
                }
            }
        },
        beforeMount() {
            this.setGlobalLanguage();
        },
        data: () => ({
            baseUri: process.env.TOUBIZ_BASE_URI,
        }),
    });
}
