// 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-spin :spinning="loading">
    <a-alert
      v-if="disableSettings"
      banner
      :message="$t('message.action.settings.warning.vm.running')" />
    <div v-else>
      <div v-show="!showAddDetail">
        <a-button
          type="dashed"
          style="width: 100%"
          :disabled="!(isAdminOrOwner() && hasSettingUpdatePermission())"
          @click="onShowAddDetail">
          <template #icon><plus-outlined /></template>
          {{ $t('label.add.setting') }}
        </a-button>
      </div>
      <div v-show="showAddDetail">
        <a-input-group
          type="text"
          compact>
          <a-auto-complete
            class="detail-input"
            ref="keyElm"
            :filterOption="(input, option) => filterOption(input, option, 'key')"
            v-model:value="newKey"
            :options="detailKeys"
            :placeholder="$t('label.name')"
            @change="e => onAddInputChange(e, 'newKey')" />
          <a-input
            class="tag-disabled-input"
            style=" width: 30px; border-left: 0; pointer-events: none; text-align: center"
            placeholder="="
            disabled />
          <a-auto-complete
            class="detail-input"
            :filterOption="(input, option) => filterOption(input, option, 'value')"
            v-model:value="newValue"
            :options="detailValues"
            :placeholder="$t('label.value')"
            @change="e => onAddInputChange(e, 'newValue')" />
          <tooltip-button :tooltip="$t('label.add.setting')" :shape="null" icon="check-outlined" @onClick="addDetail" buttonClass="detail-button" />
          <tooltip-button :tooltip="$t('label.cancel')" :shape="null" icon="close-outlined" @onClick="closeDetail" buttonClass="detail-button" />
        </a-input-group>
        <p v-if="error" style="color: red"> {{ $t(error) }} </p>
      </div>
    </div>
    <a-list size="large">
      <a-list-item :key="index" v-for="(item, index) in details">
        <a-list-item-meta>
          <template #title>
            {{ item.name }}
          </template>
          <template #description>
            <div v-if="item.edit" style="display: flex">
              <a-auto-complete
                style="width: 100%"
                v-model:value="item.value"
                :options="getDetailOptions(detailOptions[item.name])"
                @change="val => handleInputChange(val, index)"
                @pressEnter="e => updateDetail(index)" />
              <tooltip-button
                buttonClass="edit-button"
                :tooltip="$t('label.cancel')"
                @onClick="hideEditDetail(index)"
                v-if="item.edit"
                iconType="close-circle-two-tone"
                iconTwoToneColor="#f5222d" />
              <tooltip-button
                buttonClass="edit-button"
                :tooltip="$t('label.ok')"
                @onClick="updateDetail(index)"
                v-if="item.edit"
                iconType="check-circle-two-tone"
                iconTwoToneColor="#52c41a" />
            </div>
            <span v-else style="word-break: break-all">{{ item.value }}</span>
          </template>
        </a-list-item-meta>
        <template #actions>
          <div
            v-if="!disableSettings && isAdminOrOwner() && allowEditOfDetail(item.name) && hasSettingUpdatePermission()">
            <tooltip-button
              :tooltip="$t('label.edit')"
              icon="edit-outlined"
              :disabled="deployasistemplate === true || item.name.startsWith('extraconfig')"
              v-if="!item.edit"
              @onClick="showEditDetail(index)" />
          </div>
          <div
            v-if="!disableSettings && isAdminOrOwner() && allowEditOfDetail(item.name) && hasSettingUpdatePermission()">
            <a-popconfirm
              :title="`${$t('label.delete.setting')}?`"
              @confirm="deleteDetail(index)"
              :okText="$t('label.yes')"
              :cancelText="$t('label.no')"
              placement="left"
            >
              <tooltip-button
                :tooltip="$t('label.delete')"
                :disabled="deployasistemplate === true || item.name.startsWith('extraconfig')"
                type="primary"
                :danger="true"
                icon="delete-outlined" />
            </a-popconfirm>
          </div>
        </template>
      </a-list-item>
    </a-list>
  </a-spin>
</template>

<script>
import { api } from '@/api'
import TooltipButton from '@/components/widgets/TooltipButton'

export default {
  components: { TooltipButton },
  name: 'DetailSettings',
  props: {
    resource: {
      type: Object,
      required: true
    }
  },
  data () {
    return {
      details: [],
      detailOptions: {},
      showAddDetail: false,
      disableSettings: false,
      newKey: '',
      newValue: '',
      loading: false,
      resourceType: 'UserVm',
      deployasistemplate: false,
      error: false
    }
  },
  watch: {
    resource: {
      deep: true,
      handler (newItem) {
        this.updateResource(newItem)
      }
    }
  },
  computed: {
    detailKeys () {
      return Object.keys(this.detailOptions).map(key => {
        return { value: key }
      })
    },
    detailValues () {
      if (!this.newKey) {
        return []
      }
      if (!Array.isArray(this.detailOptions[this.newKey])) {
        if (this.detailOptions[this.newKey]) {
          return { value: this.detailOptions[this.newKey] }
        } else {
          return []
        }
      }
      return this.detailOptions[this.newKey].map(value => {
        return { value: value }
      })
    }
  },
  created () {
    this.updateResource(this.resource)
  },
  methods: {
    filterOption (input, option, filterType) {
      if ((filterType === 'key' && !this.newKey) ||
        (filterType === 'value' && !this.newValue)) {
        return true
      }

      return (
        option.value.toUpperCase().indexOf(input.toUpperCase()) >= 0
      )
    },
    updateResource (resource) {
      this.details = []
      if (!resource) {
        return
      }
      this.resourceType = this.$route.meta.resourceType
      if (resource.details) {
        this.details = Object.keys(resource.details).map(k => {
          return { name: k, value: resource.details[k], edit: false }
        })
      }
      api('listDetailOptions', { resourcetype: this.resourceType, resourceid: resource.id }).then(json => {
        this.detailOptions = json.listdetailoptionsresponse.detailoptions.details
      })
      this.disableSettings = (this.$route.meta.name === 'vm' && resource.state !== 'Stopped')
      api('listTemplates', { templatefilter: 'all', id: resource.templateid }).then(json => {
        this.deployasistemplate = json.listtemplatesresponse.template[0].deployasis
      })
    },
    allowEditOfDetail (name) {
      if (this.resource.readonlydetails) {
        if (this.resource.readonlydetails.split(',').map(item => item.trim()).includes(name)) {
          return false
        }
      }
      return true
    },
    showEditDetail (index) {
      this.details[index].edit = true
      this.details[index].originalValue = this.details[index].value
    },
    hideEditDetail (index) {
      this.details[index].edit = false
      this.details[index].value = this.details[index].originalValue
    },
    handleInputChange (val, index) {
      this.details[index].value = val
    },
    getDetailOptions (values) {
      if (!values) {
        return
      }
      var data = values.map(value => { return { value: value } })
      return data
    },
    onAddInputChange (val, obj) {
      this.error = false
      this[obj] = val
    },
    isAdminOrOwner () {
      return ['Admin'].includes(this.$store.getters.userInfo.roletype) ||
        (this.resource.domainid === this.$store.getters.userInfo.domainid && this.resource.account === this.$store.getters.userInfo.account) ||
        this.resource.project && this.resource.projectid === this.$store.getters.project.id
    },
    getDetailsParam (details) {
      var params = {}
      var filteredDetails = details
      if (this.resource.readonlydetails && filteredDetails) {
        filteredDetails = []
        var readOnlyDetailNames = this.resource.readonlydetails.split(',').map(item => item.trim())
        for (var detail of this.details) {
          if (!readOnlyDetailNames.includes(detail.name)) {
            filteredDetails.push(detail)
          }
        }
      }
      if (filteredDetails.length === 0) {
        params.cleanupdetails = true
      } else {
        filteredDetails.forEach(function (item, index) {
          params['details[0].' + item.name] = item.value
        })
      }
      return params
    },
    runApi () {
      var apiName = ''
      if (this.resourceType === 'UserVm') {
        apiName = 'updateVirtualMachine'
      } else if (this.resourceType === 'Template') {
        apiName = 'updateTemplate'
      }
      if (!(apiName in this.$store.getters.apis)) {
        this.$notification.error({
          message: this.$t('error.execute.api.failed') + ' ' + apiName,
          description: this.$t('message.user.not.permitted.api')
        })
        return
      }

      var params = { id: this.resource.id }
      params = Object.assign(params, this.getDetailsParam(this.details))
      this.loading = true
      api(apiName, params).then(json => {
        var details = {}
        if (this.resourceType === 'UserVm' && json.updatevirtualmachineresponse.virtualmachine.details) {
          details = json.updatevirtualmachineresponse.virtualmachine.details
        } else if (this.resourceType === 'Template' && json.updatetemplateresponse.template.details) {
          details = json.updatetemplateresponse.template.details
        }
        this.details = Object.keys(details).map(k => {
          return { name: k, value: details[k], edit: false }
        })
      }).catch(error => {
        this.$notifyError(error)
      }).finally(f => {
        this.loading = false
        this.showAddDetail = false
        this.newKey = ''
        this.newValue = ''
      })
    },
    addDetail () {
      if (this.newKey === '' || this.newValue === '') {
        this.error = this.$t('message.error.provide.setting')
        return
      }
      if (this.newKey.startsWith('extraconfig')) {
        this.error = this.$t('error.unable.to.add.setting.extraconfig')
        return
      }
      if (!this.allowEditOfDetail(this.newKey)) {
        this.error = this.$t('error.unable.to.proceed')
        return
      }
      this.error = false
      this.details.push({ name: this.newKey, value: this.newValue })
      this.runApi()
    },
    updateDetail (index) {
      this.runApi()
    },
    deleteDetail (index) {
      this.details.splice(index, 1)
      this.runApi()
    },
    onShowAddDetail () {
      this.showAddDetail = true
      setTimeout(() => {
        this.$refs.keyElm.focus()
      })
    },
    closeDetail () {
      this.newKey = ''
      this.newValue = ''
      this.error = false
      this.showAddDetail = false
    },
    hasSettingUpdatePermission () {
      return (
        (this.resourceType === 'Template' && 'updateTemplate' in this.$store.getters.apis) ||
        (this.resourceType === 'UserVm' && 'updateVirtualMachine' in this.$store.getters.apis)
      )
    }
  }
}
</script>

<style scoped lang="less">
.detail-input {
  width: calc(calc(100% / 2) - 45px);
}

.detail-button {
  width: 30px;
}
</style>
