// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

<template>
  <div class="user-menu">
    <span class="action">
      <create-menu v-if="device === 'desktop'" />
    </span>
    <external-link class="action"/>
    <translation-menu class="action"/>
    <header-notice class="action"/>
    <label class="user-menu-server-info action" v-if="$config.multipleServer">
      <database-outlined />
      {{ server.name || server.apiBase || 'Local-Server' }}
    </label>
    <a-dropdown>
      <span class="user-menu-dropdown action">
        <span v-if="image">
          <resource-icon :image="image" size="4x" style="margin-right: 5px; margin-top: -3px"/>
        </span>
        <a-avatar v-else-if="userInitials" class="user-menu-avatar avatar" size="small" :style="{ backgroundColor: $config.theme['@primary-color'], color: 'white' }">
          {{ userInitials }}
        </a-avatar>
        <a-avatar v-else class="user-menu-avatar avatar" size="small" :style="{ backgroundColor: $config.theme['@primary-color'], color: 'white' }">
          <template #icon><user-outlined /></template>
        </a-avatar>
        <span>{{ nickname() }}</span>
      </span>
      <template #overlay>
        <a-menu class="user-menu-wrapper" @click="handleClickMenu">
          <a-menu-item class="user-menu-item" key="profile">
            <UserOutlined class="user-menu-item-icon" />
            <span class="user-menu-item-name">{{ $t('label.profilename') }}</span>
          </a-menu-item>
          <a-menu-item class="user-menu-item" key="limits">
            <ControlOutlined class="user-menu-item-icon" />
            <span class="user-menu-item-name">{{ $t('label.limits') }}</span>
          </a-menu-item>
          <a-menu-item class="user-menu-item" key="timezone">
            <ClockCircleOutlined class="user-menu-item-icon" />
            <span class="user-menu-item-name" style="margin-right: 5px">{{ $t('label.use.local.timezone') }}</span>
            <a-switch :checked="$store.getters.usebrowsertimezone" />
          </a-menu-item>
          <a-menu-item class="user-menu-item" key="document">
            <QuestionCircleOutlined class="user-menu-item-icon" />
            <span class="user-menu-item-name">{{ $t('label.help') }}</span>
          </a-menu-item>
          <a-menu-divider/>
          <a-menu-item class="user-menu-item" key="logout">
            <LogoutOutlined class="user-menu-item-icon" />
            <span class="user-menu-item-name">{{ $t('label.logout') }}</span>
          </a-menu-item>
        </a-menu>
      </template>
    </a-dropdown>
  </div>
</template>

<script>
import { getAPI } from '@/api'
import CreateMenu from './CreateMenu'
import ExternalLink from './ExternalLink'
import HeaderNotice from './HeaderNotice'
import TranslationMenu from './TranslationMenu'
import { mapActions, mapGetters } from 'vuex'
import ResourceIcon from '@/components/view/ResourceIcon'
import eventBus from '@/config/eventBus'
import { SERVER_MANAGER } from '@/store/mutation-types'
import { sourceToken } from '@/utils/request'
import { applyCustomGuiTheme } from '@/utils/guiTheme'

export default {
  name: 'UserMenu',
  components: {
    CreateMenu,
    ExternalLink,
    TranslationMenu,
    HeaderNotice,
    ResourceIcon
  },
  props: {
    device: {
      type: String,
      required: false,
      default: 'desktop'
    }
  },
  data () {
    return {
      image: '',
      userInitials: '',
      countNotify: 0
    }
  },
  created () {
    this.userInitials = (this.$store.getters.userInfo.firstname.toUpperCase().charAt(0) || '') +
      (this.$store.getters.userInfo.lastname.toUpperCase().charAt(0) || '')
    this.getIcon()
    eventBus.on('refresh-header', () => {
      this.getIcon()
    })
    this.$store.watch(
      (state, getters) => getters.countNotify,
      (newValue, oldValue) => {
        this.countNotify = newValue
      }
    )
  },
  watch: {
    image () {
      this.getIcon()
    }
  },
  computed: {
    server () {
      return this.$localStorage.get(SERVER_MANAGER) || this.$config.servers[0]
    }
  },
  methods: {
    ...mapActions(['Logout']),
    ...mapGetters(['nickname', 'avatar']),
    toggleUseBrowserTimezone () {
      this.$store.dispatch('SetUseBrowserTimezone', !this.$store.getters.usebrowsertimezone)
    },
    async getIcon () {
      await this.fetchResourceIcon(this.$store.getters.userInfo.id)
    },
    fetchResourceIcon (id) {
      return new Promise((resolve, reject) => {
        if (this.$store.getters.avatar) {
          this.image = this.$store.getters.avatar
          resolve(this.image)
        }
        getAPI('listUsers', {
          id: id,
          showicon: true
        }).then(json => {
          const response = json.listusersresponse.user || []
          if (response?.[0]) {
            this.image = response[0]?.icon?.base64image || ''
            this.$store.commit('SET_AVATAR', this.image)
            resolve(this.image)
          }
        }).catch(error => {
          reject(error)
        })
      })
    },
    handleClickMenu (item) {
      switch (item.key) {
        case 'profile':
          this.$router.push(`/accountuser/${this.$store.getters.userInfo.id}`)
          break
        case 'limits':
          this.$router.push(`/account/${this.$store.getters.userInfo.accountid}?tab=limits`)
          break
        case 'timezone':
          this.toggleUseBrowserTimezone()
          break
        case 'document':
          window.open(this.$config.docBase, '_blank')
          break
        case 'logout':
          this.handleLogout()
          break
      }
    },
    handleLogout () {
      this.Logout({}).finally(async () => {
        sourceToken.init()
        await applyCustomGuiTheme(null, null)
        this.$router.push('/user/login')
      }).catch(err => {
        this.$message.error({
          title: 'Failed to Logout',
          description: err.message
        })
      })
    },
    clearAllNotify () {
      this.$store.commit('SET_COUNT_NOTIFY', 0)
      this.$notification.destroy()
    }
  }
}
</script>

<style lang="less" scoped>
.user-menu {
  &-wrapper {
    padding: 4px 0;
  }

  &-item {
    width: auto;
  }

  &-item-name {
    user-select: none;
    margin-left: 8px;
  }

  &-item-icon i {
    min-width: 12px;
    margin-right: 8px;
  }

  &-server-info {
    .anticon {
      margin-right: 5px;
    }
  }
}
</style>
