// 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>
  <span class="header-notice-opener">
    <a-select
      v-if="!isDisabled()"
      class="project-select"
      :loading="loading"
      v-model:value="projectSelected"
      :filterOption="filterProject"
      @change="changeProject"
      @focus="fetchData"
      showSearch>

      <a-select-option
        v-for="(project, index) in projects"
        :key="index"
        :label="project.displaytext || project.name">
        <span>
          <resource-icon v-if="project.icon && project.icon.base64image" :image="project.icon.base64image" size="1x" style="margin-right: 5px"/>
          <project-outlined v-else style="margin-right: 5px" />
          {{ project.displaytext || project.name }}
        </span>
      </a-select-option>
    </a-select>
  </span>
</template>

<script>
import store from '@/store'
import { api } from '@/api'
import _ from 'lodash'
import ResourceIcon from '@/components/view/ResourceIcon'

export default {
  name: 'ProjectMenu',
  components: {
    ResourceIcon
  },
  data () {
    return {
      projects: [],
      loading: false
    }
  },
  created () {
    this.fetchData()
  },
  computed: {
    projectSelected () {
      let projectIndex = 0
      if (this.$store.getters?.project?.id) {
        projectIndex = this.projects.findIndex(project => project.id === this.$store.getters.project.id)
        this.$store.dispatch('ToggleTheme', projectIndex === undefined ? 'light' : 'dark')
      }

      return projectIndex
    }
  },
  methods: {
    fetchData () {
      if (this.isDisabled()) {
        return
      }
      var page = 1
      const projects = []
      const getNextPage = () => {
        this.loading = true
        api('listProjects', { listAll: true, page: page, pageSize: 500, details: 'min', showIcon: true }).then(json => {
          if (json?.listprojectsresponse?.project) {
            projects.push(...json.listprojectsresponse.project)
          }
          if (projects.length < json.listprojectsresponse.count) {
            page++
            getNextPage()
          }
        }).finally(() => {
          this.loading = false
          this.$store.commit('RELOAD_ALL_PROJECTS', projects)
        })
      }
      getNextPage()
    },
    isDisabled () {
      return !Object.prototype.hasOwnProperty.call(store.getters.apis, 'listProjects')
    },
    changeProject (index) {
      const project = this.projects[index]
      this.$store.dispatch('ProjectView', project.id)
      this.$store.dispatch('SetProject', project)
      this.$store.dispatch('ToggleTheme', project.id === undefined ? 'light' : 'dark')
      this.$message.success(`${this.$t('message.switch.to')} "${project.displaytext || project.name}"`)
      if (this.$route.name !== 'dashboard') {
        this.$router.push({ name: 'dashboard' })
      }
    },
    filterProject (input, option) {
      return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
    }
  },
  mounted () {
    this.$store.watch(
      (state, getters) => getters.allProjects,
      (newValue, oldValue) => {
        if (oldValue !== newValue && newValue !== undefined) {
          this.projects = _.orderBy(newValue, ['displaytext'], ['asc'])
          this.projects.unshift({ name: this.$t('label.default.view') })
        }
      }
    )
  }
}
</script>

<style lang="less" scoped>
.project {
  &-select {
    width: 27vw;
  }

  &-icon {
    font-size: 20px;
    line-height: 1;
    padding-top: 5px;
    padding-right: 5px;
  }
}

.custom-suffix-icon {
  font-size: 20px;
  position: absolute;
  top: 0;
  right: 1px;
  margin-top: -5px;
}
</style>
