<!--
  ~ 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="__container_layout_header">
    <a-layout-header class="header">
      <a-flex style="height: 100%" justify="space-between" align="center">
        <a-flex>
          <menu-unfold-outlined
            v-if="collapsed"
            class="trigger"
            @click="() => (collapsed = !collapsed)"
          />
          <menu-fold-outlined v-else class="trigger" @click="() => (collapsed = !collapsed)" />
        </a-flex>
        <div></div>
        <a-flex :gap="20">
          <a-input-group @keyup.enter="globalSearch" class="search-group" compact>
            <a-select v-model:value="searchType" class="select-type">
              <a-select-option v-for="option in searchTypeOptions" :value="option.value"
                >{{ option.label }}
              </a-select-option>
            </a-select>
            <a-auto-complete
              v-model:value="keywords"
              class="input-keywords"
              :placeholder="$t('globalSearchTip')"
              :options="candidates"
              @select="onSelect"
              @search="inputChange"
            />
            <a-button
              :icon="h(SearchOutlined)"
              class="search-icon"
              @click="globalSearch"
            ></a-button>
          </a-input-group>
          <a-form layout="inline">
            <a-form-item class="mesh-select-item" :label="$t('registryCenter')" inline>
              <a-select
                class="mesh-select"
                :value="meshStore.mesh"
                :options="
                  meshes.map((x: any) => {
                    return {
                      value: x.id,
                      label: x.name
                    }
                  })
                "
                @change="changeMesh"
              ></a-select>
            </a-form-item>
          </a-form>
        </a-flex>
        <div></div>

        <a-flex align="center" gap="middle">
          <a-flex align="center">
            <a-segmented v-model:value="locale" :options="i18nConfig.opts" />
          </a-flex>
          <a-flex align="center">
            <color-picker
              :pureColor="PRIMARY_COLOR"
              @pureColorChange="changeTheme"
              format="hex6"
              shape="circle"
              useType="pure"
            ></color-picker>
            <a-popover>
              <template #content>reset the theme</template>
              <Icon
                class="reset-icon"
                icon="material-symbols:reset-tv-outline"
                @click="resetTheme"
              ></Icon>
            </a-popover>
          </a-flex>
          <a-flex align="center">
            <a-dropdown>
              <a-avatar @click="">
                <template #icon>
                  <UserOutlined />
                </template>
              </a-avatar>
              <template #overlay>
                <a-menu>
                  <a-menu-item @click="logoutHandle">
                    <a href="javascript:;">logout</a>
                  </a-menu-item>
                </a-menu>
              </template>
            </a-dropdown>
            <span class="username">{{ authState?.userinfo?.username }}</span>
          </a-flex>
        </a-flex>
      </a-flex>
    </a-layout-header>
  </div>
</template>

<script setup lang="ts">
import {
  MenuFoldOutlined,
  MenuUnfoldOutlined,
  SearchOutlined,
  UserOutlined
} from '@ant-design/icons-vue'
import { type ComponentInternalInstance, onMounted } from 'vue'
import { computed, getCurrentInstance, h, inject, nextTick, reactive, ref, watch } from 'vue'
import { PROVIDE_INJECT_KEY } from '@/base/enums/ProvideInject'
import { changeLanguage, localeConfig } from '@/base/i18n'
import {
  LOCAL_STORAGE_THEME,
  PRIMARY_COLOR,
  PRIMARY_COLOR_DEFAULT,
  PRIMARY_COLOR_R
} from '@/base/constants'
import { Icon } from '@iconify/vue'
import { debounce } from 'lodash'
import type { SelectOption } from '@/types/common.ts'
import { searchApplications } from '@/api/service/app'
import { searchInstances } from '@/api/service/instance'
import { searchService } from '@/api/service/service'
import { useRoute, useRouter } from 'vue-router'
import { getAuthState, removeAuthState } from '@/utils/AuthUtil'
import { logout } from '@/api/service/login'
import { useMeshStore } from '@/stores/mesh'
import { meshesSearch } from '@/api/service/globalSearch'

const {
  appContext: {
    config: { globalProperties }
  }
} = <ComponentInternalInstance>getCurrentInstance()

let __null = PRIMARY_COLOR
let __null_r = PRIMARY_COLOR_R
const collapsed = inject(PROVIDE_INJECT_KEY.COLLAPSED)
const i18nConfig = <typeof localeConfig>inject(PROVIDE_INJECT_KEY.LOCALE)
let locale = ref(localeConfig.locale)

function changeTheme(val: string) {
  localStorage.setItem(LOCAL_STORAGE_THEME, val)
  PRIMARY_COLOR.value = val
}

function resetTheme(val: string) {
  localStorage.removeItem(LOCAL_STORAGE_THEME)
  PRIMARY_COLOR.value = PRIMARY_COLOR_DEFAULT
}
function logoutHandle() {
  removeAuthState()
  logout().then(() => {
    router.replace(`/login?redirect=${route.path}`)
  })
}

const meshes = ref([])
const meshStore = useMeshStore()
const refreshCurrentRoute: any = inject(PROVIDE_INJECT_KEY.LAYOUT_ROUTE_KEY)
const changeMesh = (value: any) => {
  meshStore.mesh = value
  refreshCurrentRoute()
}

onMounted(async () => {
  const { data } = await meshesSearch()
  meshes.value = data
})

const authState = getAuthState()
watch(locale, (value) => {
  changeLanguage(value)
})

const searchTypeOptions = reactive([
  // Temporarily hidden, awaiting improvement
  // {
  //   label: 'IP',
  //   value: 'ip'
  // },
  {
    label: computed(() => globalProperties.$t('application')),
    value: 'applications'
  },
  {
    label: computed(() => globalProperties.$t('instance')),
    value: 'instances'
  },
  {
    label: computed(() => globalProperties.$t('service')),
    value: 'services'
  }
])
const searchType = ref(searchTypeOptions[0].value)

const keywords = ref('')

const onSearch = async () => {
  const params = {
    keywords: keywords.value
  }

  // Public search processing function
  const globalSearch = async (searchFunc: Function, labelKey: string) => {
    const {
      data: { list }
    } = await searchFunc(params)

    // Using map instead of forEach is more concise.
    candidates.value = list.map((item: any) => ({
      label: item[labelKey],
      value: item[labelKey]
    }))
  }

  // Various types of search functions
  const globalSearchByIp = () => {
    // The IP search logic is undefined and left blank.
  }

  switch (searchType.value) {
    case 'ip':
      globalSearchByIp()
      break
    case 'applications':
      await globalSearch(searchApplications, 'appName')
      break
    case 'instances':
      await globalSearch(searchInstances, 'name')
      break
    case 'services':
      await globalSearch(searchService, 'serviceName')
      break
    default:
      break
  }
}

// Listen for changes in searchType and trigger a search.
watch(searchType, async (newType) => {
  await onSearch() // When a change is detected, re-call the search function.
})

const candidates = ref<Array<SelectOption>>([])

const inputChange = debounce(onSearch, 300)
const router = useRouter()
const route = useRoute()
const globalSearch = () => {
  router.replace(`/resources/${searchType.value}/list?query=${keywords.value}`)
}
const onSelect = () => {}
</script>
<style lang="less" scoped>
.__container_layout_header {
  .header {
    background: v-bind('PRIMARY_COLOR');
    padding: 0;
    .mesh-select {
      min-width: 100px;
    }
    .mesh-select-item {
      :deep(label) {
        color: v-bind('PRIMARY_COLOR_R');
      }
    }
    .search-group {
      display: flex;
      align-items: center;

      .select-type {
        width: 120px;
      }

      .input-keywords {
        &:hover {
          border-color: #d9d9d9;
          :deep(.ant-select-selector) {
            border-color: #d9d9d9;
          }
        }
        width: calc(20vw);
        :deep(.ant-select-selector) {
          border-color: #d9d9d9;
          box-shadow: none;
          &:hover {
            border-color: #d9d9d9;
            box-shadow: none;
          }
        }
      }

      .search-icon {
        width: 32px;
      }
    }
  }

  .trigger {
    font-size: 20px;
    margin-left: 20px;
    color: white;
  }

  .username {
    color: white;
    padding: 5px;
  }

  .reset-icon {
    font-size: 25px;
    color: white;
    //margin-bottom: -9px;
  }
}
</style>
