<template>
  <a-config-provider :locale="antdLocale">
    <div id="app" :class="{ 'ops-fullscreen': isOpsFullScreen, 'ops-only-topmenu': isOpsOnlyTopMenu }">
      <router-view v-if="alive" />
    </div>
  </a-config-provider>
</template>

<script>
import { mapState, mapActions, mapMutations } from 'vuex'
import zhCN from 'ant-design-vue/lib/locale-provider/zh_CN'
import enUS from 'ant-design-vue/lib/locale-provider/en_US'
import { AppDeviceEnquire } from '@/utils/mixin'
import { debounce } from './utils/util'
import { getSystemLanguage } from '@/api/system.js'

import { h } from 'snabbdom'
import { DomEditor, Boot } from '@wangeditor/editor'

export default {
  mixins: [AppDeviceEnquire],
  provide() {
    return {
      reload: this.reload,
    }
  },
  data() {
    return {
      alive: true,
      timer: null,
    }
  },
  computed: {
    ...mapState(['locale']),
    antdLocale() {
      if (this.locale === 'zh') {
        return zhCN
      }
      return enUS
    },
    isOpsFullScreen() {
      return ['cmdb_screen'].includes(this.$route.name)
    },
    isOpsOnlyTopMenu() {
      return ['fullscreen_index', 'setting_person', 'notice_center'].includes(this.$route.name)
    },
  },
  created() {
    this.initLanguage()
    this.timer = setInterval(() => {
      this.setTime(new Date().getTime())
    }, 1000)
  },
  mounted() {
    this.$store.dispatch('setWindowSize')
    window.addEventListener(
      'resize',
      debounce(() => {
        this.$store.dispatch('setWindowSize')
      })
    )

    this.handleEditor()
  },
  beforeDestroy() {
    clearInterval(this.timer)
  },
  methods: {
    ...mapActions(['setTime']),
    ...mapMutations(['SET_LOCALE']),
    reload() {
      this.alive = false
      this.$nextTick(() => {
        this.alive = true
      })
    },
    async initLanguage() {
      let saveLocale = localStorage.getItem('ops_locale')
      if (!saveLocale) {
        let requestLanguage = ''
        try {
          const languageRes = await getSystemLanguage()
          requestLanguage = languageRes?.language || ''
        } catch (e) {
          console.error('getSystemLanguage error:', e)
        }

        // request language variable || user local system language
        const userLanguage = requestLanguage || navigator.language || navigator.userLanguage
        if (userLanguage.includes('zh')) {
          saveLocale = 'zh'
        } else {
          saveLocale = 'en'
        }
      }
      this.SET_LOCALE(saveLocale)
      this.$i18n.locale = saveLocale
    },

    handleEditor() {
      // register custom rich text element: attachment
      function withAttachment(editor) {
        const { isInline, isVoid } = editor
        const newEditor = editor

        newEditor.isInline = (elem) => {
          const type = DomEditor.getNodeType(elem)
          if (type === 'attachment') return true // For type: attachment, set to inline
          return isInline(elem)
        }

        newEditor.isVoid = (elem) => {
          const type = DomEditor.getNodeType(elem)
          if (type === 'attachment') return true // For type: attachment ，set to void
          return isVoid(elem)
        }

        return newEditor // Must return, important!!!
      }
      Boot.registerPlugin(withAttachment)
      /**
       * Render "attachment" element in editor
       * @param elem Attachment element
       * @param children Child nodes (ignored for void elements)
       * @param editor Editor instance
       * @returns vnode (generated by snabbdom's h function)
       */
      function renderAttachment(elem, children, editor) {
        const { attachmentLabel = '', attachmentValue = '' } = elem

        const attachVnode = h(
          // HTML tag
          'span',
          // HTML attr, style, event
          {
            props: { contentEditable: false },
            style: {
              display: 'inline-block',
              margin: '0 3px',
              padding: '0 3px',
              backgroundColor: '#e6f7ff',
              border: '1px solid #91d5ff',
              borderRadius: '2px',
              color: '#1890ff',
            },
            on: {
              click() {
                console.log('clicked', attachmentValue)
              }
            },
          },
          // child node
          [attachmentLabel]
        )

        return attachVnode
      }
      const renderElemConf = {
        type: 'attachment',
        renderElem: renderAttachment,
      }
      Boot.registerRenderElem(renderElemConf)

      /**
       * Generate HTML for "attachment" element
       * @param elem Attachment element
       * @param childrenHtml Child HTML (ignored for void elements)
       * @returns HTML string
       */
      function attachmentToHtml(elem, childrenHtml) {
        // Getting data for attached elements
        const { attachmentValue = '', attachmentLabel = '' } = elem

        // generate HTML
        const html = `<span data-w-e-type="attachment" data-w-e-is-void data-w-e-is-inline data-attachmentValue="${attachmentValue}" data-attachmentLabel="${attachmentLabel}">${attachmentLabel}</span>`

        return html
      }
      const elemToHtmlConf = {
        type: 'attachment',
        elemToHtml: attachmentToHtml,
      }
      Boot.registerElemToHtml(elemToHtmlConf)

      /**
       * Parse HTML to generate "attachment" element
       * @param domElem DOM element
       * @param children Children
       * @param editor Editor instance
       * @returns Attachment element
       */
      function parseAttachmentHtml(domElem, children, editor) {
        // Getting “attachment” information from DOM element
        const attachmentValue = domElem.getAttribute('data-attachmentValue') || ''
        const attachmentLabel = domElem.getAttribute('data-attachmentLabel') || ''

        const myResume = {
          type: 'attachment',
          attachmentValue,
          attachmentLabel,
          children: [{ text: '' }], // The void node must have children with an empty string in it, important!!!!
        }

        return myResume
      }
      const parseHtmlConf = {
        selector: 'span[data-w-e-type="attachment"]', // CSS selector to match specific HTML tags
        parseElemHtml: parseAttachmentHtml,
      }
      Boot.registerParseElemHtml(parseHtmlConf)
    }
  },
}
</script>
<style lang="less">
@import './style/index.less';

#app {
  height: 100%;
}
</style>
