// 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-form
    v-ctrl-enter="handleSubmit"
    @finish="handleSubmit"
    layout="vertical">
    <a-alert type="warning" show-icon>
      <template #message>
        <span style="margin-bottom: 5px" v-html="$t('message.reinstall.vm')" />
      </template>
    </a-alert>
    <os-based-image-selection
      v-if="isModernImageSelection"
      :imageTypeSelectionAllowed="false"
      :guestOsCategories="options.guestOsCategories"
      :guestOsCategoriesLoading="loading.guestOsCategories"
      :selectedGuestOsCategoryId="selectedGuestOsCategoryId"
      :imageItems="options.templates"
      :imagesLoading="loading.templates"
      :filterOption="filterOption"
      :preFillContent="dataPreFill"
      @change-guest-os-category="onSelectGuestOsCategory"
      @handle-image-search-filter="($event) => fetchAllTemplates($event)"
      @update-image="updateFieldValue" />
    <a-form-item v-else>
      <template-iso-selection
        input-decorator="templateid"
        :items="options.templates"
        :selected="tabKey"
        :loading="loading.templates"
        :preFillContent="dataPreFill"
        :key="templateKey"
        @handle-search-filter="($event) => fetchAllTemplates($event)"
        @update-template-iso="updateFieldValue" />
    </a-form-item>
    <a-form-item>
      <template #label>
        <tooltip-label
          :title="$t('label.override.root.diskoffering')"
          :tooltip="apiParams.diskofferingid.description"
        />
      </template>
      <a-switch
        v-model:checked="overrideDiskOffering"
        @change="val => { overrideDiskOffering = val }"
      />
    </a-form-item>
    <a-form-item v-if="overrideDiskOffering">
      <disk-offering-selection
        :items="options.diskOfferings"
        :row-count="count.diskOfferings"
        :zoneId="resource.zoneId"
        :value="diskOffering ? diskOffering.id : ''"
        :loading="loading.diskOfferings"
        :preFillContent="dataPreFill"
        :isIsoSelected="false"
        :isRootDiskOffering="true"
        @on-selected-disk-size="onSelectDiskSize"
        @handle-search-filter="($event) => fetchDiskOfferings($event)"
      />
    </a-form-item>
    <a-form-item v-if="diskOffering && (diskOffering.iscustomized || diskOffering.iscustomizediops)">
      <disk-size-selection
        input-decorator="rootdisksize"
        :diskSelected="diskOffering"
        :isCustomized="diskOffering.iscustomized"
        @handler-error="handlerError"
        @update-disk-size="updateFieldValue"
        @update-root-disk-iops-value="updateFieldValue"
      />
    </a-form-item>
    <a-form-item v-if="!(diskOffering && diskOffering.iscustomized)">
      <template #label>
        <tooltip-label
          :title="$t('label.override.rootdisk.size')"
          :tooltip="apiParams.rootdisksize.description"
        />
      </template>
      <a-switch
        v-model:checked="overrideDiskSize"
        @change="val => { overrideDiskSize = val }"
      />
      <disk-size-selection
        v-if="overrideDiskSize"
        input-decorator="rootdisksize"
        :isCustomized="true"
        @update-disk-size="(input, value) => updateFieldValue('overrideRootDiskSize', value)"
        style="margin-top: 10px;"
      />
    </a-form-item>
    <a-form-item>
      <template #label>
        <tooltip-label
          :title="$t('label.expunge')"
          :tooltip="apiParams.expunge.description"
        />
      </template>
      <a-switch
        v-model:checked="expungeDisk"
        @change="val => { expungeDisk = val }"
      />
    </a-form-item>
    <div
      :span="24"
      class="action-button"
    >
      <a-button @click="closeAction">{{ $t('label.cancel') }}</a-button>
      <a-button
        ref="submit"
        type="primary"
        @click="handleSubmit"
      >{{ $t('label.ok') }}</a-button>
    </div>
  </a-form>
</template>

<script>
import { getAPI, postAPI } from '@/api'
import DiskOfferingSelection from '@views/compute/wizard/DiskOfferingSelection'
import DiskSizeSelection from '@views/compute/wizard/DiskSizeSelection'
import OsBasedImageSelection from '@views/compute/wizard/OsBasedImageSelection'
import TemplateIsoSelection from '@views/compute/wizard/TemplateIsoSelection'
import TooltipLabel from '@/components/widgets/TooltipLabel'
import _ from 'lodash'

export default {
  name: 'ReinstallVM',
  components: {
    DiskOfferingSelection,
    DiskSizeSelection,
    TemplateIsoSelection,
    OsBasedImageSelection,
    TooltipLabel
  },
  props: {
    resource: {
      type: Object,
      required: true
    }
  },
  inject: ['parentFetchData'],
  data () {
    return {
      overrideDiskOffering: false,
      overrideDiskSize: false,
      expungeDisk: false,
      selectedGuestOsCategoryId: null,
      options: {
        templates: {},
        diskOfferings: [],
        guestOsCategories: []
      },
      loading: {
        templates: false,
        diskOfferings: false,
        guestOsCategories: false
      },
      count: {
        diskOfferings: 0
      },
      rootDiskSizeKey: 'details[0].rootdisksize',
      minIopsKey: 'details[0].minIops',
      maxIopsKey: 'details[0].maxIops',
      rootdisksize: 0,
      minIops: 0,
      maxIops: 0,
      diskOffering: {},
      imageSearchFilters: null,
      templateid: null,
      templateKey: 0,
      dataPreFill: {
        templateid: this.resource.templateid,
        diskofferingid: this.resource.diskofferingid
      }
    }
  },
  beforeCreate () {
    this.apiParams = this.$getApiParams('restoreVirtualMachine')
  },
  created () {
    this.fetchData()
  },
  computed: {
    isNormalAndDomainUser () {
      return ['DomainAdmin', 'User'].includes(this.$store.getters.userInfo.roletype)
    },
    isModernImageSelection () {
      return this.$config.imageSelectionInterface === undefined || this.$config.imageSelectionInterface === 'modern'
    },
    imageSelection () {
      return this.isModernImageSelection ? 'modern' : 'legacy'
    },
    showUserCategoryForModernImageSelection () {
      return this.$config.showUserCategoryForModernImageSelection === undefined || this.$config.showUserCategoryForModernImageSelection
    },
    showAllCategoryForModernImageSelection () {
      return this.$config.showAllCategoryForModernImageSelection
    }
  },
  methods: {
    fetchData () {
      this.fetchDiskOfferings({})
      if (this.isModernImageSelection) {
        this.fetchGuestOsCategories()
      } else {
        this.fetchAllTemplates()
      }
    },
    getImageFilters (params, forReset) {
      if (this.isModernImageSelection) {
        if (this.selectedGuestOsCategoryId === '0') {
          return ['self']
        }
        if (this.isModernImageSelection && params && !forReset) {
          if (params.featured) {
            return ['featured']
          } else if (params.public) {
            return ['community']
          }
        }
        return this.isNormalAndDomainUser ? ['executable'] : ['all']
      }
      return [
        'featured',
        'community',
        'selfexecutable',
        'sharedexecutable'
      ]
    },
    closeAction () {
      this.$emit('close-action')
    },
    handlerError (error) {
      this.error = error
    },
    handleSubmit () {
      const params = {
        virtualmachineid: this.resource.id
      }
      if (this.templateid) {
        params.templateid = this.templateid
      }
      if (this.overrideDiskOffering) {
        params.diskofferingid = this.diskOffering.id
        if (this.diskOffering.iscustomized) {
          params[this.rootDiskSizeKey] = this.rootdisksize
        }
        if (this.diskOffering.iscustomizediops) {
          params[this.minIopsKey] = this.minIops
          params[this.maxIopsKey] = this.maxIops
        }
      }
      if (this.overrideDiskSize && this.overrideRootDiskSize) {
        params.rootdisksize = this.overrideRootDiskSize
      }
      params.expunge = this.expungeDisk
      postAPI('restoreVirtualMachine', params).then(response => {
        this.$pollJob({
          jobId: response.restorevmresponse.jobid,
          successMessage: this.$t('label.reinstall.vm') + ' ' + this.$t('label.success'),
          successMethod: (result) => {
            const vm = result.jobresult.virtualmachine || {}
            const name = vm.displayname || vm.name || vm.id
            if (result.jobstatus === 1 && vm.password) {
              this.$notification.success({
                message: `${this.$t('label.reinstall.vm')}: ` + name,
                description: `${this.$t('label.password.reset.confirm')}: ` + vm.password,
                duration: 0
              })
            }
          },
          errorMessage: this.$t('label.reinstall.vm') + ' ' + this.$t('label.failed'),
          errorMethod: (result) => {
            this.closeAction()
          },
          loadingMessage: this.$t('label.reinstall.vm') + ': ' + this.resource.name,
          catchMessage: this.$t('error.fetching.async.job.result')
        })
      }).catch(error => {
        this.$notifyError(error)
        this.closeAction()
      }).finally(() => {
        this.closeAction()
      })
    },
    fetchGuestOsCategories () {
      this.loading.guestOsCategories = true
      const params = {
        zoneid: this.resource.zoneid,
        arch: this.resource.arch,
        isiso: false,
        featured: true,
        showicon: true
      }
      getAPI('listOsCategories', params).then((response) => {
        this.options.guestOsCategories = response?.listoscategoriesresponse?.oscategory || []
        if (this.showUserCategoryForModernImageSelection) {
          const userCategory = {
            id: '0',
            name: this.$t('label.user')
          }
          if (this.$store.getters.avatar) {
            userCategory.icon = {
              base64image: this.$store.getters.avatar
            }
          }
          this.options.guestOsCategories.push(userCategory)
        }
        if (this.showAllCategoryForModernImageSelection) {
          this.options.guestOsCategories.push({
            id: '-1',
            name: this.$t('label.all')
          })
        }
        this.selectedGuestOsCategoryId = this.options.guestOsCategories[0].id
      }).finally(() => {
        this.loading.guestOsCategories = false
        this.fetchAllTemplates()
      })
    },
    fetchAllTemplates (params) {
      const promises = []
      const templates = {}
      this.loading.templates = true
      this.imageSearchFilters = params
      const templateFilters = this.getImageFilters(params)
      templateFilters.forEach((filter) => {
        templates[filter] = { count: 0, template: [] }
        promises.push(this.fetchTemplates(filter, params))
      })
      this.options.templates = templates
      Promise.all(promises).then((response) => {
        response.forEach((resItem, idx) => {
          templates[templateFilters[idx]] = _.isEmpty(resItem.listtemplatesresponse) ? { count: 0, template: [] } : resItem.listtemplatesresponse
          this.options.templates = { ...templates }
        })
      }).catch((reason) => {
        console.log(reason)
      }).finally(() => {
        this.loading.templates = false
      })
    },
    fetchTemplates (templateFilter, params) {
      const args = Object.assign({}, params)
      if (this.isModernImageSelection && this.selectedGuestOsCategoryId && !['-1', '0'].includes(this.selectedGuestOsCategoryId)) {
        args.oscategoryid = this.selectedGuestOsCategoryId
      }
      if (!args.page || args.keyword || (args.category && args.category !== templateFilter)) {
        args.page = 1
      }
      args.pageSize = args.pageSize || 10
      args.zoneid = this.resource.zoneid
      args.templatefilter = templateFilter
      args.isready = true
      if (this.resource.arch) {
        args.arch = this.resource.arch
      }
      args.details = 'all'
      args.showicon = 'true'

      return new Promise((resolve, reject) => {
        getAPI('listTemplates', args).then((response) => {
          resolve(response)
        }).catch((reason) => {
          reject(reason)
        })
      })
    },
    fetchDiskOfferings (params) {
      getAPI('listDiskOfferings', { zoneid: this.resource.zoneid, listall: true, ...params }).then((response) => {
        this.options.diskOfferings = response?.listdiskofferingsresponse?.diskoffering || []
        this.count.diskOfferings = response?.listdiskofferingsresponse?.count || 0
      })
    },
    onSelectGuestOsCategory (value) {
      this.selectedGuestOsCategoryId = value
      this.fetchAllTemplates(this.imageSearchFilters)
    },
    onSelectDiskSize (rowSelected) {
      this.diskOffering = rowSelected
      this.dataPreFill.diskofferingid = rowSelected.id
    },
    updateFieldValue (input, value) {
      this[input] = value
      this.dataPreFill[input] = value
    },
    filterOption (input, option) {
      return option.label.toUpperCase().indexOf(input.toUpperCase()) >= 0
    }
  }
}
</script>

<style
  scoped
  lang="scss"
>
.ant-form {
  width: 90vw;

  @media (min-width: 700px) {
    width: 50vw;
  }
}
</style>
