// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.common with an alias.
import { createApp, provide, computed, watch<% if (enableTranslation) { %>, onMounted<% } %> } from 'vue';
import { createPinia, storeToRefs } from 'pinia'
<%_ if (enableTranslation) { _%>
import { useI18n } from 'vue-i18n';
<%_ } _%>

import { useStore<% if (enableTranslation) { %>, useTranslationStore<% } %> } from '@/store';
import { setupAxiosInterceptors } from '@/shared/config/axios-interceptor';

import App from './app.vue';
import router<% if (applicationTypeGateway && microfrontend) { %>, { lazyRoutes }<% } %> from './router';
import { initFortAwesome<% if (enableTranslation) { %>, initI18N<% } %> } from '@/shared/config/config';
import { initBootstrapVue } from '@/shared/config/config-bootstrap-vue';
import JhiItemCount from '@/shared/jhi-item-count.vue';
import JhiSortIndicator from '@/shared/sort/jhi-sort-indicator.vue';
<%_ if (authenticationUsesCsrf) { _%>
import LoginService from '@/account/login.service';
<%_ } _%>
<%_ if (generateUserManagement) { _%>
import { useLoginModal } from '@/account/login-modal';
<%_ } _%>
import AccountService from '@/account/account.service';

import '../content/scss/global.scss';
import '../content/scss/vendor.scss';
<%_ if (enableTranslation) { _%>
import TranslationService from '@/locale/translation.service';
<%_ } _%>
<%_ if (communicationSpringWebsocket) { _%>
import { useTrackerService } from './admin/tracker/tracker.service';
<%_ } _%>
<%_ if (applicationTypeGateway && microfrontend) { _%>
import { init } from '@module-federation/enhanced/runtime';

init({
  name: '<%= lowercaseBaseName %>',
  remotes: [
  <%_ for (const remote of microfrontends) { _%>
    {
      name: '<%= remote.lowercaseBaseName %>',
      entry: '/<%= remote.endpointPrefix %>/remoteEntry.js',
    },
  <%_ } _%>
  ],
});
<%_ } _%>

const pinia = createPinia();

// jhipster-needle-add-entity-service-to-main-import - JHipster will import entities services here
<%_ if (enableTranslation) { _%>

const i18n = initI18N();
<%_ } _%>

const app = createApp({
  components: { App },
  setup() {
<%_ if (authenticationUsesCsrf) { _%>
    provide('loginService', new LoginService());
<%_ } _%>
<%_ if (generateUserManagement) { _%>
    const { hideLogin, showLogin } = useLoginModal();
<%_ } _%>
    const store = useStore();
    const accountService = new AccountService(store);
<%_ if (enableTranslation) { _%>
    const i18n = useI18n();
    const translationStore = useTranslationStore();
    const translationService = new TranslationService(i18n);

    const changeLanguage = async (newLanguage: string) => {
      if (i18n.locale.value !== newLanguage) {
        await translationService.refreshTranslation(newLanguage);
        translationStore.setCurrentLanguage(newLanguage);
      }
    };

    provide('currentLanguage', i18n.locale);
    provide('changeLanguage', changeLanguage);

    watch(
      () => store.account,
      async value => {
        if (!translationService.getLocalStoreLanguage()) {
          await changeLanguage(value.langKey);
        }
      },
    );

    watch(
      () => translationStore.currentLanguage,
      value => {
        translationService.setLocale(value);
      },
    );

    onMounted(async () => {
      const lang = [
      translationService.getLocalStoreLanguage(),
        store.account?.langKey,
        navigator.language,
        '<%- nativeLanguage %>'
      ].find(lang => lang && translationService.isLanguageSupported(lang));
      await changeLanguage(lang);
    });
<%_ } else { _%>
    provide('currentLanguage', computed(() => store.account?.langKey ?? navigator.language ?? '<%- nativeLanguage %>'));
<%_ } _%>

    router.beforeResolve(async (to, from, next) => {
<%_ if (!authenticationTypeOauth2) { _%>
      // Make sure login modal is closed
      hideLogin();

<%_ } _%>
      if (!store.authenticated) {
        await accountService.update();
      }
      if (to.meta?.authorities && to.meta.authorities.length > 0) {
        const value = await accountService.hasAnyAuthorityAndCheckAuth(to.meta.authorities);
        if (!value) {
          if (from.path !== '/forbidden') {
            next({ path: '/forbidden' });
            return;
          }
        }
      }
      next();
    });

    setupAxiosInterceptors(
      error => {
        const url = error.response?.config?.url;
        const status = error.status || error.response?.status;
        if (status === 401) {
          // Store logged out state.
          store.logout();
          if (!url.endsWith('api/account') && !url.endsWith('api/<% if (authenticationTypeSession) { %>authentication<% } else { %>authenticate<% } %>')) {
            // Ask for a new authentication
<%_ if (authenticationTypeOauth2) { _%>
            window.location.reload();
<%_ } else { _%>
            showLogin();
<%_ } _%>
            return;
          }
        }
        return Promise.reject(error);
      },
      error => {
        return Promise.reject(error);
      },
    );

    const { authenticated } = storeToRefs(store);
    provide('authenticated', authenticated);
    provide(
      'currentUsername',
      computed(() => store.account?.login),
    );

<%_ if (enableTranslation) { _%>
    provide('translationService', translationService);
<%_ } _%>
    provide('accountService', accountService);
    // jhipster-needle-add-entity-service-to-main - JHipster will import entities services here
<%_ if (communicationSpringWebsocket) { _%>

    provide('trackerService', useTrackerService({ authenticated }));
<%_ } _%>
<%_ if (enableTranslation && applicationTypeMicroservice && microfrontend) { _%>
    provide('microfrontendI18n', false);
<%_ } _%>
  },
  template: '<App/>',
});

initFortAwesome(app);

initBootstrapVue(app);

app
  .component('JhiItemCount', JhiItemCount)
  .component('JhiSortIndicator', JhiSortIndicator)
  .use(router)
  .use(pinia)
<%_ if (enableTranslation) { _%>
  .use(i18n)
<%_ } _%>
  .mount('#app');
