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/setup/store.vuex';

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) => `/redirect/article/${route.params.id}`);
            registry.registerLinkGenerator(
                'article.list',
                (route) => `/redirect/articles?params=${route.query.params}`,
            );
            registry.registerLinkGenerator('event.detail', (route) => `/redirect/event/${route.params.id}`);
            registry.registerLinkGenerator('event.list', (route) => `/redirect/events?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-area-collections', TbNullComponent);
            registry.replaceComponent('tb-w-show-all', 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.
                `,
            },
        ],
    });

    return new Vue({
        template,
        store,
        created() {
            if (!isSsr()) {
                const credentials = window.ToubizWidget?.credentials;
                if (credentials) {
                    this.initializeRepositories(credentials);
                }
            }
        },
        data: () => ({
            baseUri: process.env.TOUBIZ_BASE_URI,
        }),
    });
}
