// 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>
  <a-list>
    <a-list-item>
      <span v-if="configrecord.type ==='Boolean'">
        <a-tooltip :title="editableValue?'true':'false'">
          <a-switch
            :disabled="(!('updateConfiguration' in $store.getters.apis) || configDisabled)"
            v-model:checked="editableValue"
            @keydown.esc="editableValueKey = null"
            @pressEnter="updateConfigurationValue(configrecord)"
            @change="value => setConfigurationEditable(configrecord, value)"
          />
         </a-tooltip>
      </span>
      <span v-else-if="configrecord.type ==='Number'">
        <a-tooltip :title="editableValue">
          <a-input-number
            style="width: 20vw;"
            :defaultValue="actualValue"
            :disabled="(!('updateConfiguration' in $store.getters.apis) || configDisabled)"
            v-model:value="editableValue"
            @keydown.esc="editableValueKey = null"
            @pressEnter="updateConfigurationValue(configrecord)"
            @change="value => setConfigurationEditable(configrecord, value)"
            @keydown="e => handleInputNumberKeyDown(e, false)"
          />
        </a-tooltip>
      </span>
      <span v-else-if="configrecord.type ==='Decimal'">
        <a-tooltip :title="editableValue">
          <a-input-number
            style="width: 20vw"
            :defaultValue="actualValue"
            :disabled="(!('updateConfiguration' in $store.getters.apis) || configDisabled)"
            v-model:value="editableValue"
            @keydown.esc="editableValueKey = null"
            @pressEnter="updateConfigurationValue(configrecord)"
            @change="value => setConfigurationEditable(configrecord, value)"
            @keydown="e => handleInputNumberKeyDown(e, true)"
          />
        </a-tooltip>
      </span>
      <span v-else-if="configrecord.type ==='Range'" style="width: 75%;">
        <a-row type="flex">
          <a-col flex="auto">
            <a-tooltip :title="editableValue">
              <a-slider
                style="width: 13vw"
                class="config-slider-value"
                :defaultValue="configrecord.value * 100"
                :min="0"
                :max="100"
                :disabled="(!('updateConfiguration' in $store.getters.apis) || configDisabled)"
                v-model:value="editableValue"
                @keydown.esc="editableValueKey = null"
                @pressEnter="updateConfigurationValue(configrecord)"
                @change="value => setConfigurationEditable(configrecord, value)"
              />
            </a-tooltip>
          </a-col>
          <a-col flex="30px">
            <a-tooltip :title="editableValue">
              <a-input-number
                style="margin-left: 10px;"
                class="config-slider-text"
                :defaultValue="configrecord.value * 100"
                :min="0"
                :max="100"
                :disabled="(!('updateConfiguration' in $store.getters.apis) || configDisabled)"
                :formatter="(value) => `${value}%`"
                v-model:value="editableValue"
                @keydown.esc="editableValueKey = null"
                @pressEnter="updateConfigurationValue(configrecord)"
                @change="value => setConfigurationEditable(configrecord, value)"
                @keydown="e => handleInputNumberKeyDown(e, true)"
              />
            </a-tooltip>
          </a-col>
        </a-row>
      </span>
      <span v-else-if="configrecord.type === 'Select'">
        <a-tooltip :title="editableValue">
          <a-select
            style="width: 20vw"
            :defaultValue="actualValue"
            :disabled="(!('updateConfiguration' in $store.getters.apis) || configDisabled)"
            v-model:value="editableValue"
            @keydown.esc="editableValueKey = null"
            @pressEnter="updateConfigurationValue(configrecord)"
            @change="value => setConfigurationEditable(configrecord, value)">
            <a-select-option
              v-for="value of configrecord.options.split(',')"
              :key="value">
              {{ value }}
            </a-select-option>
          </a-select>
        </a-tooltip>
      </span>
      <span v-else-if="configrecord.type === 'Order' || configrecord.type === 'WhitespaceSeparatedListWithOptions'">
        <a-tooltip :title="editableValue.join(', ')">
          <b v-if="configrecord.type === 'Order'">
            {{ $t('message.select.deselect.to.sort') }}
          </b>
          <b v-else>
            {{ $t('message.select.deselect.desired.options') }}
          </b>
          <br />
          <a-select
            style="width: 20vw"
            mode="multiple"
            :defaultValue="actualValue"
            :disabled="(!('updateConfiguration' in $store.getters.apis) || configDisabled)"
            v-model:value="editableValue"
            @keydown.esc="editableValueKey = null"
            @pressEnter="updateConfigurationValue(configrecord)"
            @change="value => setConfigurationEditable(configrecord, value)">
            <a-select-option
              v-for="value of configrecord.options.split(',')"
              :key="value">
              {{ value }}
            </a-select-option>
          </a-select>
        </a-tooltip>
      </span>
      <span v-else-if="configrecord.type === 'CSV'">
        <a-tooltip :title="editableValue.join(', ')">
          <b>{{ $t('message.type.values.to.add') }}</b>
          <br />
          <a-select
            style="width: 20vw"
            mode="tags"
            :disabled="(!('updateConfiguration' in $store.getters.apis) || configDisabled)"
            v-model:value="editableValue"
            @keydown.esc="editableValueKey = null"
            @pressEnter="updateConfigurationValue(configrecord)"
            @change="value => setConfigurationEditable(configrecord, value)">
          </a-select>
        </a-tooltip>
      </span>
      <span v-else>
        <a-tooltip :title="editableValue">
          <a-textarea
            style="width: 20vw; word-break: break-all"
            :defaultValue="actualValue"
            :disabled="(!('updateConfiguration' in $store.getters.apis) || configDisabled)"
            v-model:value="editableValue"
            @keydown.esc="editableValueKey = null"
            @pressEnter="updateConfigurationValue(configrecord)"
            @change="value => setConfigurationEditable(configrecord, value)"
          />
        </a-tooltip>
      </span>
      <span class="actions">
        <tooltip-button
          :tooltip="$t('label.cancel')"
          @onClick="cancelEditConfigurationValue(configrecord)"
          v-if="editableValueKey !== null"
          iconType="CloseCircleTwoTone"
          iconTwoToneColor="#f5222d"
          :disabled="valueLoading" />
        <tooltip-button
          :tooltip="$t('label.ok')"
          @onClick="updateConfigurationValue(configrecord)"
          v-if="editableValueKey !== null"
          iconType="CheckCircleTwoTone"
          iconTwoToneColor="#52c41a"
          :disabled="valueLoading" />
        <tooltip-button
          :tooltip="$t('label.reset.config.value')"
          @onClick="$resetConfigurationValueConfirm(configrecord, resetConfigurationValue)"
          v-if="editableValueKey === null"
          icon="reload-outlined"
          :disabled="(!('resetConfiguration' in $store.getters.apis) || configDisabled || valueLoading)" />
      </span>
    </a-list-item>
  </a-list>
</template>
<script>
import { postAPI } from '@/api'
import TooltipButton from '@/components/widgets/TooltipButton'

export default {
  name: 'ConfigurationValue',
  components: {
    TooltipButton
  },
  props: {
    configrecord: {
      type: Object,
      required: true
    },
    loading: {
      type: Boolean,
      default: false
    },
    configDisabled: {
      type: Boolean,
      default: false
    },
    actions: {
      type: Array,
      default: () => []
    },
    resource: {
      type: Object,
      required: false
    }
  },
  data () {
    return {
      valueLoading: this.loading,
      scopeKey: '',
      actualValue: null,
      editableValue: null,
      editableValueKey: null
    }
  },
  created () {
    switch (this.$route.meta.name) {
      case 'account':
        this.scopeKey = 'accountid'
        break
      case 'domain':
        this.scopeKey = 'domainid'
        break
      case 'zone':
        this.scopeKey = 'zoneid'
        break
      case 'cluster':
        this.scopeKey = 'clusterid'
        break
      case 'storagepool':
        this.scopeKey = 'storageid'
        break
      case 'imagestore':
        this.scopeKey = 'imagestoreuuid'
        break
      default:
        this.scopeKey = ''
    }
    this.setConfigData()
  },
  watch: {
    configrecord: {
      handler () {
        this.setConfigData()
      },
      deep: true
    }
  },
  methods: {
    setConfigData () {
      this.valueLoading = false
      this.editableValue = this.getEditableValue(this.configrecord)
      this.actualValue = this.editableValue
      this.editableValueKey = null
    },
    updateConfigurationValue (configrecord) {
      this.valueLoading = true
      this.editableValueKey = null
      var newValue = this.editableValue
      if (configrecord.type === 'Range') {
        newValue = newValue / 100
      }
      if (['Order', 'CSV'].includes(configrecord.type)) {
        newValue = newValue.join(',')
      }
      if (configrecord.type === 'WhitespaceSeparatedListWithOptions') {
        newValue = newValue.join(' ')
      }
      const params = {
        [this.scopeKey]: this.$route.params?.id,
        name: configrecord.name,
        value: newValue
      }
      if (this.scopeKey === 'domainid' && !params[this.scopeKey]) {
        params[this.scopeKey] = this.resource?.id
      }
      postAPI('updateConfiguration', params).then(json => {
        this.editableValue = this.getEditableValue(json.updateconfigurationresponse.configuration)
        this.actualValue = this.editableValue
        this.$emit('change-config', { value: newValue })
        this.$store.dispatch('RefreshFeatures')
        this.$messageConfigSuccess(`${this.$t('message.setting.updated')} ${configrecord.name}`, configrecord)
        this.$notifyConfigurationValueChange(json?.updateconfigurationresponse?.configuration || null)
      }).catch(error => {
        this.editableValue = this.actualValue
        console.error(error)
        this.$message.error(this.$t('message.error.save.setting'))
        this.$notification.error({
          message: this.$t('label.error'),
          description: error?.response?.data?.updateconfigurationresponse?.errortext || this.$t('message.error.save.setting')
        })
      }).finally(() => {
        this.valueLoading = false
        this.$emit('refresh')
      })
    },
    resetConfigurationValue (configrecord) {
      this.valueLoading = true
      this.editableValueKey = null
      const params = {
        [this.scopeKey]: this.$route.params?.id,
        name: configrecord.name
      }
      if (this.scopeKey === 'domainid' && !params[this.scopeKey]) {
        params[this.scopeKey] = this.resource?.id
      }
      postAPI('resetConfiguration', params).then(json => {
        this.editableValue = this.getEditableValue(json.resetconfigurationresponse.configuration)
        this.actualValue = this.editableValue
        var newValue = this.editableValue
        if (configrecord.type === 'Range') {
          newValue = newValue / 100
        }
        this.$emit('change-config', { value: newValue })
        this.$store.dispatch('RefreshFeatures')
        this.$messageConfigSuccess(`${this.$t('label.setting')} ${configrecord.name} ${this.$t('label.reset.config.value')}`, configrecord)
        this.$notifyConfigurationValueChange(json?.resetconfigurationresponse?.configuration || null)
      }).catch(error => {
        this.editableValue = this.actualValue
        console.error(error)
        this.$message.error(this.$t('message.error.reset.config'))
        this.$notification.error({
          message: this.$t('label.error'),
          description: this.$t('message.error.reset.config')
        })
      }).finally(() => {
        this.valueLoading = false
        this.$emit('refresh')
      })
    },
    getEditableValue (configrecord) {
      if (configrecord.type === 'Range') {
        return Number(configrecord.value) * 100 || 0
      }
      if (configrecord.type === 'Boolean') {
        return configrecord.value === 'true'
      }
      if (configrecord.type === 'Number' || configrecord.type === 'Decimal') {
        if (configrecord.value) {
          return Number(configrecord.value)
        } else if (configrecord.defaultvalue) {
          return Number(configrecord.defaultvalue)
        }
        return 0
      }
      if (['Order', 'CSV'].includes(configrecord.type)) {
        if (configrecord.value && configrecord.value.length > 0) {
          return String(configrecord.value).split(',')
        } else {
          return []
        }
      }
      if (configrecord.type === 'WhitespaceSeparatedListWithOptions') {
        if (configrecord.value && configrecord.value.length > 0) {
          return String(configrecord.value).split(' ')
        }

        return []
      }
      if (configrecord.value) {
        return String(configrecord.value)
      }
      if (configrecord.defaultvalue) {
        return String(configrecord.defaultvalue)
      }
      return ''
    },
    cancelEditConfigurationValue (configrecord) {
      this.editableValueKey = null
      this.editableValue = this.getEditableValue(configrecord)
    },
    setConfigurationEditable (configrecord, value) {
      if (this.actualValue !== this.editableValue) {
        this.editableValueKey = 'edit'
      } else {
        this.editableValueKey = null
      }
    },
    handleInputNumberKeyDown (event, isDecimal) {
      const allowedCodes = ['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Minus']

      if (isDecimal) {
        allowedCodes.push('Period')
      }

      if (
        event.getModifierState('Control') ||
        event.getModifierState('Meta') ||
        event.getModifierState('Alt')
      ) {
        return
      }

      const isValid = allowedCodes.includes(event.code) || !isNaN(event.key)
      if (!isValid) {
        event.preventDefault()
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.actions {
    margin-left: 10px;
    width: 100px;
}
</style>
