// 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="form-layout" v-ctrl-enter="handleSubmit">
    <a-spin :spinning="loading">
      <a-form
        :ref="formRef"
        :model="form"
        :rules="rules"
        @finish="handleSubmit"
        layout="vertical">
        <a-form-item name="volumeid" ref="volumeid">
          <template #label>
            <tooltip-label :title="$t('label.volumeid')" :tooltip="apiParams.volumeid.description"/>
          </template>
          <a-select
            allowClear
            v-model:value="form.volumeid"
            @change="onChangeVolume"
            :placeholder="apiParams.volumeid.description"
            v-focus="true"
            showSearch
            optionFilterProp="label"
            :filterOption="(input, option) => {
              return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
            }">
            <a-select-option
              v-for="volume in listVolumes"
              :key="volume.id"
              :label="volume.name">
              {{ volume.name }}
            </a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item name="name" ref="name">
          <template #label>
            <tooltip-label :title="$t('label.name')" :tooltip="apiParams.name.description"/>
          </template>
          <a-input
            v-model:value="form.name"
            :placeholder="apiParams.name.description"/>
        </a-form-item>
        <a-form-item name="quiescevm" ref="quiescevm" v-if="isQuiesceVm && hypervisorSupportsQuiesceVm">
          <template #label>
            <tooltip-label :title="$t('label.quiescevm')" :tooltip="apiParams.quiescevm.description"/>
          </template>
          <a-switch v-model:checked="form.quiescevm"/>
        </a-form-item>
        <a-form-item name="asyncbackup" ref="asyncbackup" v-if="!supportsStorageSnapshot">
          <template #label>
            <tooltip-label :title="$t('label.asyncbackup')" :tooltip="apiParams.asyncbackup.description"/>
          </template>
          <a-switch v-model:checked="form.asyncbackup"/>
        </a-form-item>
        <div :span="24" class="action-button">
          <a-button @click="closeAction">{{ $t('label.cancel') }}</a-button>
          <a-button :loading="loading" ref="submit" type="primary" @click="handleSubmit">{{ $t('label.ok') }}</a-button>
        </div>
      </a-form>
    </a-spin>
  </div>
</template>

<script>
import { ref, reactive, toRaw } from 'vue'
import { api } from '@/api'
import { mixinForm } from '@/utils/mixin'
import TooltipLabel from '@/components/widgets/TooltipLabel'

export default {
  name: 'CreateSnapshotWizard',
  mixins: [mixinForm],
  components: {
    TooltipLabel
  },
  props: {
    resource: {
      type: Object,
      required: true
    }
  },
  data () {
    return {
      loading: false,
      isQuiesceVm: false,
      hypervisorSupportsQuiesceVm: false,
      supportsStorageSnapshot: false,
      listVolumes: []
    }
  },
  beforeCreate () {
    this.apiParams = this.$getApiParams('createSnapshot')
  },
  created () {
    this.initForm()
    this.fetchData()
  },
  methods: {
    initForm () {
      this.formRef = ref()
      this.form = reactive({})
      this.rules = reactive({
        volumeid: [{ required: true, message: this.$t('message.error.select') }]
      })
    },
    fetchData () {
      this.loading = true
      if (['KVM', 'VMware'].includes(this.resource.hypervisor)) {
        this.hypervisorSupportsQuiesceVm = true
      }

      api('listVolumes', { virtualMachineId: this.resource.id, listall: true })
        .then(json => {
          this.listVolumes = json.listvolumesresponse.volume || []
        })
        .catch(e => {})
        .finally(() => { this.loading = false })
    },
    handleSubmit (e) {
      e.preventDefault()

      if (this.loading) return
      this.formRef.value.validate().then(() => {
        const formRaw = toRaw(this.form)
        const values = this.handleRemoveFields(formRaw)
        const params = {}
        params.volumeid = values.volumeid
        params.name = values.name
        params.asyncbackup = false
        if (values.asyncbackup) {
          params.asyncbackup = values.asyncbackup
        }
        params.quiescevm = false
        if (values.quiescevm) {
          params.quiescevm = values.quiescevm
        }

        const title = this.$t('label.action.vmstoragesnapshot.create')
        const description = values.name || values.volumeid

        this.loading = true

        api('createSnapshot', params)
          .then(json => {
            const jobId = json.createsnapshotresponse.jobid
            if (jobId) {
              this.$pollJob({
                jobId,
                title,
                description,
                successMethod: result => {
                  const volumeId = result.jobresult.snapshot.volumeid
                  const snapshotId = result.jobresult.snapshot.id
                  const message = `${this.$t('label.create.snapshot.for.volume')} ${volumeId} ${this.$t('label.with.snapshotid')} ${snapshotId}`
                  this.$notification.success({
                    message: message,
                    duration: 0
                  })
                },
                loadingMessage: `${title} ${this.$t('label.in.progress')}`,
                catchMessage: this.$t('error.fetching.async.job.result')
              })
            }
          }).catch(error => {
            this.$notifyError(error)
          }).finally(() => {
            this.loading = false
            this.closeAction()
          })
      }).catch(error => {
        this.formRef.value.scrollToField(error.errorFields[0].name)
      })
    },
    onChangeVolume (volumeId) {
      const volumeFilter = this.listVolumes.filter(volume => volume.id === volumeId)
      if (volumeFilter && volumeFilter.length > 0) {
        this.isQuiesceVm = volumeFilter[0].quiescevm
        this.supportsStorageSnapshot = volumeFilter[0].supportsstoragesnapshot
      }
    },
    closeAction () {
      this.$emit('close-action')
    }
  }
}
</script>

<style scoped lang="less">
.form-layout {
  width: 80vw;
  @media (min-width: 600px) {
    width: 450px;
  }
}
</style>
