// 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 :style="styleSearch">
    <span v-if="!searchFilters || searchFilters.length === 0" style="display: flex;">
      <a-input-search
        v-model:value="searchQuery"
        :placeholder="$t('label.search')"
        allowClear
        @search="onSearch"
      />
    </span>

    <span
      v-else
      class="filter-group">
      <a-input-search
        allowClear
        class="input-search"
        :placeholder="$t('label.search')"
        v-model:value="searchQuery"
        @search="onSearch">
        <template #addonBefore>
          <a-popover
            placement="bottomRight"
            trigger="click"
            v-model:visible="visibleFilter">
            <template #content v-if="visibleFilter">
              <a-form
                style="min-width: 170px"
                :ref="formRef"
                :model="form"
                :rules="rules"
                layout="vertical"
                @finish="handleSubmit"
                v-ctrl-enter="handleSubmit">
                <a-form-item
                  v-for="(field, index) in fields"
                  :ref="field.name"
                  :name="field.name"
                  :key="index"
                  :label="retrieveFieldLabel(field.name)">
                  <a-select
                    allowClear
                    v-if="field.type==='list'"
                    v-model:value="form[field.name]"
                    showSearch
                    :dropdownMatchSelectWidth="false"
                    optionFilterProp="label"
                    :filterOption="(input, option) => {
                      return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                    }"
                    :loading="field.loading"
                    @input="onchange($event, field.name)"
                    @change="onSelectFieldChange(field.name)">
                    <a-select-option
                      v-for="(opt, idx) in field.opts"
                      :key="idx"
                      :value="['account'].includes(field.name) ? opt.name : opt.id"
                      :label="$t((['storageid'].includes(field.name) || !opt.path) ? opt.name : opt.path)">
                      <div>
                        <span v-if="(field.name.startsWith('zone'))">
                          <span v-if="opt.icon">
                            <resource-icon :image="opt.icon.base64image" size="1x" style="margin-right: 5px"/>
                          </span>
                          <global-outlined v-else style="margin-right: 5px" />
                        </span>
                        <span v-if="(field.name.startsWith('domain') || field.name === 'account' || field.name.startsWith('associatednetwork'))">
                          <span v-if="opt.icon">
                            <resource-icon :image="opt.icon.base64image" size="1x" style="margin-right: 5px"/>
                          </span>
                          <block-outlined v-else style="margin-right: 5px" />
                        </span>
                        <span v-if="(field.name.startsWith('managementserver'))">
                          <status :text="opt.state" />
                        </span>
                        {{ $t((['storageid'].includes(field.name) || !opt.path) ? opt.name : opt.path) }}
                      </div>
                    </a-select-option>
                  </a-select>
                  <a-input
                    v-else-if="field.type==='input'"
                    v-model:value="form[field.name]" />
                  <div v-else-if="field.type==='tag'">
                    <a-input-group
                      type="text"
                      size="small"
                      compact>
                      <a-input ref="input" v-model:value="inputKey" style="width: 50px; text-align: center" :placeholder="$t('label.key')" />
                      <a-input
                        class="tag-disabled-input"
                        style=" width: 20px; border-left: 0; pointer-events: none; text-align: center"
                        placeholder="="
                        disabled />
                      <a-input v-model:value="inputValue" style="width: 50px; text-align: center; border-left: 0" :placeholder="$t('label.value')" />
                      <tooltip-button :tooltip="$t('label.clear')" icon="close-outlined" size="small" @onClick="inputKey = inputValue = ''" />
                    </a-input-group>
                  </div>
                  <a-switch
                    v-else-if="field.type==='boolean'"
                    v-model:checked="form[field.name]"
                  />
                  <a-auto-complete
                    v-else-if="field.type==='autocomplete'"
                    v-model:value="form[field.name]"
                    :placeholder="$t('message.error.input.value')"
                    :options="field.opts"
                    :filterOption="(inputValue, option) => {
                      return option.value.toLowerCase().indexOf(inputValue.toLowerCase()) !== -1
                    }" />
                </a-form-item>
                <div class="filter-group-button">
                  <a-button
                    class="filter-group-button-clear"
                    type="default"
                    size="small"
                    @click="onClear">
                    <template #icon><stop-outlined /></template>
                    {{ $t('label.reset') }}
                  </a-button>
                  <a-button
                    class="filter-group-button-search"
                    type="primary"
                    size="small"
                    ref="submit"
                    html-type="submit">
                    <template #icon><search-outlined /></template>
                    {{ $t('label.search') }}
                  </a-button>
                </div>
              </a-form>
            </template>
            <a-button
              class="filter-button"
              size="small"
              @click="() => { searchQuery = null }">
              <filter-two-tone v-if="isFiltered" />
              <filter-outlined v-else />
            </a-button>
          </a-popover>
        </template>
      </a-input-search>
    </span>
  </span>
</template>

<script>
import { ref, reactive, toRaw } from 'vue'
import { api } from '@/api'
import { isAdmin } from '@/role'
import TooltipButton from '@/components/widgets/TooltipButton'
import ResourceIcon from '@/components/view/ResourceIcon'
import Status from '@/components/widgets/Status'
import { i18n } from '@/locales'

export default {
  name: 'SearchView',
  components: {
    TooltipButton,
    ResourceIcon,
    Status
  },
  props: {
    searchFilters: {
      type: Array,
      default: () => []
    },
    apiName: {
      type: String,
      default: () => ''
    },
    searchParams: {
      type: Object,
      default: () => {}
    }
  },
  data () {
    return {
      searchQuery: null,
      paramsFilter: {},
      visibleFilter: false,
      fields: [],
      inputKey: null,
      inputValue: null,
      fieldValues: {},
      isFiltered: false,
      alertTypes: []
    }
  },
  created () {
    this.formRef = ref()
    this.form = reactive({})
    this.rules = reactive({})
  },
  watch: {
    visibleFilter (newValue, oldValue) {
      if (newValue) {
        this.initFormFieldData()
      }
    },
    '$route' (to, from) {
      this.searchQuery = ''
      if (to && to.query && 'q' in to.query) {
        this.searchQuery = to.query.q
      }
      this.updateIsFiltered()
    }
  },
  mounted () {
    this.searchQuery = ''
    if (this.$route && this.$route.query && 'q' in this.$route.query) {
      this.searchQuery = this.$route.query.q
    }
    this.updateIsFiltered()
  },
  computed: {
    styleSearch () {
      if (!this.searchFilters || this.searchFilters.length === 0) {
        return {
          width: '100%',
          display: 'table-cell'
        }
      }

      return {
        width: '100%',
        display: 'table-cell',
        lineHeight: '31px'
      }
    }
  },
  methods: {
    onchange: async function (event, fieldname) {
      this.fetchDynamicFieldData(fieldname, event.target.value)
    },
    onSelectFieldChange (fieldname) {
      const fetchAccountOptions = fieldname === 'domainid' && this.fields.some((field) => field.name === 'account')
      if (fetchAccountOptions) {
        this.fetchDynamicFieldData('account')
      }
    },
    onVisibleForm () {
      this.visibleFilter = !this.visibleFilter
      if (!this.visibleFilter) return
      this.initFormFieldData()
    },
    retrieveFieldLabel (fieldName) {
      if (fieldName === 'groupid') {
        fieldName = 'group'
      }
      if (fieldName === 'keyword') {
        if ('listAnnotations' in this.$store.getters.apis) {
          return this.$t('label.annotation')
        } else {
          return this.$t('label.name')
        }
      }
      return this.$t('label.' + fieldName)
    },
    initFields () {
      const arrayField = []
      this.fields = []
      this.searchFilters.forEach(item => {
        let type = 'input'

        if (item === 'domainid' && !('listDomains' in this.$store.getters.apis)) {
          return true
        }
        if (item === 'account' && !('listAccounts' in this.$store.getters.apis)) {
          return true
        }
        if (item === 'account' && !('addAccountToProject' in this.$store.getters.apis || 'createAccount' in this.$store.getters.apis)) {
          return true
        }
        if (item === 'podid' && !('listPods' in this.$store.getters.apis)) {
          return true
        }
        if (item === 'clusterid' && !('listClusters' in this.$store.getters.apis)) {
          return true
        }
        if (item === 'groupid' && !('listInstanceGroups' in this.$store.getters.apis)) {
          return true
        }
        if (item === 'associatednetworkid' && this.$route.meta.name === 'asnumbers') {
          item = 'networkid'
        }
        if (item === 'usagetype' && !('listUsageTypes' in this.$store.getters.apis)) {
          return true
        }
        if (item === 'isencrypted' && !('listVolumes' in this.$store.getters.apis)) {
          return true
        }
        if (item === 'displaynetwork' && this.$store.getters.userInfo.roletype !== 'Admin') {
          return true
        }
        if (['zoneid', 'domainid', 'imagestoreid', 'storageid', 'state', 'account', 'hypervisor', 'level',
          'clusterid', 'podid', 'groupid', 'entitytype', 'accounttype', 'systemvmtype', 'scope', 'provider',
          'type', 'scope', 'managementserverid', 'serviceofferingid',
          'diskofferingid', 'networkid', 'usagetype', 'restartrequired',
          'displaynetwork', 'arch'].includes(item)
        ) {
          type = 'list'
        } else if (item === 'tags') {
          type = 'tag'
        } else if (['resourcetype', 'apikeyaccess'].includes(item)) {
          type = 'autocomplete'
        } else if (item === 'isencrypted') {
          type = 'boolean'
        }

        this.fields.push({
          type: type,
          name: item,
          opts: [],
          loading: false
        })
        arrayField.push(item)
      })
      return arrayField
    },
    fetchStaticFieldData (arrayField) {
      if (arrayField.includes('displaynetwork')) {
        const typeIndex = this.fields.findIndex(item => item.name === 'displaynetwork')
        this.fields[typeIndex].loading = true
        this.fields[typeIndex].opts = this.fetchBoolean()
        this.fields[typeIndex].loading = false
      }
      if (arrayField.includes('type')) {
        if (this.$route.path === '/guestnetwork' || this.$route.path.includes('/guestnetwork/')) {
          const typeIndex = this.fields.findIndex(item => item.name === 'type')
          this.fields[typeIndex].loading = true
          this.fields[typeIndex].opts = this.fetchGuestNetworkTypes()
          this.fields[typeIndex].loading = false
        } else if (this.$route.path === '/role' || this.$route.path.includes('/role/')) {
          const typeIndex = this.fields.findIndex(item => item.name === 'type')
          this.fields[typeIndex].loading = true
          this.fields[typeIndex].opts = this.fetchRoleTypes()
          this.fields[typeIndex].loading = false
        }
      }

      if (arrayField.includes('scope')) {
        const scopeIndex = this.fields.findIndex(item => item.name === 'scope')
        this.fields[scopeIndex].loading = true
        this.fields[scopeIndex].opts = this.fetchScope()
        this.fields[scopeIndex].loading = false
      }

      if (arrayField.includes('state')) {
        const stateIndex = this.fields.findIndex(item => item.name === 'state')
        this.fields[stateIndex].loading = true
        this.fields[stateIndex].opts = this.fetchState()
        this.fields[stateIndex].loading = false
      }

      if (arrayField.includes('level')) {
        const levelIndex = this.fields.findIndex(item => item.name === 'level')
        this.fields[levelIndex].loading = true
        this.fields[levelIndex].opts = this.fetchLevel()
        this.fields[levelIndex].loading = false
      }

      if (arrayField.includes('entitytype')) {
        const entityTypeIndex = this.fields.findIndex(item => item.name === 'entitytype')
        this.fields[entityTypeIndex].loading = true
        this.fields[entityTypeIndex].opts = this.fetchEntityType()
        this.fields[entityTypeIndex].loading = false
      }

      if (arrayField.includes('accounttype')) {
        const accountTypeIndex = this.fields.findIndex(item => item.name === 'accounttype')
        this.fields[accountTypeIndex].loading = true
        this.fields[accountTypeIndex].opts = this.fetchAccountTypes()
        this.fields[accountTypeIndex].loading = false
      }

      if (arrayField.includes('systemvmtype')) {
        const systemVmTypeIndex = this.fields.findIndex(item => item.name === 'systemvmtype')
        this.fields[systemVmTypeIndex].loading = true
        this.fields[systemVmTypeIndex].opts = this.fetchSystemVmTypes()
        this.fields[systemVmTypeIndex].loading = false
      }

      if (arrayField.includes('scope')) {
        const scopeIndex = this.fields.findIndex(item => item.name === 'scope')
        this.fields[scopeIndex].loading = true
        this.fields[scopeIndex].opts = this.fetchStoragePoolScope()
        this.fields[scopeIndex].loading = false
      }

      if (arrayField.includes('provider')) {
        const providerIndex = this.fields.findIndex(item => item.name === 'provider')
        this.fields[providerIndex].loading = true
        this.fields[providerIndex].opts = this.fetchImageStoreProviders()
        this.fields[providerIndex].loading = false
      }

      if (arrayField.includes('restartrequired')) {
        const restartRequiredIndex = this.fields.findIndex(item => item.name === 'restartrequired')
        this.fields[restartRequiredIndex].loading = true
        this.fields[restartRequiredIndex].opts = [
          { id: 'true', name: 'label.yes' },
          { id: 'false', name: 'label.no' }
        ]
        this.fields[restartRequiredIndex].loading = false
      }

      if (arrayField.includes('resourcetype')) {
        const resourceTypeIndex = this.fields.findIndex(item => item.name === 'resourcetype')
        this.fields[resourceTypeIndex].loading = true
        this.fields[resourceTypeIndex].opts = [
          { value: 'Account' },
          { value: 'Domain' },
          { value: 'Iso' },
          { value: 'Network' },
          { value: 'Template' },
          { value: 'User' },
          { value: 'VirtualMachine' },
          { value: 'Volume' },
          { value: 'QuotaTariff' }
        ]
        this.fields[resourceTypeIndex].loading = false
      }

      if (arrayField.includes('apikeyaccess')) {
        const apiKeyAccessIndex = this.fields.findIndex(item => item.name === 'apikeyaccess')
        this.fields[apiKeyAccessIndex].loading = true
        this.fields[apiKeyAccessIndex].opts = [
          { value: 'Disabled' },
          { value: 'Enabled' },
          { value: 'Inherit' }
        ]
        this.fields[apiKeyAccessIndex].loading = false
      }

      if (arrayField.includes('arch')) {
        const typeIndex = this.fields.findIndex(item => item.name === 'arch')
        this.fields[typeIndex].loading = true
        this.fields[typeIndex].opts = this.$fetchCpuArchitectureTypes()
        this.fields[typeIndex].loading = false
      }
    },
    async fetchDynamicFieldData (arrayField, searchKeyword) {
      const promises = []
      let typeIndex = -1
      let zoneIndex = -1
      let domainIndex = -1
      let accountIndex = -1
      let hypervisorIndex = -1
      let imageStoreIndex = -1
      let storageIndex = -1
      let podIndex = -1
      let clusterIndex = -1
      let groupIndex = -1
      let managementServerIdIndex = -1
      let serviceOfferingIndex = -1
      let diskOfferingIndex = -1
      let networkIndex = -1
      let usageTypeIndex = -1
      let volumeIndex = -1

      if (arrayField.includes('type')) {
        if (this.$route.path === '/alert') {
          typeIndex = this.fields.findIndex(item => item.name === 'type')
          this.fields[typeIndex].loading = true
          promises.push(await this.fetchAlertTypes())
        } else if (this.$route.path === '/affinitygroup') {
          typeIndex = this.fields.findIndex(item => item.name === 'type')
          this.fields[typeIndex].loading = true
          promises.push(await this.fetchAffinityGroupTypes())
        }
      }

      if (arrayField.includes('zoneid')) {
        zoneIndex = this.fields.findIndex(item => item.name === 'zoneid')
        this.fields[zoneIndex].loading = true
        promises.push(await this.fetchZones(searchKeyword))
      }

      if (arrayField.includes('domainid')) {
        domainIndex = this.fields.findIndex(item => item.name === 'domainid')
        this.fields[domainIndex].loading = true
        promises.push(await this.fetchDomains(searchKeyword))
      }

      if (arrayField.includes('account')) {
        accountIndex = this.fields.findIndex(item => item.name === 'account')
        this.fields[accountIndex].loading = true
        promises.push(await this.fetchAccounts(searchKeyword))
      }

      if (arrayField.includes('hypervisor')) {
        hypervisorIndex = this.fields.findIndex(item => item.name === 'hypervisor')
        this.fields[hypervisorIndex].loading = true
        promises.push(await this.fetchHypervisors())
      }

      if (arrayField.includes('imagestoreid')) {
        imageStoreIndex = this.fields.findIndex(item => item.name === 'imagestoreid')
        this.fields[imageStoreIndex].loading = true
        promises.push(await this.fetchImageStores(searchKeyword))
      }

      if (arrayField.includes('storageid')) {
        storageIndex = this.fields.findIndex(item => item.name === 'storageid')
        this.fields[storageIndex].loading = true
        promises.push(await this.fetchStoragePools(searchKeyword))
      }

      if (arrayField.includes('podid')) {
        podIndex = this.fields.findIndex(item => item.name === 'podid')
        this.fields[podIndex].loading = true
        promises.push(await this.fetchPods(searchKeyword))
      }

      if (arrayField.includes('clusterid')) {
        clusterIndex = this.fields.findIndex(item => item.name === 'clusterid')
        this.fields[clusterIndex].loading = true
        promises.push(await this.fetchClusters(searchKeyword))
      }

      if (arrayField.includes('groupid')) {
        groupIndex = this.fields.findIndex(item => item.name === 'groupid')
        this.fields[groupIndex].loading = true
        promises.push(await this.fetchInstanceGroups(searchKeyword))
      }

      if (arrayField.includes('managementserverid')) {
        managementServerIdIndex = this.fields.findIndex(item => item.name === 'managementserverid')
        this.fields[managementServerIdIndex].loading = true
        promises.push(await this.fetchManagementServers(searchKeyword))
      }

      if (arrayField.includes('serviceofferingid')) {
        serviceOfferingIndex = this.fields.findIndex(item => item.name === 'serviceofferingid')
        this.fields[serviceOfferingIndex].loading = true
        promises.push(await this.fetchServiceOfferings(searchKeyword))
      }

      if (arrayField.includes('diskofferingid')) {
        diskOfferingIndex = this.fields.findIndex(item => item.name === 'diskofferingid')
        this.fields[diskOfferingIndex].loading = true
        promises.push(await this.fetchDiskOfferings(searchKeyword))
      }

      if (arrayField.includes('networkid')) {
        networkIndex = this.fields.findIndex(item => item.name === 'networkid')
        this.fields[networkIndex].loading = true
        promises.push(await this.fetchNetworks(searchKeyword))
      }

      if (arrayField.includes('usagetype')) {
        usageTypeIndex = this.fields.findIndex(item => item.name === 'usagetype')
        this.fields[usageTypeIndex].loading = true
        promises.push(await this.fetchUsageTypes())
      }

      if (arrayField.includes('isencrypted')) {
        volumeIndex = this.fields.findIndex(item => item.name === 'isencrypted')
        this.fields[volumeIndex].loading = true
        promises.push(await this.fetchVolumes(searchKeyword))
      }

      Promise.all(promises).then(response => {
        if (typeIndex > -1) {
          const types = response.filter(item => item.type === 'type')
          if (types && types.length > 0) {
            this.fields[typeIndex].opts = this.sortArray(types[0].data)
          }
        }
        if (zoneIndex > -1) {
          const zones = response.filter(item => item.type === 'zoneid')
          if (zones && zones.length > 0) {
            this.fields[zoneIndex].opts = this.sortArray(zones[0].data)
          }
        }
        if (domainIndex > -1) {
          const domain = response.filter(item => item.type === 'domainid')
          if (domain && domain.length > 0) {
            this.fields[domainIndex].opts = this.sortArray(domain[0].data, 'path')
          }
        }
        if (accountIndex > -1) {
          const account = response.filter(item => item.type === 'account')
          if (account && account.length > 0) {
            this.fields[accountIndex].opts = this.sortArray(account[0].data, 'name')
          }
        }
        if (hypervisorIndex > -1) {
          const hypervisor = response.filter(item => item.type === 'hypervisor')
          if (hypervisor && hypervisor.length > 0) {
            this.fields[hypervisorIndex].opts = this.sortArray(hypervisor[0].data, 'name')
          }
        }
        if (imageStoreIndex > -1) {
          const imageStore = response.filter(item => item.type === 'imagestoreid')
          if (imageStore && imageStore.length > 0) {
            this.fields[imageStoreIndex].opts = this.sortArray(imageStore[0].data, 'name')
          }
        }
        if (storageIndex > -1) {
          const storagePool = response.filter(item => item.type === 'storageid')
          if (storagePool && storagePool.length > 0) {
            this.fields[storageIndex].opts = this.sortArray(storagePool[0].data, 'name')
          }
        }
        if (podIndex > -1) {
          const pod = response.filter(item => item.type === 'podid')
          if (pod && pod.length > 0) {
            this.fields[podIndex].opts = this.sortArray(pod[0].data)
          }
        }
        if (clusterIndex > -1) {
          const cluster = response.filter(item => item.type === 'clusterid')
          if (cluster && cluster.length > 0) {
            this.fields[clusterIndex].opts = this.sortArray(cluster[0].data)
          }
        }
        if (groupIndex > -1) {
          const groups = response.filter(item => item.type === 'groupid')
          if (groups && groups.length > 0) {
            this.fields[groupIndex].opts = this.sortArray(groups[0].data)
          }
        }

        if (managementServerIdIndex > -1) {
          const managementServers = response.filter(item => item.type === 'managementserverid')
          if (managementServers && managementServers.length > 0) {
            this.fields[managementServerIdIndex].opts = this.sortArray(managementServers[0].data)
          }
        }

        if (serviceOfferingIndex > -1) {
          const serviceOfferings = response.filter(item => item.type === 'serviceofferingid')
          if (serviceOfferings && serviceOfferings.length > 0) {
            this.fields[serviceOfferingIndex].opts = this.sortArray(serviceOfferings[0].data)
          }
        }

        if (diskOfferingIndex > -1) {
          const diskOfferings = response.filter(item => item.type === 'diskofferingid')
          if (diskOfferings && diskOfferings.length > 0) {
            this.fields[diskOfferingIndex].opts = this.sortArray(diskOfferings[0].data)
          }
        }

        if (networkIndex > -1) {
          const networks = response.filter(item => item.type === 'networkid')
          if (networks && networks.length > 0) {
            this.fields[networkIndex].opts = this.sortArray(networks[0].data)
          }
        }

        if (usageTypeIndex > -1) {
          const usageTypes = response.filter(item => item.type === 'usagetype')
          if (usageTypes?.length > 0) {
            this.fields[usageTypeIndex].opts = this.sortArray(usageTypes[0].data)
          }
        }
      }).finally(() => {
        if (typeIndex > -1) {
          this.fields[typeIndex].loading = false
        }
        if (zoneIndex > -1) {
          this.fields[zoneIndex].loading = false
        }
        if (domainIndex > -1) {
          this.fields[domainIndex].loading = false
        }
        if (accountIndex > -1) {
          this.fields[accountIndex].loading = false
        }
        if (hypervisorIndex > -1) {
          this.fields[hypervisorIndex].loading = false
        }
        if (imageStoreIndex > -1) {
          this.fields[imageStoreIndex].loading = false
        }
        if (storageIndex > -1) {
          this.fields[storageIndex].loading = false
        }
        if (podIndex > -1) {
          this.fields[podIndex].loading = false
        }
        if (clusterIndex > -1) {
          this.fields[clusterIndex].loading = false
        }
        if (groupIndex > -1) {
          this.fields[groupIndex].loading = false
        }
        if (managementServerIdIndex > -1) {
          this.fields[managementServerIdIndex].loading = false
        }
        if (serviceOfferingIndex > -1) {
          this.fields[serviceOfferingIndex].loading = false
        }
        if (diskOfferingIndex > -1) {
          this.fields[diskOfferingIndex].loading = false
        }
        if (networkIndex > -1) {
          this.fields[networkIndex].loading = false
        }
        if (usageTypeIndex > -1) {
          this.fields[usageTypeIndex].loading = false
        }
        if (Array.isArray(arrayField)) {
          this.fillFormFieldValues()
        }
      })
    },
    initFormFieldData () {
      const arrayField = this.initFields()

      this.fetchStaticFieldData(arrayField)

      this.fetchDynamicFieldData(arrayField)
    },
    sortArray (data, key = 'name') {
      if (!data) {
        return []
      }
      return data.sort(function (a, b) {
        if (a[key] < b[key]) { return -1 }
        if (a[key] > b[key]) { return 1 }

        return 0
      })
    },
    fillFormFieldValues () {
      this.fieldValues = {}
      if (Object.keys(this.$route.query).length > 0) {
        this.fieldValues = this.$route.query
      }
      if (this.$route.meta.params) {
        Object.assign(this.fieldValues, this.$route.meta.params)
      }
      this.fields.forEach(field => {
        this.form[field.name] = this.fieldValues[field.name]
      })
      this.inputKey = this.fieldValues['tags[0].key'] || null
      this.inputValue = this.fieldValues['tags[0].value'] || null
    },
    fetchZones (searchKeyword) {
      return new Promise((resolve, reject) => {
        api('listZones', { showicon: true, keyword: searchKeyword }).then(json => {
          const zones = json.listzonesresponse.zone
          resolve({
            type: 'zoneid',
            data: zones
          })
        }).catch(error => {
          reject(error.response.headers['x-description'])
        })
      })
    },
    fetchDomains (searchKeyword) {
      return new Promise((resolve, reject) => {
        api('listDomains', { listAll: true, details: 'min', showicon: true, keyword: searchKeyword }).then(json => {
          const domain = json.listdomainsresponse.domain
          resolve({
            type: 'domainid',
            data: domain
          })
        }).catch(error => {
          reject(error.response.headers['x-description'])
        })
      })
    },
    fetchAccounts (searchKeyword) {
      return new Promise((resolve, reject) => {
        const params = { listAll: true, isrecursive: false, showicon: true, keyword: searchKeyword }
        if (this.form.domainid) {
          params.domainid = this.form.domainid
        }
        api('listAccounts', params).then(json => {
          let account = json?.listaccountsresponse?.account || []
          if (this.form.domainid) {
            account = account.filter(a => a.domainid === this.form.domainid)
          }
          resolve({
            type: 'account',
            data: account
          })
        }).catch(error => {
          reject(error.response.headers['x-description'])
        })
      })
    },
    fetchHypervisors () {
      return new Promise((resolve, reject) => {
        api('listHypervisors').then(json => {
          const hypervisor = json.listhypervisorsresponse.hypervisor.map(a => { return { id: a.name, name: a.name } })
          resolve({
            type: 'hypervisor',
            data: hypervisor
          })
        }).catch(error => {
          reject(error.response.headers['x-description'])
        })
      })
    },
    fetchImageStores (searchKeyword) {
      return new Promise((resolve, reject) => {
        api('listImageStores', { listAll: true, showicon: true, keyword: searchKeyword }).then(json => {
          const imageStore = json.listimagestoresresponse.imagestore
          resolve({
            type: 'imagestoreid',
            data: imageStore
          })
        }).catch(error => {
          reject(error.response.headers['x-description'])
        })
      })
    },
    fetchStoragePools (searchKeyword) {
      return new Promise((resolve, reject) => {
        api('listStoragePools', { listAll: true, showicon: true, keyword: searchKeyword }).then(json => {
          const storagePool = json.liststoragepoolsresponse.storagepool
          resolve({
            type: 'storageid',
            data: storagePool
          })
        }).catch(error => {
          reject(error.response.headers['x-description'])
        })
      })
    },
    fetchPods (searchKeyword) {
      return new Promise((resolve, reject) => {
        api('listPods', { keyword: searchKeyword }).then(json => {
          const pods = json.listpodsresponse.pod
          resolve({
            type: 'podid',
            data: pods
          })
        }).catch(error => {
          reject(error.response.headers['x-description'])
        })
      })
    },
    fetchClusters (searchKeyword) {
      return new Promise((resolve, reject) => {
        api('listClusters', { keyword: searchKeyword }).then(json => {
          const clusters = json.listclustersresponse.cluster
          resolve({
            type: 'clusterid',
            data: clusters
          })
        }).catch(error => {
          reject(error.response.headers['x-description'])
        })
      })
    },
    fetchInstanceGroups (searchKeyword) {
      return new Promise((resolve, reject) => {
        api('listInstanceGroups', { listAll: true, keyword: searchKeyword }).then(json => {
          const instancegroups = json.listinstancegroupsresponse.instancegroup
          resolve({
            type: 'groupid',
            data: instancegroups
          })
        }).catch(error => {
          reject(error.response.headers['x-description'])
        })
      })
    },
    fetchServiceOfferings (searchKeyword) {
      return new Promise((resolve, reject) => {
        api('listServiceOfferings', { listAll: true, keyword: searchKeyword }).then(json => {
          const serviceOfferings = json.listserviceofferingsresponse.serviceoffering
          resolve({
            type: 'serviceofferingid',
            data: serviceOfferings
          })
        }).catch(error => {
          reject(error.response.headers['x-description'])
        })
      })
    },
    fetchDiskOfferings (searchKeyword) {
      return new Promise((resolve, reject) => {
        api('listDiskOfferings', { listAll: true, keyword: searchKeyword }).then(json => {
          const diskOfferings = json.listdiskofferingsresponse.diskoffering
          resolve({
            type: 'diskofferingid',
            data: diskOfferings
          })
        }).catch(error => {
          reject(error.response.headers['x-description'])
        })
      })
    },
    fetchNetworks (searchKeyword) {
      return new Promise((resolve, reject) => {
        api('listNetworks', { listAll: true, keyword: searchKeyword }).then(json => {
          const networks = json.listnetworksresponse.network
          resolve({
            type: 'networkid',
            data: networks
          })
        }).catch(error => {
          reject(error.response.headers['x-description'])
        })
      })
    },
    fetchAlertTypes () {
      if (this.alertTypes.length > 0) {
        return new Promise((resolve, reject) => {
          resolve({
            type: 'type',
            data: this.alertTypes
          })
        })
      } else {
        return new Promise((resolve, reject) => {
          api('listAlertTypes').then(json => {
            const alerttypes = json.listalerttypesresponse.alerttype.map(a => { return { id: a.alerttypeid, name: a.name } })
            this.alertTypes = alerttypes
            resolve({
              type: 'type',
              data: alerttypes
            })
          }).catch(error => {
            reject(error.response.headers['x-description'])
          })
        })
      }
    },
    fetchAffinityGroupTypes () {
      if (this.alertTypes.length > 0) {
        return new Promise((resolve, reject) => {
          resolve({
            type: 'type',
            data: this.alertTypes
          })
        })
      } else {
        return new Promise((resolve, reject) => {
          api('listAffinityGroupTypes').then(json => {
            const alerttypes = json.listaffinitygrouptypesresponse.affinityGroupType.map(a => {
              let name = a.type
              if (a.type === 'host anti-affinity') {
                name = 'host anti-affinity (Strict)'
              } else if (a.type === 'host affinity') {
                name = 'host affinity (Strict)'
              } else if (a.type === 'non-strict host anti-affinity') {
                name = 'host anti-affinity (Non-Strict)'
              } else if (a.type === 'non-strict host affinity') {
                name = 'host affinity (Non-Strict)'
              }
              return { id: a.type, name: name }
            })
            this.alertTypes = alerttypes
            resolve({
              type: 'type',
              data: alerttypes
            })
          }).catch(error => {
            reject(error.response.headers['x-description'])
          })
        })
      }
    },
    fetchVolumes (searchKeyword) {
      return new Promise((resolve, reject) => {
        api('listVolumes', { listAll: true, isencrypted: searchKeyword }).then(json => {
          const volumes = json.listvolumesresponse.volume
          resolve({
            type: 'isencrypted',
            data: volumes
          })
        }).catch(error => {
          reject(error.response.headers['x-description'])
        })
      })
    },
    fetchManagementServers (searchKeyword) {
      return new Promise((resolve, reject) => {
        api('listManagementServers', { listAll: true, keyword: searchKeyword }).then(json => {
          const managementservers = json.listmanagementserversresponse.managementserver
          resolve({
            type: 'managementserverid',
            data: managementservers
          })
        }).catch(error => {
          reject(error.response.headers['x-description'])
        })
      })
    },
    fetchGuestNetworkTypes () {
      const types = []
      if (this.apiName.indexOf('listNetworks') > -1) {
        types.push({
          id: 'Isolated',
          name: 'label.isolated'
        })
        types.push({
          id: 'Shared',
          name: 'label.shared'
        })
        types.push({
          id: 'L2',
          name: 'label.l2'
        })
      }
      return types
    },
    fetchBoolean () {
      const types = []
      types.push({
        id: 'true',
        name: 'label.true'
      })
      types.push({
        id: 'false',
        name: 'label.false'
      })
      return types
    },
    fetchAccountTypes () {
      const types = []
      if (this.apiName.indexOf('listAccounts') > -1) {
        types.push({
          id: '1',
          name: 'Admin'
        })
        types.push({
          id: '2',
          name: 'DomainAdmin'
        })
        types.push({
          id: '3',
          name: 'User'
        })
      }
      return types
    },
    fetchSystemVmTypes () {
      const types = []
      if (this.apiName.indexOf('listSystemVms') > -1) {
        types.push({
          id: 'consoleproxy',
          name: 'label.console.proxy.vm'
        })
        types.push({
          id: 'secondarystoragevm',
          name: 'label.secondary.storage.vm'
        })
      }
      return types
    },
    fetchStoragePoolScope () {
      const types = []
      if (this.apiName.indexOf('listStoragePools') > -1) {
        types.push({
          id: 'HOST',
          name: 'label.hostname'
        })
        types.push({
          id: 'CLUSTER',
          name: 'label.cluster'
        })
        types.push({
          id: 'ZONE',
          name: 'label.zone'
        })
        types.push({
          id: 'REGION',
          name: 'label.region'
        })
        types.push({
          id: 'GLOBAL',
          name: 'label.global'
        })
      }
      return types
    },
    fetchImageStoreProviders () {
      const types = []
      if (this.apiName.indexOf('listImageStores') > -1) {
        types.push({
          id: 'NFS',
          name: 'NFS'
        })
        types.push({
          id: 'SMB/CIFS',
          name: 'SMB/CIFS'
        })
        types.push({
          id: 'S3',
          name: 'S3'
        })
        types.push({
          id: 'Swift',
          name: 'Swift'
        })
      }
      return types
    },
    fetchRoleTypes () {
      const types = []
      if (this.apiName.indexOf('listRoles') > -1) {
        types.push({
          id: 'Admin',
          name: 'Admin'
        })
        types.push({
          id: 'ResourceAdmin',
          name: 'ResourceAdmin'
        })
        types.push({
          id: 'DomainAdmin',
          name: 'DomainAdmin'
        })
        types.push({
          id: 'User',
          name: 'User'
        })
      }
      return types
    },
    fetchScope () {
      const scope = []
      if (this.apiName.indexOf('listWebhooks') > -1) {
        scope.push({
          id: 'Local',
          name: 'label.local'
        })
        scope.push({
          id: 'Domain',
          name: 'label.domain'
        })
        if (isAdmin()) {
          scope.push({
            id: 'Global',
            name: 'label.global'
          })
        }
      }
      return scope
    },
    fetchState () {
      var state = []
      if (this.apiName.includes('listVolumes')) {
        state = [
          {
            id: 'Allocated',
            name: 'label.allocated'
          },
          {
            id: 'Ready',
            name: 'label.isready'
          },
          {
            id: 'Destroy',
            name: 'label.destroy'
          },
          {
            id: 'Expunging',
            name: 'label.expunging'
          },
          {
            id: 'Expunged',
            name: 'label.expunged'
          },
          {
            id: 'Migrating',
            name: 'label.migrating'
          }
        ]
      } else if (this.apiName.includes('listKubernetesClusters')) {
        state = [
          {
            id: 'Created',
            name: 'label.created'
          },
          {
            id: 'Starting',
            name: 'label.starting'
          },
          {
            id: 'Running',
            name: 'label.running'
          },
          {
            id: 'Stopping',
            name: 'label.stopping'
          },
          {
            id: 'Stopped',
            name: 'label.stopped'
          },
          {
            id: 'Scaling',
            name: 'label.scaling'
          },
          {
            id: 'Upgrading',
            name: 'label.upgrading'
          },
          {
            id: 'Alert',
            name: 'label.alert'
          },
          {
            id: 'Recovering',
            name: 'label.recovering'
          },
          {
            id: 'Destroyed',
            name: 'label.destroyed'
          },
          {
            id: 'Destroying',
            name: 'label.destroying'
          },
          {
            id: 'Error',
            name: 'label.error'
          }
        ]
      } else if (this.apiName.indexOf('listWebhooks') > -1) {
        state = [
          {
            id: 'Enabled',
            name: 'label.enabled'
          },
          {
            id: 'Disabled',
            name: 'label.disabled'
          }
        ]
      }
      return state
    },
    fetchEntityType () {
      const entityType = []
      if (this.apiName.indexOf('listAnnotations') > -1) {
        const allowedTypes = {
          VM: 'Virtual Machine',
          HOST: 'Host',
          VOLUME: 'Volume',
          SNAPSHOT: 'Snapshot',
          VM_SNAPSHOT: 'VM Snapshot',
          INSTANCE_GROUP: 'Instance Group',
          NETWORK: 'Network',
          VPC: 'VPC',
          PUBLIC_IP_ADDRESS: 'Public IP Address',
          VPN_CUSTOMER_GATEWAY: 'VPC Customer Gateway',
          TEMPLATE: 'Template',
          ISO: 'ISO',
          SSH_KEYPAIR: 'SSH Key Pair',
          DOMAIN: 'Domain',
          SERVICE_OFFERING: 'Service Offfering',
          DISK_OFFERING: 'Disk Offering',
          NETWORK_OFFERING: 'Network Offering',
          POD: 'Pod',
          ZONE: 'Zone',
          CLUSTER: 'Cluster',
          PRIMARY_STORAGE: 'Primary Storage',
          SECONDARY_STORAGE: 'Secondary Storage',
          VR: 'Virtual Router',
          SYSTEM_VM: 'System VM',
          KUBERNETES_CLUSTER: 'Kubernetes Cluster'
        }
        for (var key in allowedTypes) {
          entityType.push({
            id: key,
            name: allowedTypes[key]
          })
        }
      }
      return entityType
    },
    fetchLevel () {
      const levels = []
      levels.push({
        id: 'INFO',
        name: 'label.info.upper'
      })
      levels.push({
        id: 'WARN',
        name: 'label.warn.upper'
      })
      levels.push({
        id: 'ERROR',
        name: 'label.error.upper'
      })
      return levels
    },
    fetchUsageTypes () {
      return new Promise((resolve, reject) => {
        api('listUsageTypes')
          .then(json => {
            const usageTypes = json.listusagetypesresponse.usagetype.map(entry => {
              return {
                id: entry.id,
                name: i18n.global.t(entry.name)
              }
            })

            resolve({
              type: 'usagetype',
              data: usageTypes
            })
          })
          .catch(error => {
            reject(error.response.headers['x-description'])
          })
      })
    },
    onSearch (value) {
      this.paramsFilter = {}
      this.searchQuery = value
      this.$emit('search', { searchQuery: this.searchQuery })
    },
    async onClear () {
      this.formRef.value.resetFields()
      this.form = reactive({})
      this.isFiltered = false
      this.inputKey = null
      this.inputValue = null
      this.searchQuery = null
      this.paramsFilter = {}

      const refreshAccountOptions = ['account', 'domainid'].every((field) => {
        return this.fields.some((searchViewField) => searchViewField.name === field)
      })
      if (refreshAccountOptions) {
        await this.fetchDynamicFieldData('account')
      }

      this.$emit('search', this.paramsFilter)
    },
    handleSubmit () {
      this.paramsFilter = {}
      this.formRef.value.validate().then(() => {
        const values = toRaw(this.form)
        this.isFiltered = true
        for (const key in values) {
          const input = values[key]
          if (input === '' || input === null || input === undefined) {
            continue
          }
          this.paramsFilter[key] = input
        }
        if (this.searchFilters.includes('tags')) {
          if (this.inputKey) {
            this.paramsFilter['tags[0].key'] = this.inputKey
            this.paramsFilter['tags[0].value'] = this.inputValue
          }
        }
        this.$emit('search', this.paramsFilter)
      })
    },
    changeFilter (filter) {
      this.$emit('change-filter', filter)
    },
    updateIsFiltered () {
      this.isFiltered = this.searchFilters.some(item => {
        if (this.searchParams[item]) {
          return true
        }
      })
    }
  }
}
</script>

<style scoped lang="less">
.input-search {
  margin-left: 10px;
}

.filter-group {
  :deep(.ant-input-group-addon) {
    padding: 0 5px;
  }

  &-button {
    background: inherit;
    border: 0;
    padding: 0;
  }

  &-button {
    position: relative;
    display: block;
    min-height: 25px;

    &-clear {
      position: absolute;
      left: 0;
    }

    &-search {
      position: absolute;
      right: 0;
    }
  }
}

.filter-button {
  background: inherit;
  border: 0;
  padding: 0;
  position: relative;
  display: block;
  min-height: 25px;
  width: 20px;
}
</style>
