// 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" v-ctrl-enter="handleKeyboardSubmit">
    <a-alert type="warning">
      <template #message>
        <span v-html="$t('message.migrate.instance.to.host')" />
      </template>
    </a-alert>
    <a-input-search
      class="top-spaced"
      :placeholder="$t('label.search')"
      v-model:value="searchQuery"
      @search="fetchHostsForMigration"
      v-focus="true" />
    <a-table
      class="top-spaced"
      size="small"
      style="overflow-y: auto"
      :loading="loading"
      :columns="columns"
      :dataSource="hosts"
      :pagination="false"
      :rowKey="record => record.id">
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'name'">
          {{ record.name }}
          <a-tooltip v-if="record.name === $t('label.auto.assign')" :title="$t('message.migrate.instance.host.auto.assign')" placement="top">
            <info-circle-outlined class="table-tooltip-icon" />
          </a-tooltip>
        </template>
        <template v-if="column.key === 'suitability'">
          <check-circle-two-tone
            class="host-item__suitability-icon"
            twoToneColor="#52c41a"
            v-if="record.suitableformigration" />
          <close-circle-two-tone
            class="host-item__suitability-icon"
            twoToneColor="#f5222d"
            v-else />
        </template>
        <template v-if="column.key === 'memused'">
          <span v-if="record.memoryused">
            {{ $bytesToHumanReadableSize(record.memoryused) }}
          </span>
        </template>
        <template v-if="column.key === 'memoryallocatedpercentage'">
          {{ record.memoryallocatedpercentage }}
        </template>
        <template v-if="column.key === 'cluster'">
          {{ record.clustername }}
        </template>
        <template v-if="column.key === 'pod'">
          {{ record.podname }}
        </template>
        <template v-if="column.key === 'requiresstoragemigration'">
          {{ record.requiresStorageMotion ? $t('label.yes') : $t('label.no') }}
        </template>
        <template v-if="column.key === 'select'">
          <a-radio
            class="host-item__radio"
            @click="handleSelectedHostChange(record)"
            :checked="record.id === selectedHost.id"
            :disabled="!record.suitableformigration"></a-radio>
        </template>
      </template>
    </a-table>
    <a-pagination
      class="pagination"
      size="small"
      :current="page"
      :pageSize="pageSize"
      :total="totalCount"
      :showTotal="total => `${$t('label.total')} ${total} ${$t('label.items')}`"
      :pageSizeOptions="['10', '20', '40', '80', '100']"
      @change="handleChangePage"
      @showSizeChange="handleChangePageSize"
      showSizeChanger>
      <template #buildOptionText="props">
        <span>{{ props.value }} / {{ $t('label.page') }}</span>
      </template>
    </a-pagination>

    <a-form-item
      v-if="isUserVm && hasVolumes"
      class="top-spaced">
      <template #label>
        <tooltip-label :title="$t('label.migrate.with.storage')" :tooltip="$t('message.migrate.with.storage')"/>
      </template>
      <a-switch
        v-model:checked="migrateWithStorage"
        :disabled="!selectedHost || !selectedHost.id || selectedHost.id === -1" />
    </a-form-item>

    <a-radio-group
      v-if="migrateWithStorage"
      v-model:value="migrateMode"
      @change="e => { handleMigrateModeChange(e.target.value) }">
      <a-radio class="radio-style" :value="1">
        {{ $t('label.migrate.instance.single.storage') }}
      </a-radio>
      <a-radio class="radio-style" :value="2">
        {{ $t('label.migrate.instance.specific.storages') }}
      </a-radio>
    </a-radio-group>

    <div v-if="migrateWithStorage && migrateMode == 1">
      <storage-pool-select-view
        ref="storagePoolSelection"
        :autoAssignAllowed="false"
        :resource="resource"
        @select="handleStoragePoolChange" />
    </div>
    <instance-volumes-storage-pool-select-list-view
      ref="volumeToPoolSelect"
      v-if="migrateWithStorage && migrateMode !== 1"
      class="top-spaced"
      :resource="resource"
      :clusterId="selectedHost.id ? selectedHost.clusterid : null"
      @select="handleVolumeToPoolChange" />

    <a-divider />

    <div class="actions">
      <a-button @click="closeModal">{{ $t('label.cancel') }}</a-button>
      <a-button type="primary" ref="submit" :disabled="!selectedHost.id || (migrateWithStorage && migrateMode === 1 && !volumeToPoolSelection.length)" @click="submitForm">{{ $t('label.ok') }}</a-button>
    </div>
  </div>
</template>

<script>
import { getAPI, postAPI } from '@/api'
import TooltipLabel from '@/components/widgets/TooltipLabel'
import StoragePoolSelectView from '@/components/view/StoragePoolSelectView'
import InstanceVolumesStoragePoolSelectListView from '@/components/view/InstanceVolumesStoragePoolSelectListView'

export default {
  name: 'VMMigrateWizard',
  components: {
    TooltipLabel,
    StoragePoolSelectView,
    InstanceVolumesStoragePoolSelectListView
  },
  props: {
    resource: {
      type: Object,
      required: true
    }
  },
  data () {
    return {
      loading: true,
      hosts: [],
      selectedHost: {},
      searchQuery: '',
      totalCount: 0,
      page: 1,
      pageSize: 10,
      columns: [
        {
          key: 'name',
          title: this.$t('label.hostid')
        },
        {
          key: 'suitability',
          title: this.$t('label.suitability')
        },
        {
          title: this.$t('label.cpuused'),
          dataIndex: 'cpuused'
        },
        {
          key: 'memoryallocatedpercentage',
          title: this.$t('label.memoryallocated')
        },
        {
          key: 'memused',
          title: this.$t('label.memused')
        },
        {
          key: 'cluster',
          title: this.$t('label.cluster')
        },
        {
          key: 'pod',
          title: this.$t('label.pod')
        },
        {
          key: 'requiresstoragemigration',
          title: this.$t('label.storage.migration.required')
        },
        {
          key: 'select',
          title: this.$t('label.select')
        }
      ],
      migrateWithStorage: false,
      migrateMode: 1,
      volumeToPoolSelection: [],
      volumes: []
    }
  },
  created () {
    this.fetchData()
  },
  computed: {
    isUserVm () {
      return this.$route.meta.resourceType === 'UserVm'
    },
    hasVolumes () {
      return this.volumes && this.volumes.length > 0
    }
  },
  watch: {
    searchQuery (newValue, oldValue) {
      if (newValue !== oldValue) {
        this.page = 1
      }
    }
  },
  methods: {
    arrayHasItems (array) {
      return array !== null && array !== undefined && Array.isArray(array) && array.length > 0
    },
    fetchData () {
      this.fetchHostsForMigration()
      this.fetchVolumes()
    },
    fetchHostsForMigration () {
      this.loading = true
      getAPI('findHostsForMigration', {
        virtualmachineid: this.resource.id,
        keyword: this.searchQuery,
        page: this.page,
        pagesize: this.pageSize
      }).then(response => {
        this.hosts = response.findhostsformigrationresponse.host || []
        this.hosts.sort((a, b) => {
          return b.suitableformigration - a.suitableformigration
        })
        for (const key in this.hosts) {
          if (this.hosts[key].suitableformigration && !this.hosts[key].requiresstoragemigration) {
            this.hosts.unshift({ id: -1, name: this.$t('label.auto.assign'), suitableformigration: true, requiresstoragemigration: false })
            break
          }
        }
        this.totalCount = response.findhostsformigrationresponse.count
      }).catch(error => {
        this.$notifyError(error)
        this.closeModal()
      }).finally(() => {
        this.loading = false
      })
    },
    handleChangePage (page, pageSize) {
      this.page = page
      this.pageSize = pageSize
      this.fetchHostsForMigration()
    },
    handleChangePageSize (currentPage, pageSize) {
      this.page = currentPage
      this.pageSize = pageSize
      this.fetchHostsForMigration()
    },
    handleSelectedHostChange (host) {
      if (host.id === -1) {
        this.migrateWithStorage = false
      }
      this.selectedHost = host
      this.selectedVolumeForStoragePoolSelection = {}
      this.volumeToPoolSelection = []
      if (this.migrateWithStorage) {
        this.$refs.volumeToPoolSelect.resetSelection()
      }
    },
    handleMigrateModeChange () {
      this.volumeToPoolSelection = []
    },
    handleStoragePoolChange (storagePool) {
      this.volumeToPoolSelection = []
      for (const volume of this.volumes) {
        if (storagePool && storagePool.id && storagePool.id !== -1) {
          this.volumeToPoolSelection.push({ volume: volume.id, pool: storagePool.id })
        }
      }
    },
    handleVolumeToPoolChange (volumeToPool) {
      this.volumeToPoolSelection = volumeToPool
    },
    fetchVolumes () {
      this.loading = true
      this.volumes = []
      getAPI('listVolumes', {
        listAll: true,
        virtualmachineid: this.resource.id
      }).then(response => {
        this.volumes = response?.listvolumesresponse?.volume || []
      }).finally(() => {
        this.loading = false
      })
    },
    requiresStorageMigration () {
      if (this.selectedHost.requiresStorageMotion || this.volumeToPoolSelection.length > 0) {
        return true
      }
      if (this.selectedHost.id === -1 && this.hasVolumes) {
        for (var volume of this.volumes) {
          if (volume.storagetype === 'local') {
            return true
          }
        }
      }
      return false
    },
    handleKeyboardSubmit () {
      if (this.selectedHost.id) {
        this.submitForm()
      }
    },
    closeModal () {
      this.$emit('close-action')
    },
    submitForm () {
      if (this.loading) return
      this.loading = true
      const migrateApi = this.isUserVm
        ? this.requiresStorageMigration()
          ? 'migrateVirtualMachineWithVolume'
          : 'migrateVirtualMachine'
        : 'migrateSystemVm'
      var params = this.selectedHost.id === -1
        ? { autoselect: true, virtualmachineid: this.resource.id }
        : { hostid: this.selectedHost.id, virtualmachineid: this.resource.id }
      if (this.migrateWithStorage && this.volumeToPoolSelection && this.volumeToPoolSelection.length > 0) {
        for (var i = 0; i < this.volumeToPoolSelection.length; i++) {
          const mapping = this.volumeToPoolSelection[i]
          params['migrateto[' + i + '].volume'] = mapping.volume
          params['migrateto[' + i + '].pool'] = mapping.pool
        }
      }
      postAPI(migrateApi, params).then(response => {
        const jobId = response[migrateApi.toLowerCase() + 'response'].jobid
        this.$pollJob({
          jobId: jobId,
          title: `${this.$t('label.migrating')} ${this.resource.name}`,
          description: this.resource.name,
          successMessage: `${this.$t('message.success.migrating')} ${this.resource.name}`,
          successMethod: () => {
            this.closeModal()
          },
          errorMessage: this.$t('message.migrating.failed'),
          errorMethod: () => {
            this.closeModal()
          },
          loadingMessage: `${this.$t('message.migrating.processing')} ${this.resource.name}`,
          catchMessage: this.$t('error.fetching.async.job.result'),
          catchMethod: () => {
            this.closeModal()
          }
        })
        this.closeModal()
      }).catch(error => {
        this.$notification.error({
          message: this.$t('message.request.failed'),
          description: (error.response?.headers?.['x-description']) || error.message,
          duration: 0
        })
      }).finally(() => {
        this.loading = false
      })
    }
  }
}
</script>

<style scoped lang="scss">

  .form {
    width: 95vw;
    @media (min-width: 900px) {
      width: 850px;
    }
  }

  .host-item {
    padding-right: 20px;
    padding-bottom: 0;
    padding-left: 20px;

    &--selected {
      background-color: #e6f7ff;
    }

    &__row {
      display: flex;
      flex-direction: column;
      width: 100%;

      @media (min-width: 760px) {
        flex-direction: row;
      }
    }

    &__value {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      flex: 1;
      margin-bottom: 10px;

      &--small {

        @media (min-width: 760px) {
          flex: none;
          margin-right: 40px;
          margin-left: 40px;
        }
      }
    }

    &__title {
      font-weight: bold;
    }

    &__suitability-icon {
      margin-top: 5px;
    }

    &__radio {
      display: flex;
      align-items: center;
    }

  }

  .top-spaced {
    margin-top: 20px;
  }

  .pagination {
    margin-top: 20px;
  }

  .actions {
    display: flex;
    justify-content: flex-end;
    margin-top: 20px;

    button {
      &:not(:last-child) {
        margin-right: 10px;
      }
    }
  }
  .table-tooltip-icon {
    color: rgba(0,0,0,.45);
  }
</style>
