// unitybase_adminui_vue - name from webpack config
/* global SystemJS, UB, unitybase_adminui_vue */
window.unitybase_adminui_vue = window.unitybase_adminui_vue || module.exports

/**
 * @module @unitybase/adminui-vue
 */
module.exports.runApp = async () => {
  UB.isExistExt = typeof window.Ext !== 'undefined'
  UB.IS_SYSTEM_JS = typeof SystemJS !== 'undefined'

  const moduleExports = require('./app/moduleExports')

  // INIT MODULE EXPORTS
  // eslint-disable-next-line no-global-assign
  unitybase_adminui_vue = moduleExports
  unitybase_adminui_vue.SidebarInstance = null

  // INIT OVERRIDE SYSTEMJS MODULES
  // register adminui-vue after all module.exports are defined - SystemJS.newModule memoryse an object props,
  // so any new property added after call to SystemJS.newModule are not available to importers
  if (UB.IS_SYSTEM_JS && !SystemJS.has('@unitybase/adminui-vue')) {
    SystemJS.set(
      '@unitybase/adminui-vue',
      SystemJS.newModule(unitybase_adminui_vue)
    )
  }

  const MainVueApp = require('./app/app')
  const initVue = require('./app/init/initVue')
  const initExtPolyfills = require('./app/extUBPolyfills/init')
  const initSpecialExtReplaces = require('./app/init/initSpecialExtReplaces')
  const { uDialogs, lookups, uiSettings } = moduleExports
  const $App = new MainVueApp()

  if (UB.IS_SYSTEM_JS && !SystemJS.has('@unitybase/adminui-pub')) {
    SystemJS.set('@unitybase/adminui-pub', SystemJS.newModule($App))
  }

  // INIT EXT POLYFILLS
  initExtPolyfills()

  // CONNECT UB APP (get UB.connection / UB.domainInfo)
  await $App.connect()

  // INIT CSS
  require('./app/init/initCss')

  // INIT VUE CONFIG / PROTOTYPES (depend on UB.connection)
  const Vue = initVue(
    [uDialogs, lookups], // additional plugins
    [{ key: 'uiSettings', value: uiSettings }] // additional prototypes
  )

  // LOAD MODELS, FETCH DATA
  await $App.init()

  // RUN (MOUNT) APP
  await $App.mount()

  // INIT SPECIAL EXT REPLACES
  initSpecialExtReplaces(Vue)

  // after all initializations we can hide the logo
  /**
   * Fires after application loads all models and mounts UI
   *
   * @event 'applicationReady'
   * @memberOf module:@unitybase/adminui-vue
   */
  $App.fireEvent('applicationReady')
  $App.hideLogo()

  // for CERT2 auth we must select crypto provider before connection, on this stage models is not available
  // the only way to give pki() function access to capiSelectionDialog is global window object
  const capiSelectionDialog = require('./views/capiSelectionDialog')

  if (window) {
    window.$AdminUiVue = unitybase_adminui_vue
    window.capiSelectionDialog = capiSelectionDialog
  }

  $App.on('appInitialize', function serviceAccountGuard () {
    if (UB.connection.userData('roles').split(',').includes('ServiceAccount')) {
      throw new UB.UBError(
        'Using of UI for members of "ServiceAccount" role is forbidden'
      )
    }
  })
}

// event fired by vue components documented here (jsdoc do not parse vue files)
/**
 * Insert some elements into user menu
 * @example
 *  Vue.nextTick(() => {
 *     const UserButtonSelectDepartment = require('./components/UserButtonSelectDepartment.vue').default
 *     $App.fireEvent('portal:navbar:userButton:appendSlot', UserButtonSelectDepartment, {})
 *   })
 *
 * @event 'portal:navbar:userButton:appendSlot'
 * @memberOf module:@unitybase/adminui-vue
 * @param {Component} Component
 * @param {object} bindings
 * @param {string<'menuAppend'|'logoutAppend'|'logoutPrepend'>} [slotName='default'] supported values: 'menuAppend', 'logoutAppend', 'logoutPrepend'
 */

/**
 * Fired on desktop changed
 *
 * @event 'portal:sidebar:desktopChanged'
 * @memberOf module:@unitybase/adminui-vue
 * @param {number} desktopID
 */