// 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>
    <a-row :gutter="12">
      <a-col :md="24" :lg="17">
        <a-card :bordered="true" :title="$t('label.new.autoscale.vmgroup')">
          <a-form
            v-ctrl-enter="handleSubmit"
            :ref="formRef"
            :model="form"
            :rules="rules"
            @finish="handleSubmit"
            layout="vertical"
          >
            <a-steps direction="vertical" size="small">
              <a-step :title="$t('label.select.a.zone')" status="process">
                <template #description>
                  <div style="margin-top: 15px">
                    <span>{{ $t('message.select.a.zone') }}</span><br/>
                    <a-form-item :label="$t('label.zoneid')" name="zoneid" ref="zoneid">
                      <div v-if="zones.length <= 8">
                        <a-row type="flex" :gutter="[16,18]" justify="start">
                          <div v-for="(zoneItem, idx) in zones" :key="idx">
                            <a-radio-group
                              :key="idx"
                              :size="large"
                              v-model:value="form.zoneid"
                              @change="onSelectZoneId(zoneItem.id)">
                              <a-col :span="6">
                                <a-radio-button
                                  :value="zoneItem.id"
                                  style="border-width: 2px"
                                  class="zone-radio-button">
                                  <span>
                                    <resource-icon
                                      v-if="zoneItem && zoneItem.icon && zoneItem.icon.base64image"
                                      :image="zoneItem.icon.base64image"
                                      size="2x" />
                                    <global-outlined size="2x" v-else />
                                    {{ zoneItem.name }}
                                    </span>
                                </a-radio-button>
                              </a-col>
                            </a-radio-group>
                          </div>
                        </a-row>
                      </div>
                      <a-select
                        v-else
                        v-model:value="form.zoneid"
                        showSearch
                        optionFilterProp="label"
                        :filterOption="(input, option) => {
                          return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                        }"
                        @change="onSelectZoneId"
                        :loading="loading.zones"
                        v-focus="true"
                      >
                        <a-select-option v-for="zone1 in zones" :key="zone1.id" :label="zone1.name">
                          <span>
                            <resource-icon v-if="zone1.icon && zone1.icon.base64image" :image="zone1.icon.base64image" size="1x" style="margin-right: 5px"/>
                            <global-outlined v-else style="margin-right: 5px" />
                            {{ zone1.name }}
                          </span>
                        </a-select-option>
                      </a-select>
                    </a-form-item>
                  </div>
                </template>
              </a-step>
              <a-step
                :title="$t('label.template')"
                :status="zoneSelected ? 'process' : 'wait'">
                <template #description>
                  <div v-if="zoneSelected" style="margin-top: 15px">
                    <a-card
                      :tabList="tabList"
                      :activeTabKey="tabKey"
                      @tabChange="key => onTabChange(key, 'tabKey')">
                      <div v-if="tabKey === 'templateid'">
                        {{ $t('message.template.desc') }}
                        <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" />
                         <div>
                          {{ $t('label.override.rootdisk.size') }}
                          <a-switch
                            v-model:checked="form.rootdisksizeitem"
                            :disabled="rootDiskSizeFixed > 0 || template.deployasis || showOverrideDiskOfferingOption"
                            @change="val => { showRootDiskSizeChanger = val }"
                            style="margin-left: 10px;"/>
                          <div v-if="template.deployasis">  {{ $t('message.deployasis') }} </div>
                        </div>
                        <disk-size-selection
                          v-if="showRootDiskSizeChanger"
                          input-decorator="rootdisksize"
                          :preFillContent="dataPreFill"
                          :isCustomized="true"
                          :minDiskSize="dataPreFill.minrootdisksize"
                          @update-disk-size="updateFieldValue"
                          style="margin-top: 10px;"/>
                      </div>
                    </a-card>
                    <a-form-item class="form-item-hidden">
                      <a-input v-model:value="form.templateid" />
                    </a-form-item>
                    <a-form-item class="form-item-hidden">
                      <a-input v-model:value="form.rootdisksize" />
                    </a-form-item>
                  </div>
                </template>
              </a-step>
              <a-step
                :title="$t('label.serviceofferingid')"
                :status="zoneSelected ? 'process' : 'wait'">
                <template #description>
                  <div v-if="zoneSelected">
                    <a-form-item v-if="zoneSelected && templateConfigurationExists" name="templateConfiguration" ref="templateConfiguration">
                      <template #label>
                        <tooltip-label :title="$t('label.configuration')" :tooltip="$t('message.ovf.configurations')"/>
                      </template>
                      <a-select
                        showSearch
                        optionFilterProp="label"
                        v-model:value="form.templateConfiguration"
                        defaultActiveFirstOption
                        :placeholder="$t('message.ovf.configurations')"
                        :filterOption="(input, option) => {
                          return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                        }"
                        @change="onSelectTemplateConfigurationId"
                      >
                        <a-select-option v-for="opt in templateConfigurations" :key="opt.id" :label="opt.name || opt.description">
                          {{ opt.name || opt.description }}
                        </a-select-option>
                      </a-select>
                      <span v-if="selectedTemplateConfiguration && selectedTemplateConfiguration.description">{{ selectedTemplateConfiguration.description }}</span>
                    </a-form-item>
                    <compute-offering-selection
                      :compute-items="options.serviceOfferings"
                      :selected-template="template ? template : {}"
                      :row-count="rowCount.serviceOfferings"
                      :zoneId="zoneId"
                      :autoscale="true"
                      :value="serviceOffering ? serviceOffering.id : ''"
                      :loading="loading.serviceOfferings"
                      :preFillContent="dataPreFill"
                      :minimum-cpunumber="templateConfigurationExists && selectedTemplateConfiguration && selectedTemplateConfiguration.cpunumber ? selectedTemplateConfiguration.cpunumber : 0"
                      :minimum-cpuspeed="templateConfigurationExists && selectedTemplateConfiguration && selectedTemplateConfiguration.cpuspeed ? selectedTemplateConfiguration.cpuspeed : 0"
                      :minimum-memory="templateConfigurationExists && selectedTemplateConfiguration && selectedTemplateConfiguration.memory ? selectedTemplateConfiguration.memory : 0"
                      @select-compute-item="($event) => updateComputeOffering($event)"
                      @handle-search-filter="($event) => handleSearchFilter('serviceOfferings', $event)"
                    ></compute-offering-selection>
                    <compute-selection
                      v-if="serviceOffering && (serviceOffering.iscustomized || serviceOffering.iscustomizediops)"
                      cpuNumberInputDecorator="cpunumber"
                      cpuSpeedInputDecorator="cpuspeed"
                      memoryInputDecorator="memory"
                      :preFillContent="dataPreFill"
                      :computeOfferingId="vmgroupConfig.computeofferingid"
                      :isConstrained="isOfferingConstrained(serviceOffering)"
                      :minCpu="'serviceofferingdetails' in serviceOffering ? serviceOffering.serviceofferingdetails.mincpunumber*1 : 0"
                      :maxCpu="'serviceofferingdetails' in serviceOffering ? serviceOffering.serviceofferingdetails.maxcpunumber*1 : Number.MAX_SAFE_INTEGER"
                      :minMemory="'serviceofferingdetails' in serviceOffering ? serviceOffering.serviceofferingdetails.minmemory*1 : 0"
                      :maxMemory="'serviceofferingdetails' in serviceOffering ? serviceOffering.serviceofferingdetails.maxmemory*1 : Number.MAX_SAFE_INTEGER"
                      :isCustomized="serviceOffering.iscustomized"
                      :isCustomizedIOps="'iscustomizediops' in serviceOffering && serviceOffering.iscustomizediops"
                      @handler-error="handlerError"
                      @update-iops-value="updateIOPSValue"
                      @update-compute-cpunumber="updateFieldValue"
                      @update-compute-cpuspeed="updateFieldValue"
                      @update-compute-memory="updateFieldValue" />
                    <span v-if="serviceOffering && serviceOffering.iscustomized">
                      <a-form-item name="cpunumber" ref="cpunumber" class="form-item-hidden">
                        <a-input v-model:value="form.cpunumber"/>
                      </a-form-item>
                      <a-form-item
                        class="form-item-hidden"
                        v-if="(serviceOffering && !(serviceOffering.cpuspeed > 0))"
                        name="cpuspeed"
                        ref="cpuspeed">
                        <a-input v-model:value="form.cpuspeed"/>
                      </a-form-item>
                      <a-form-item class="form-item-hidden" name="memory" ref="memory">
                        <a-input v-model:value="form.memory"/>
                      </a-form-item>
                    </span>
                    <span>
                      {{ $t('label.override.root.diskoffering') }}
                      <a-switch
                        v-model:checked="showOverrideDiskOfferingOption"
                        :checked="serviceOffering && !serviceOffering.diskofferingstrictness && showOverrideDiskOfferingOption"
                        :disabled="(serviceOffering && serviceOffering.diskofferingstrictness)"
                        @change="val => { updateOverrideRootDiskShowParam(val) }"
                        style="margin-left: 10px;"/>
                    </span>
                    <span v-if="serviceOffering && !serviceOffering.diskofferingstrictness">
                      <a-step
                        :status="zoneSelected ? 'process' : 'wait'"
                        v-if="!template.deployasis && template.childtemplates && template.childtemplates.length > 0" >
                        <template #description>
                          <div v-if="zoneSelected">
                            <multi-disk-selection
                              :items="template.childtemplates"
                              :diskOfferings="options.diskOfferings"
                              :zoneId="zoneId"
                              @select-multi-disk-offering="updateMultiDiskOffering($event)" />
                          </div>
                        </template>
                      </a-step>
                      <a-step
                        v-else
                        :status="zoneSelected ? 'process' : 'wait'">
                        <template #description>
                          <div v-if="zoneSelected">
                            <disk-offering-selection
                              v-if="showOverrideDiskOfferingOption"
                              :items="options.diskOfferings"
                              :row-count="rowCount.diskOfferings"
                              :zoneId="zoneId"
                              :value="overrideDiskOffering ? overrideDiskOffering.id : ''"
                              :loading="loading.diskOfferings"
                              :preFillContent="dataPreFill"
                              :isIsoSelected="tabKey==='isoid'"
                              :isRootDiskOffering="true"
                              @on-selected-root-disk-size="onSelectRootDiskSize"
                              @select-disk-offering-item="($event) => updateOverrideDiskOffering($event)"
                              @handle-search-filter="($event) => handleSearchFilter('diskOfferings', $event)"
                            ></disk-offering-selection>
                            <disk-size-selection
                              v-if="overrideDiskOffering && (overrideDiskOffering.iscustomized || overrideDiskOffering.iscustomizediops)"
                              input-decorator="rootdisksize"
                              :preFillContent="dataPreFill"
                              :minDiskSize="dataPreFill.minrootdisksize"
                              :rootDiskSelected="overrideDiskOffering"
                              :isCustomized="overrideDiskOffering.iscustomized"
                              @handler-error="handlerError"
                              @update-disk-size="updateFieldValue"
                              @update-root-disk-iops-value="updateIOPSValue"/>
                            <a-form-item class="form-item-hidden">
                              <a-input v-model:value="form.rootdisksize"/>
                            </a-form-item>
                          </div>
                        </template>
                      </a-step>
                    </span>
                  </div>
                </template>
              </a-step>
              <a-step
                :title="$t('label.data.disk')"
                :status="zoneSelected ? 'process' : 'wait'"
                v-if="!template.deployasis && template.childtemplates && template.childtemplates.length > 0" >
                <template #description>
                  <div v-if="zoneSelected">
                    <multi-disk-selection
                      :items="template.childtemplates"
                      :diskOfferings="options.diskOfferings"
                      :zoneId="zoneId"
                      @select-multi-disk-offering="updateMultiDiskOffering($event)" />
                  </div>
                </template>
              </a-step>
              <a-step
                v-else
                :title="tabKey === 'templateid' ? $t('label.data.disk') : $t('label.disk.size')"
                :status="zoneSelected ? 'process' : 'wait'">
                <template #description>
                  <div v-if="zoneSelected">
                    <span>
                      {{ $t('label.data.disk') }}
                      <a-switch
                        v-model:checked="showDiskOfferingOption"
                        @change="updateDiskOffering(0)"
                        style="margin-left: 10px;"/>
                    </span>
                    <disk-offering-selection
                      v-if="showDiskOfferingOption"
                      :items="options.diskOfferings"
                      :row-count="rowCount.diskOfferings"
                      :zoneId="zoneId"
                      :value="diskOffering ? diskOffering.id : ''"
                      :loading="loading.diskOfferings"
                      :preFillContent="dataPreFill"
                      :isIsoSelected="tabKey==='isoid'"
                      @on-selected-disk-size="onSelectDiskSize"
                      @select-disk-offering-item="($event) => updateDiskOffering($event)"
                      @handle-search-filter="($event) => handleSearchFilter('diskOfferings', $event)"
                    ></disk-offering-selection>
                    <disk-size-selection
                      v-if="diskOffering && (diskOffering.iscustomized || diskOffering.iscustomizediops)"
                      input-decorator="size"
                      :preFillContent="dataPreFill"
                      :diskSelected="diskSelected"
                      :isCustomized="diskOffering.iscustomized"
                      @handler-error="handlerError"
                      @update-disk-size="updateFieldValue"
                      @update-iops-value="updateIOPSValue"/>
                    <a-form-item class="form-item-hidden">
                      <a-input v-model:value="form.size"/>
                    </a-form-item>
                  </div>
                </template>
              </a-step>
              <a-step
                :title="$t('label.select.network')"
                :status="zoneSelected ? 'process' : 'wait'"
                v-if="zone && zone.networktype !== 'Basic'">
                <template #description>
                  <label>{{ $t('message.autoscale.vm.networks') }}</label>
                  <div v-if="zoneSelected">
                    <div v-if="vm.templateid && templateNics && templateNics.length > 0">
                      <instance-nics-network-select-list-view
                        :nics="templateNics"
                        :zoneid="selectedZone"
                        @select="handleNicsNetworkSelection" />
                    </div>
                    <div v-show="!(vm.templateid && templateNics && templateNics.length > 0)" >
                      <network-selection
                        :items="options.networks"
                        :row-count="rowCount.networks"
                        :value="networkOfferingIds"
                        :loading="loading.networks"
                        :zoneId="zoneId"
                        :preFillContent="dataPreFill"
                        @select-network-item="($event) => updateNetworks($event)"
                        @handle-search-filter="($event) => handleSearchFilter('networks', $event)"
                      ></network-selection>
                      <network-configuration
                        v-if="networks.length > 0"
                        :items="networks"
                        :autoscale="true"
                        :preFillContent="dataPreFill"
                        @handler-error="($event) => hasError = $event"
                        @select-default-network-item="($event) => updateDefaultNetworks($event)"
                      ></network-configuration>
                    </div>
                  </div>
                </template>
              </a-step>
              <a-step
                :title="$t('label.loadbalancing')"
                :status="zoneSelected ? 'process' : 'wait'"
                v-if="networks.length > 0">
                <template #description>
                  <load-balancer-selection
                    :items="options.loadbalancers"
                    :zoneId="zoneId"
                    :loading="loading.networks"
                    :preFillContent="dataPreFill"
                    @select-load-balancer-item="($event) => updateLoadBalancers($event)"
                    @handle-search-filter="($event) => handleSearchFilter('loadbalancers', $event)"
                  ></load-balancer-selection>
                </template>
              </a-step>
              <a-step
                v-if="showSecurityGroupSection"
                :title="$t('label.security.groups')"
                :status="zoneSelected ? 'process' : 'wait'">
                <template #description>
                  <security-group-selection
                    :zoneId="zoneId"
                    :value="securitygroupids"
                    :loading="loading.networks"
                    :preFillContent="dataPreFill"
                    @select-security-group-item="($event) => updateSecurityGroups($event)"></security-group-selection>
                </template>
              </a-step>
              <a-step
                :title="$t('label.ovf.properties')"
                :status="zoneSelected ? 'process' : 'wait'"
                v-if="vm.templateid && templateProperties && Object.keys(templateProperties).length > 0">
                <template #description>
                  <div v-for="(props, category) in templateProperties" :key="category">
                    <a-alert :message="'Category: ' + category + ' (' + props.length + ' properties)'" type="info" />
                    <div style="margin-left: 15px; margin-top: 10px">
                      <a-form-item
                        v-for="(property, propertyIndex) in props"
                        :key="propertyIndex"
                        :v-bind="property.key"
                        :name="'properties.' + escapePropertyKey(property.key)"
                        :ref="'properties.' + escapePropertyKey(property.key)">
                        <tooltip-label style="text-transform: capitalize" :title="property.label" :tooltip="property.description"/>

                        <span v-if="property.type && property.type==='boolean'">
                          <a-switch
                            v-model:checked="form['properties.' + escapePropertyKey(property.key)]"
                            :placeholder="property.description"
                          />
                        </span>
                        <span v-else-if="property.type && (property.type==='int' || property.type==='real')">
                          <a-input-number
                            v-model:value="form['properties.'+ escapePropertyKey(property.key)]"
                            :placeholder="property.description"
                            :min="getPropertyQualifiers(property.qualifiers, 'number-select').min"
                            :max="getPropertyQualifiers(property.qualifiers, 'number-select').max" />
                        </span>
                        <span v-else-if="property.type && property.type==='string' && property.qualifiers && property.qualifiers.startsWith('ValueMap')">
                          <a-select
                            showSearch
                            optionFilterProp="value"
                            v-model:value="form['properties.' + escapePropertyKey(property.key)]"
                            :placeholder="property.description"
                            :filterOption="(input, option) => {
                              return option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
                            }"
                          >
                            <a-select-option v-for="opt in getPropertyQualifiers(property.qualifiers, 'select')" :key="opt">
                              {{ opt }}
                            </a-select-option>
                          </a-select>
                        </span>
                        <span v-else-if="property.type && property.type==='string' && property.password">
                          <a-input-password
                            v-model:value="form['properties.' + escapePropertyKey(property.key)]"
                            :placeholder="property.description" />
                        </span>
                        <span v-else>
                          <a-input
                            v-model:value="form['properties.' + escapePropertyKey(property.key)]"
                            :placeholder="property.description" />
                        </span>
                      </a-form-item>
                    </div>
                  </div>
                </template>
              </a-step>
              <a-step
                :title="$t('label.scaleup.policies')"
                :status="zoneSelected ? 'process' : 'wait'">
                <template #description>
                  <label>{{ $t('message.scaleup.policies') }}</label>
                  <a-divider/>
                  <div class="form">
                    <strong>{{ $t('label.scaleup.policy') }} &nbsp;&nbsp;&nbsp;</strong>
                    <a-select
                      style="width: 320px"
                      v-model:value="selectedScaleUpPolicyId"
                      @change="fetchScaleUpConditions()"
                      :placeholder="$t('label.scaleup.policy')"
                      showSearch
                      optionFilterProp="label"
                      :filterOption="(input, option) => {
                        return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                      }" >
                      <a-select-option
                        v-for="policy in this.scaleUpPolicies"
                        :key="policy.id"
                        :label="policy.name">
                        {{ policy.name }}
                      </a-select-option>
                    </a-select>
                    <a-button style="margin-left: 10px" ref="submit" type="primary" @click="addNewScaleUpPolicy">
                      <template #icon><plus-outlined /></template>
                      {{ $t('label.add.policy') }}
                    </a-button>
                    <a-button style="margin-left: 10px" ref="submit" type="primary" @click="removeScaleUpPolicy" :danger="true" >
                      <template #icon><delete-outlined /></template>
                      {{ $t('label.remove.policy') }}
                    </a-button>
                  </div>
                  <div class="form">
                    <a-form-item>
                      <template #label>
                        <span class="form__required">*</span>
                        <tooltip-label :title="$t('label.name')" :tooltip="createAutoScalePolicyApiParams.name.description"/>
                      </template>
                      <a-input v-model:value="selectedScaleUpPolicy.name"></a-input>
                      <span class="error-text">{{ $t('label.required') }}</span>
                    </a-form-item>
                    <a-form-item name="scaleupduration" ref="scaleupduration">
                      <template #label>
                        <span class="form__required">*</span>
                        <tooltip-label :title="$t('label.duration')" :tooltip="createAutoScalePolicyApiParams.duration.description"/>
                      </template>
                      <a-input v-model:value="selectedScaleUpPolicy.scaleupduration" type="number"></a-input>
                      <span class="error-text">{{ $t('label.required') }}</span>
                    </a-form-item>
                    <a-form-item name="scaleupquiettime" ref="scaleupquiettime">
                      <template #label>
                        <tooltip-label :title="$t('label.quiettime')" :tooltip="createAutoScalePolicyApiParams.quiettime.description"/>
                      </template>
                      <a-input v-model:value="selectedScaleUpPolicy.scaleupquiettime" type="number"></a-input>
                    </a-form-item>
                  </div>
                  <a-divider/>
                  <div class="form">
                    <div class="form__item" ref="newScaleUpConditionCounterId">
                      <div class="form__label">
                        <span class="form__required">*</span>
                        <tooltip-label :title="$t('label.counter')" :tooltip="$t('label.counter.name')"/>
                      </div>
                      <a-select
                        style="width: 100%"
                        showSearch
                        optionFilterProp="label"
                        :filterOption="(input, option) => {
                          return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                        }"
                        v-focus="true"
                        v-model:value="newScaleUpCondition.counterid">
                        <a-select-option
                          v-for="(counter, index) in countersList"
                          :value="counter.id"
                          :key="index"
                          :label="counter.name">
                          {{ counter.name }}
                        </a-select-option>
                      </a-select>
                      <span class="error-text">{{ $t('label.required') }}</span>
                    </div>
                    <div class="form__item" ref="newScaleUpConditionRelationalOperator">
                      <div class="form__label">
                        <span class="form__required">*</span>
                        <tooltip-label :title="$t('label.relationaloperator')" :tooltip="createConditionApiParams.relationaloperator.description"/>
                      </div>
                      <a-select
                        v-model:value="newScaleUpCondition.relationaloperator"
                        style="width: 100%;"
                        optionFilterProp="value"
                        :filterOption="(input, option) => {
                          return option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
                        }" >
                        <a-select-option value="GT">{{ getOperator('GT') }}</a-select-option>
                      </a-select>
                      <span class="error-text">{{ $t('label.required') }}</span>
                    </div>
                    <div class="form__item" ref="newScaleUpConditionThreshold">
                      <div class="form__label">
                        <span class="form__required">*</span>
                        <tooltip-label :title="$t('label.threshold')" :tooltip="$t('label.threshold.description')"/>
                      </div>
                      <a-input v-model:value="newScaleUpCondition.threshold" type="number"></a-input>
                      <span class="error-text">{{ $t('label.invalid.number') }}</span>
                    </div>
                    <div class="form__item">
                      <div class="form__label">{{ $t('label.action') }}</div>
                      <a-button ref="submit" type="primary" @click="addScaleUpCondition">
                        <template #icon><plus-outlined /></template>
                        {{ $t('label.add.condition') }}
                      </a-button>
                    </div>
                  </div>
                  <a-divider/>
                  <div>
                    <a-table
                      size="small"
                      style="overflow-y: auto"
                      :loading="false"
                      :columns="scaleUpColumns"
                      :dataSource="scaleUpConditions"
                      :pagination="false"
                      :rowKey="record => record.counterid">
                      <template #bodyCell="{ column, record }">
                        <template v-if="column.key === 'relationaloperator'">
                          {{ getOperator(record.relationaloperator) }}
                        </template>
                        <template v-if="column.key === 'actions'">
                          <a-button ref="submit" type="primary" :danger="true" @click="deleteScaleUpCondition(record.counterid)">
                            <template #icon><delete-outlined /></template>
                            {{ $t('label.delete') }}
                          </a-button>
                        </template>
                      </template>
                    </a-table>
                  </div>
                </template>
              </a-step>
              <a-step
                :title="$t('label.scaledown.policies')"
                :status="zoneSelected ? 'process' : 'wait'">
                <template #description>
                  <label>{{ $t('message.scaledown.policies') }}</label>
                  <a-divider/>
                  <div class="form">
                    <strong>{{ $t('label.scaledown.policy') }} &nbsp;&nbsp;&nbsp;</strong>
                    <a-select
                      style="width: 320px"
                      v-model:value="selectedScaleDownPolicyId"
                      @change="fetchScaleDownConditions()"
                      :placeholder="$t('label.scaledown.policy')"
                      showSearch
                      optionFilterProp="label"
                      :filterOption="(input, option) => {
                        return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                      }" >
                      <a-select-option
                        v-for="policy in this.scaleDownPolicies"
                        :key="policy.id"
                        :label="policy.name">
                        {{ policy.name }}
                      </a-select-option>
                    </a-select>
                    <a-button style="margin-left: 10px" ref="submit" type="primary" @click="addNewScaleDownPolicy">
                      <template #icon><plus-outlined /></template>
                      {{ $t('label.add.policy') }}
                    </a-button>
                    <a-button style="margin-left: 10px" ref="submit" type="primary" @click="removeScaleDownPolicy" :danger="true" >
                      <template #icon><delete-outlined /></template>
                      {{ $t('label.remove.policy') }}
                    </a-button>
                  </div>
                  <div class="form">
                    <a-form-item>
                      <template #label>
                        <span class="form__required">*</span>
                        <tooltip-label :title="$t('label.name')" :tooltip="createAutoScalePolicyApiParams.name.description"/>
                      </template>
                      <a-input v-model:value="selectedScaleDownPolicy.name"></a-input>
                      <span class="error-text">{{ $t('label.required') }}</span>
                    </a-form-item>
                    <a-form-item name="scaledownduration" ref="scaledownduration">
                      <template #label>
                        <span class="form__required">*</span>
                        <tooltip-label :title="$t('label.duration')" :tooltip="createAutoScalePolicyApiParams.duration.description"/>
                      </template>
                      <a-input v-model:value="selectedScaleDownPolicy.scaledownduration" type="number"></a-input>
                      <span class="error-text">{{ $t('label.required') }}</span>
                    </a-form-item>
                    <a-form-item name="scaledownquiettime" ref="scaledownquiettime">
                      <template #label>
                        <tooltip-label :title="$t('label.quiettime')" :tooltip="createAutoScalePolicyApiParams.quiettime.description"/>
                      </template>
                      <a-input v-model:value="selectedScaleDownPolicy.scaledownquiettime" type="number"></a-input>
                    </a-form-item>
                  </div>
                  <a-divider/>
                  <div class="form">
                    <div class="form__item" ref="newScaleDownConditionCounterId">
                      <div class="form__label">
                        <span class="form__required">*</span>
                        <tooltip-label :title="$t('label.counter')" :tooltip="$t('label.counter.name')"/>
                      </div>
                      <a-select
                        style="width: 100%"
                        showSearch
                        optionFilterProp="label"
                        :filterOption="(input, option) => {
                          return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                        }"
                        v-focus="true"
                        v-model:value="newScaleDownCondition.counterid">
                        <a-select-option
                          v-for="(counter, index) in countersList"
                          :value="counter.id"
                          :key="index"
                          :label="counter.name">
                          {{ counter.name }}
                        </a-select-option>
                      </a-select>
                      <span class="error-text">{{ $t('label.required') }}</span>
                    </div>
                    <div class="form__item" ref="newScaleDownConditionRelationalOperator">
                      <div class="form__label">
                        <span class="form__required">*</span>
                        <tooltip-label :title="$t('label.relationaloperator')" :tooltip="createConditionApiParams.relationaloperator.description"/>
                      </div>
                      <a-select
                        v-model:value="newScaleDownCondition.relationaloperator"
                        style="width: 100%;"
                        optionFilterProp="value"
                        :filterOption="(input, option) => {
                          return option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
                        }" >
                        <a-select-option value="LT">{{ getOperator('LT') }}</a-select-option>
                      </a-select>
                      <span class="error-text">{{ $t('label.required') }}</span>
                    </div>
                    <div class="form__item" ref="newScaleDownConditionThreshold">
                      <div class="form__label">
                        <span class="form__required">*</span>
                        <tooltip-label :title="$t('label.threshold')" :tooltip="$t('label.threshold.description')"/>
                      </div>
                      <a-input v-model:value="newScaleDownCondition.threshold" type="number"></a-input>
                      <span class="error-text">{{ $t('label.invalid.number') }}</span>
                    </div>
                    <div class="form__item">
                      <div class="form__label">{{ $t('label.action') }}</div>
                      <a-button ref="submit" type="primary" @click="addScaleDownCondition">
                        <template #icon><plus-outlined /></template>
                        {{ $t('label.add.condition') }}
                      </a-button>
                    </div>
                  </div>
                  <a-divider/>
                  <div style="display: block">
                    <a-table
                      size="small"
                      style="overflow-y: auto"
                      :loading="false"
                      :columns="scaleDownColumns"
                      :dataSource="scaleDownConditions"
                      :pagination="false"
                      :rowKey="record => record.counterid">
                      <template #bodyCell="{ column, record }">
                        <template v-if="column.key === 'relationaloperator'">
                          {{ getOperator(record.relationaloperator) }}
                        </template>
                        <template v-if="column.key === 'actions'">
                          <a-button ref="submit" type="primary" :danger="true" @click="deleteScaleDownCondition(record.counterid)">
                            <template #icon><delete-outlined /></template>
                            {{ $t('label.delete') }}
                          </a-button>
                        </template>
                      </template>
                    </a-table>
                  </div>
                </template>
              </a-step>
              <a-step
                :title="$t('label.advanced.mode')"
                :status="zoneSelected ? 'process' : 'wait'">
                <template #description v-if="zoneSelected">
                  <span>
                    {{ $t('label.isadvanced') }}
                    <a-switch v-model:checked="showDetails" style="margin-left: 10px"/>
                  </span>
                  <div style="margin-top: 15px" v-show="showDetails">
                    <a-form-item :label="$t('label.sshkeypairs')">
                      <ssh-key-pair-selection
                        :items="options.sshKeyPairs"
                        :row-count="rowCount.sshKeyPairs"
                        :zoneId="zoneId"
                        :value="sshKeyPairs"
                        :loading="loading.sshKeyPairs"
                        :preFillContent="dataPreFill"
                        @select-ssh-key-pair-item="($event) => updateSshKeyPairs($event)"
                        @handle-search-filter="($event) => handleSearchFilter('sshKeyPairs', $event)"
                      />
                    </a-form-item>
                    <a-form-item :label="$t('label.affinity.groups')">
                      <affinity-group-selection
                        :items="options.affinityGroups"
                        :row-count="rowCount.affinityGroups"
                        :zoneId="zoneId"
                        :value="affinityGroupIds"
                        :loading="loading.affinityGroups"
                        :preFillContent="dataPreFill"
                        @select-affinity-group-item="($event) => updateAffinityGroups($event)"
                        @handle-search-filter="($event) => handleSearchFilter('affinityGroups', $event)"/>
                    </a-form-item>
                    <a-form-item>
                      <template #label>
                        <tooltip-label :title="$t('label.userdata')" :tooltip="createAutoScaleVmProfileApiParams.userdata.description"/>
                      </template>
                      <a-card>
                        <div v-if="this.template && this.template.userdataid">
                          <a-text type="primary">
                            Userdata "{{ $t(this.template.userdataname) }}" is linked with template "{{ $t(this.template.name) }}" with override policy "{{ $t(this.template.userdatapolicy) }}"
                          </a-text><br/><br/>
                          <div v-if="templateUserDataParams.length > 0 && !doUserdataOverride">
                            <a-text type="primary" v-if="this.template && this.template.userdataid && templateUserDataParams.length > 0">
                              Enter the values for the variables in userdata
                            </a-text>
                            <a-input-group>
                              <a-table
                                size="small"
                                style="overflow-y: auto"
                                :columns="userDataParamCols"
                                :dataSource="templateUserDataParams"
                                :pagination="false"
                                :rowKey="record => record.key">
                                <template #value="{ record }">
                                  <a-input v-model:value="templateUserDataValues[record.key]" />
                                </template>
                              </a-table>
                            </a-input-group>
                          </div>
                        </div><br/><br/>
                        <div v-if="userdataDefaultOverridePolicy === 'ALLOWOVERRIDE' || userdataDefaultOverridePolicy === 'APPEND' || !userdataDefaultOverridePolicy">
                          <span v-if="userdataDefaultOverridePolicy === 'ALLOWOVERRIDE'" >
                            {{ $t('label.userdata.do.override') }}
                            <a-switch v-model:checked="doUserdataOverride" style="margin-left: 10px"/>
                          </span>
                          <span v-if="userdataDefaultOverridePolicy === 'APPEND'">
                            {{ $t('label.userdata.do.append') }}
                            <a-switch v-model:checked="doUserdataAppend" style="margin-left: 10px"/>
                          </span>
                          <a-step
                            :status="zoneSelected ? 'process' : 'wait'">
                            <template #description>
                              <div v-if="doUserdataOverride || doUserdataAppend || !userdataDefaultOverridePolicy" style="margin-top: 15px">
                                <a-card
                                  :tabList="userdataTabList"
                                  :activeTabKey="userdataTabKey"
                                  @tabChange="key => onUserdataTabChange(key, 'userdataTabKey')">
                                  <div v-if="userdataTabKey === 'userdataregistered'">
                                    <a-step
                                      v-if="isUserAllowedToListUserDatas"
                                      :status="zoneSelected ? 'process' : 'wait'">
                                      <template #description>
                                        <div v-if="zoneSelected">
                                          <user-data-selection
                                            :items="options.userDatas"
                                            :row-count="rowCount.userDatas"
                                            :zoneId="zoneId"
                                            :disabled="template.userdatapolicy === 'DENYOVERRIDE'"
                                            :loading="loading.userDatas"
                                            :preFillContent="dataPreFill"
                                            @select-user-data-item="($event) => updateUserData($event)"
                                            @handle-search-filter="($event) => handleSearchFilter('userData', $event)"
                                          />
                                          <div v-if="userDataParams.length > 0">
                                            <a-input-group>
                                              <a-table
                                                size="small"
                                                style="overflow-y: auto"
                                                :columns="userDataParamCols"
                                                :dataSource="userDataParams"
                                                :pagination="false"
                                                :rowKey="record => record.key">
                                                <template #value="{ record }">
                                                  <a-input v-model:value="userDataValues[record.key]" />
                                                </template>
                                              </a-table>
                                            </a-input-group>
                                          </div>
                                        </div>
                                      </template>
                                    </a-step>
                                  </div>
                                  <div v-else>
                                    <a-form-item name="userdata" ref="userdata" >
                                      <a-textarea
                                        placeholder="Userdata"
                                        v-model:value="form.userdata">
                                      </a-textarea>
                                    </a-form-item>
                                  </div>
                                </a-card>
                              </div>
                            </template>
                          </a-step>
                        </div>
                      </a-card>
                    </a-form-item>
                  </div>
                </template>
              </a-step>
              <a-step
                :title="$t('label.details')"
                :status="zoneSelected ? 'process' : 'wait'">
                <template #description v-if="zoneSelected">
                  <div style="margin-top: 15px">
                    <a-form-item name="name" ref="name">
                      <template #label>
                        <tooltip-label :title="$t('label.name')" :tooltip="createAutoScaleVmGroupApiParams.name.description"/>
                      </template>
                      <a-input v-model:value="form.name"></a-input>
                    </a-form-item>
                    <a-form-item name="autoscaleuserid" ref="autoscaleuserid" v-if="this.selectedLbProdiver === 'Netscaler'">
                      <template #label>
                        <tooltip-label :title="$t('label.user')" :tooltip="createAutoScaleVmProfileApiParams.autoscaleuserid.description"/>
                      </template>
                      <a-select
                        style="width: 100%"
                        showSearch
                        optionFilterProp="label"
                        :filterOption="(input, option) => {
                          return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                        }"
                        v-focus="true"
                        v-model:value="form.autoscaleuserid">
                        <a-select-option
                          v-for="(user, index) in usersList"
                          :value="user.id"
                          :key="index"
                          :label="user.username">
                          {{ user.username }}
                        </a-select-option>
                      </a-select>
                    </a-form-item>
                    <a-form-item name="expungevmgraceperiod" ref="expungevmgraceperiod">
                      <template #label>
                        <tooltip-label :title="$t('label.expungevmgraceperiod')" :tooltip="createAutoScaleVmProfileApiParams.expungevmgraceperiod.description"/>
                      </template>
                      <a-input v-model:value="form.expungevmgraceperiod" type="number"></a-input>
                    </a-form-item>
                    <a-form-item name="maxmembers" ref="maxmembers">
                      <template #label>
                        <tooltip-label :title="$t('label.maxmembers')" :tooltip="createAutoScaleVmGroupApiParams.maxmembers.description"/>
                      </template>
                      <a-input v-model:value="form.maxmembers" type="number"></a-input>
                    </a-form-item>
                    <a-form-item name="minmembers" ref="minmembers">
                      <template #label>
                        <tooltip-label :title="$t('label.minmembers')" :tooltip="createAutoScaleVmGroupApiParams.minmembers.description"/>
                      </template>
                      <a-input v-model:value="form.minmembers" type="number"></a-input>
                    </a-form-item>
                    <a-form-item name="interval" ref="interval">
                      <template #label>
                        <tooltip-label :title="$t('label.interval')" :tooltip="createAutoScaleVmGroupApiParams.interval.description"/>
                      </template>
                      <a-input v-model:value="form.interval" type="number"></a-input>
                    </a-form-item>
                  </div>
                </template>
              </a-step>
              <a-step
                :title="$t('label.license.agreements')"
                :status="zoneSelected ? 'process' : 'wait'"
                v-if="vm.templateid && templateLicenses && templateLicenses.length > 0">
                <template #description>
                  <div style="margin-top: 10px">
                    {{ $t('message.read.accept.license.agreements') }}
                    <a-form-item
                      style="margin-top: 10px"
                      v-for="(license, licenseIndex) in templateLicenses"
                      :key="licenseIndex"
                      :v-bind="license.id">
                      <template #label>
                        <tooltip-label style="text-transform: capitalize" :title="$t('label.agreement' + ' ' + (licenseIndex+1) + ': ' + license.name)"/>
                      </template>
                      <a-textarea
                        v-model:value="license.text"
                        :auto-size="{ minRows: 3, maxRows: 8 }"
                        readOnly />
                      <a-checkbox
                        style="margin-top: 10px"
                        v-model:checked="form.licensesaccepted">
                        {{ $t('label.i.accept.all.license.agreements') }}
                      </a-checkbox>
                    </a-form-item>
                  </div>
                </template>
              </a-step>
            </a-steps>
            <div class="card-footer">
              <!-- ToDo extract as component -->
              <a-button @click="() => $router.back()" :disabled="loading.deploy">
                {{ $t('label.cancel') }}
              </a-button>
              <a-button style="margin-left: 10px" type="primary" ref="submit" @click="handleSubmit" :loading="loading.deploy">
                {{ $t('label.create') }}
              </a-button>
            </div>
          </a-form>
        </a-card>
      </a-col>
      <a-col :md="24" :lg="7" v-if="!isMobile()">
        <a-affix :offsetTop="75" class="vm-info-card">
          <info-card :resource="vm" :title="$t('label.your.autoscale.vmgroup')" @change-resource="(data) => resource = data" />
        </a-affix>
      </a-col>
    </a-row>
  </div>
  <div>
    <a-modal
      :title="$t('message.creating.autoscale.vmgroup')"
      :visible="processStatusModalVisible"
      :afterClose="closeModal"
      :maskClosable="false"
      :closable="false"
      :footer="null"
      @cancel="processStatusModalVisible = false">

      <div class="form">
        <a-card class="ant-form-text card-launch-description">
          {{ $t('message.please.wait.while.autoscale.vmgroup.is.being.created') }}
        </a-card>
      </div>
      <div class="form">
        <a-card
          id="launch-content"
          class="ant-form-text card-launch-content">
          <a-steps
            size="small"
            direction="vertical"
            :current="currentStep"
          >
            <a-step
              v-for="(step, index) in steps"
              :key="index"
              :title="$t(step.title) + (step.detail ? ' (' + step.detail + ')' : '')"
              :status="step.status">
              <template #icon>
                <LoadingOutlined v-if="step.status===status.PROCESS" />
                <CloseCircleOutlined v-else-if="step.status===status.FAILED" />
              </template>
              <template #description>
                <a-card
                  class="step-error"
                  v-if="step.status===status.FAILED"
                >
                  <div><strong>{{ $t('label.error.something.went.wrong.please.correct.the.following') }}:</strong></div>
                  <div>{{ messageError }}</div>
                </a-card>
              </template>
            </a-step>
          </a-steps>
        </a-card>
      </div>
      <div class="form-action" v-if="processStatus">
        <a-button
          type="primary"
          @click="closeModal"
        >{{ $t('label.close') }}</a-button>
      </div>
    </a-modal>
  </div>
</template>

<script>
import { ref, reactive, toRaw } from 'vue'
import { api } from '@/api'
import _ from 'lodash'
import { mixin, mixinDevice } from '@/utils/mixin.js'
import store from '@/store'
import eventBus from '@/config/eventBus'

import InfoCard from '@/components/view/InfoCard'
import ResourceIcon from '@/components/view/ResourceIcon'
import ComputeOfferingSelection from '@views/compute/wizard/ComputeOfferingSelection'
import ComputeSelection from '@views/compute/wizard/ComputeSelection'
import DiskOfferingSelection from '@views/compute/wizard/DiskOfferingSelection'
import DiskSizeSelection from '@views/compute/wizard/DiskSizeSelection'
import MultiDiskSelection from '@views/compute/wizard/MultiDiskSelection'
import TemplateIsoSelection from '@views/compute/wizard/TemplateIsoSelection'
import AffinityGroupSelection from '@views/compute/wizard/AffinityGroupSelection'
import NetworkSelection from '@views/compute/wizard/NetworkSelection'
import NetworkConfiguration from '@views/compute/wizard/NetworkConfiguration'
import LoadBalancerSelection from '@views/compute/wizard/LoadBalancerSelection'
import SshKeyPairSelection from '@views/compute/wizard/SshKeyPairSelection'
import UserDataSelection from '@views/compute/wizard/UserDataSelection'
import SecurityGroupSelection from '@views/compute/wizard/SecurityGroupSelection'
import TooltipLabel from '@/components/widgets/TooltipLabel'
import InstanceNicsNetworkSelectListView from '@/components/view/InstanceNicsNetworkSelectListView.vue'

const STATUS_PROCESS = 'process'
const STATUS_FINISH = 'finish'
const STATUS_FAILED = 'error'

export default {
  name: 'Wizard',
  components: {
    SshKeyPairSelection,
    UserDataSelection,
    NetworkConfiguration,
    NetworkSelection,
    LoadBalancerSelection,
    AffinityGroupSelection,
    TemplateIsoSelection,
    DiskSizeSelection,
    MultiDiskSelection,
    DiskOfferingSelection,
    InfoCard,
    ComputeOfferingSelection,
    ComputeSelection,
    SecurityGroupSelection,
    ResourceIcon,
    TooltipLabel,
    InstanceNicsNetworkSelectListView
  },
  props: {
    visible: {
      type: Boolean
    },
    preFillContent: {
      type: Object,
      default: () => {}
    }
  },
  mixins: [mixin, mixinDevice],
  data () {
    return {
      steps: [],
      currentStep: 0,
      processStatus: null,
      messageError: '',
      processStatusModalVisible: false,
      status: {
        PROCESS: STATUS_PROCESS,
        FAILED: STATUS_FAILED,
        FINISH: STATUS_FINISH
      },
      naturalNumberRule: {
        type: 'number',
        validator: this.validateNumber
      },
      zoneId: '',
      zoneSelected: false,
      dynamicscalingenabled: true,
      templateKey: 0,
      showRegisteredUserdata: true,
      doUserdataOverride: false,
      doUserdataAppend: false,
      userdataDefaultOverridePolicy: 'ALLOWOVERRIDE',
      vm: {
        name: null,
        zoneid: null,
        zonename: null,
        templateid: null,
        templatename: null,
        serviceofferingid: null,
        serviceofferingname: null,
        ostypeid: null,
        ostypename: null,
        keypairs: [],
        affinitygroupids: [],
        affinitygroup: [],
        rootdisksize: null,
        disksize: null
      },
      options: {
        templates: {},
        serviceOfferings: [],
        diskOfferings: [],
        zones: [],
        affinityGroups: [],
        networks: [],
        sshKeyPairs: [],
        UserDatas: [],
        loadbalancers: []
      },
      rowCount: {},
      loading: {
        deploy: false,
        templates: false,
        serviceOfferings: false,
        diskOfferings: false,
        affinityGroups: false,
        networks: false,
        sshKeyPairs: false,
        userDatas: false,
        loadbalancers: false,
        zones: false
      },
      vmgroupConfig: {},
      template: {},
      templateConfigurations: [],
      templateNics: [],
      templateLicenses: [],
      templateProperties: {},
      selectedTemplateConfiguration: {},
      serviceOffering: {},
      diskOffering: {},
      affinityGroups: [],
      networks: [],
      networksAdd: [],
      selectedLbId: null,
      selectedLbProdiver: null,
      countersList: [],
      scaleUpPolicies: [],
      scaleUpCounter: 0,
      selectedScaleUpPolicy: null,
      selectedScaleUpPolicyId: null,
      scaleUpConditions: [],
      newScaleUpCondition: {
        counterid: null,
        relationaloperator: 'GT',
        threshold: null
      },
      scaleUpColumns: [
        {
          title: this.$t('label.counter'),
          dataIndex: 'countername'
        },
        {
          title: this.$t('label.relationaloperator'),
          key: 'relationaloperator'
        },
        {
          title: this.$t('label.threshold'),
          dataIndex: 'threshold'
        },
        {
          title: this.$t('label.actions'),
          key: 'actions'
        }
      ],
      scaleDownPolicies: [],
      scaleDownCounter: 0,
      selectedScaleDownPolicy: null,
      selectedScaleDownPolicyId: null,
      scaleDownConditions: [],
      newScaleDownCondition: {
        counterid: null,
        relationaloperator: 'LT',
        threshold: null
      },
      scaleDownColumns: [
        {
          title: this.$t('label.counter'),
          dataIndex: 'countername'
        },
        {
          title: this.$t('label.relationaloperator'),
          key: 'relationaloperator'
        },
        {
          title: this.$t('label.threshold'),
          dataIndex: 'threshold'
        },
        {
          title: this.$t('label.actions'),
          key: 'actions'
        }
      ],
      usersList: [],
      zone: {},
      sshKeyPairs: [],
      sshKeyPair: {},
      userData: {},
      userDataParams: [],
      userDataParamCols: [
        {
          title: this.$t('label.key'),
          dataIndex: 'key'
        },
        {
          title: this.$t('label.value'),
          dataIndex: 'value',
          slots: { customRender: 'value' }
        }
      ],
      userDataValues: {},
      templateUserDataCols: [
        {
          title: this.$t('label.userdata'),
          dataIndex: 'userdata'
        },
        {
          title: this.$t('label.userdatapolicy'),
          dataIndex: 'userdataoverridepolicy'
        }
      ],
      templateUserDataParams: [],
      templateUserDataValues: {},
      overrideDiskOffering: {},
      templateFilter: [
        'featured',
        'community',
        'selfexecutable',
        'sharedexecutable'
      ],
      initDataConfig: {},
      defaultNetworkId: '',
      dataNetworkCreated: [],
      tabKey: 'templateid',
      userdataTabKey: 'userdataregistered',
      dataPreFill: {},
      showDetails: false,
      showRootDiskSizeChanger: false,
      showOverrideDiskOfferingOption: false,
      showDiskOfferingOption: false,
      securitygroupids: [],
      rootDiskSizeFixed: 0,
      hasError: false,
      error: false,
      diskSelected: {},
      rootDiskSelected: {},
      diskIOpsMin: 0,
      diskIOpsMax: 0,
      minIops: 0,
      maxIops: 0,
      zones: [],
      selectedZone: '',
      formModel: {},
      nicToNetworkSelection: []
    }
  },
  computed: {
    rootDiskSize () {
      return this.showRootDiskSizeChanger && this.rootDiskSizeFixed > 0
    },
    isNormalAndDomainUser () {
      return ['DomainAdmin', 'User'].includes(this.$store.getters.userInfo.roletype)
    },
    diskSize () {
      const rootDiskSize = _.get(this.vmgroupConfig, 'rootdisksize', 0)
      const customDiskSize = _.get(this.vmgroupConfig, 'size', 0)
      const diskOfferingDiskSize = _.get(this.diskOffering, 'disksize', 0)
      const dataDiskSize = diskOfferingDiskSize > 0 ? diskOfferingDiskSize : customDiskSize
      const size = []
      if (rootDiskSize > 0) {
        size.push(`${rootDiskSize} GB (Root)`)
      }
      if (dataDiskSize > 0) {
        size.push(`${dataDiskSize} GB (Data)`)
      }
      return size.join(' | ')
    },
    affinityGroupIds () {
      return _.map(this.affinityGroups, 'id')
    },
    params () {
      return {
        serviceOfferings: {
          list: 'listServiceOfferings',
          options: {
            zoneid: _.get(this.zone, 'id'),
            issystem: false,
            page: 1,
            pageSize: 10,
            keyword: undefined
          }
        },
        diskOfferings: {
          list: 'listDiskOfferings',
          options: {
            zoneid: _.get(this.zone, 'id'),
            page: 1,
            pageSize: 10,
            keyword: undefined
          }
        },
        zones: {
          list: 'listZones',
          networktype: 'Advanced',
          isLoad: true,
          field: 'zoneid'
        },
        affinityGroups: {
          list: 'listAffinityGroups',
          options: {
            page: 1,
            pageSize: 10,
            keyword: undefined,
            listall: false
          }
        },
        sshKeyPairs: {
          list: 'listSSHKeyPairs',
          options: {
            page: 1,
            pageSize: 10,
            keyword: undefined,
            listall: false
          }
        },
        userDatas: {
          list: 'listUserData',
          options: {
            page: 1,
            pageSize: 10,
            keyword: undefined,
            listall: false
          }
        },
        networks: {
          list: 'listNetworks',
          options: {
            zoneid: _.get(this.zone, 'id'),
            canusefordeploy: true,
            projectid: store.getters.project ? store.getters.project.id : null,
            domainid: store.getters.project && store.getters.project.id ? null : store.getters.userInfo.domainid,
            account: store.getters.project && store.getters.project.id ? null : store.getters.userInfo.account,
            page: 1,
            pageSize: 10,
            keyword: undefined,
            showIcon: true
          }
        },
        loadbalancers: {
          list: 'listLoadBalancerRules',
          options: {
            zoneid: _.get(this.zone, 'id'),
            networkid: this.defaultNetworkId,
            id: this.lbRuleId,
            projectid: store.getters.project ? store.getters.project.id : null,
            domainid: store.getters.project && store.getters.project.id ? null : store.getters.userInfo.domainid,
            account: store.getters.project && store.getters.project.id ? null : store.getters.userInfo.account,
            page: 1,
            pageSize: 10,
            keyword: undefined,
            showIcon: true
          }
        }
      }
    },
    networkOfferingIds () {
      return _.map(this.networks, 'id')
    },
    zoneSelectOptions () {
      return this.options.zones.map((zone) => {
        return {
          label: zone.name,
          value: zone.id
        }
      })
    },
    templateConfigurationExists () {
      return this.vm.templateid && this.templateConfigurations && this.templateConfigurations.length > 0
    },
    templateId () {
      return this.$route.query.templateid || null
    },
    networkId () {
      return this.$route.query.networkid || null
    },
    lbRuleId () {
      return this.$route.query.lbruleid || null
    },
    tabList () {
      const tabList = [{
        key: 'templateid',
        tab: this.$t('label.templates')
      }]
      return tabList
    },
    userdataTabList () {
      let tabList = []
      tabList = [{
        key: 'userdataregistered',
        tab: this.$t('label.userdata.registered')
      },
      {
        key: 'userdatatext',
        tab: this.$t('label.userdata.text')
      }]
      return tabList
    },
    showSecurityGroupSection () {
      return (this.networks.length > 0 && this.zone.securitygroupsenabled) || (this.zone && this.zone.networktype === 'Basic')
    },
    isUserAllowedToListSshKeys () {
      return Boolean('listSSHKeyPairs' in this.$store.getters.apis)
    },
    isUserAllowedToListUserDatas () {
      return Boolean('listUserData' in this.$store.getters.apis)
    },
    dynamicScalingVmConfigValue () {
      return this.options.dynamicScalingVmConfig?.[0]?.value === 'true'
    },
    isCustomizedDiskIOPS () {
      return this.diskSelected?.iscustomizediops || false
    },
    isCustomizedIOPS () {
      return this.rootDiskSelected?.iscustomizediops || this.serviceOffering?.iscustomizediops || false
    }
  },
  watch: {
    '$route' (to, from) {
      if (to.name === 'createAutoScaleVmGroup') {
        this.resetData()
      }
    },
    formModel: {
      deep: true,
      handler (vmgroupConfig) {
        this.vmgroupConfig = toRaw(vmgroupConfig)
        Object.keys(vmgroupConfig).forEach(field => {
          this.vm[field] = this.vmgroupConfig[field]
        })
        this.template = ''
        for (const key in this.options.templates) {
          var template = _.find(_.get(this.options.templates[key], 'template', []), (option) => option.id === vmgroupConfig.templateid)
          if (template) {
            this.template = template
            break
          }
        }

        this.serviceOffering = _.find(this.options.serviceOfferings, (option) => option.id === vmgroupConfig.computeofferingid)
        if (this.serviceOffering?.diskofferingid) {
          vmgroupConfig.overridediskofferingid = this.serviceOffering.diskofferingid
        }
        if (this.diskSelected) {
          this.diskOffering = _.find(this.options.diskOfferings, (option) => option.id === vmgroupConfig.diskofferingid)
        }
        if (this.rootDiskSelected?.id) {
          vmgroupConfig.overridediskofferingid = this.rootDiskSelected.id
        }
        if (vmgroupConfig.overridediskofferingid) {
          this.overrideDiskOffering = _.find(this.options.diskOfferings, (option) => option.id === vmgroupConfig.overridediskofferingid)
        } else {
          this.overrideDiskOffering = null
        }

        this.zone = _.find(this.options.zones, (option) => option.id === vmgroupConfig.zoneid)
        this.networks = _.filter(this.options.networks, (option) => _.includes(vmgroupConfig.networkids, option.id))
        this.affinityGroups = _.filter(this.options.affinityGroups, (option) => _.includes(vmgroupConfig.affinitygroupids, option.id))
        this.sshKeyPair = _.find(this.options.sshKeyPairs, (option) => option.name === vmgroupConfig.keypair)

        if (this.zone) {
          this.vm.zoneid = this.zone.id
          this.vm.zonename = this.zone.name
        }

        if (this.serviceOffering?.rootdisksize) {
          this.vm.disksizetotalgb = this.serviceOffering.rootdisksize
        } else if (this.diskSize) {
          this.vm.disksizetotalgb = this.diskSize
        } else {
          this.vm.disksizetotalgb = null
        }

        if (this.diskSize) {
          this.vm.disksizetotalgb = this.diskSize
        }

        if (this.networks) {
          this.vm.networks = this.networks
        }

        if (this.selectedLbId) {
          this.loadbalancer = _.find(this.options.loadbalancers, (option) => option.id === this.selectedLbId)
          this.vm.loadbalancer = this.loadbalancer
        } else {
          this.vm.loadbalancer = null
        }

        if (this.template) {
          this.vm.templateid = this.template.id
          this.vm.templatename = this.template.displaytext
          this.vm.ostypeid = this.template.ostypeid
          this.vm.ostypename = this.template.ostypename
        }

        if (this.serviceOffering) {
          this.vm.serviceofferingid = this.serviceOffering.id
          this.vm.serviceofferingname = this.serviceOffering.displaytext
          if (this.serviceOffering.cpunumber) {
            this.vm.cpunumber = this.serviceOffering.cpunumber
          }
          if (this.serviceOffering.cpuspeed) {
            this.vm.cpuspeed = this.serviceOffering.cpuspeed
          }
          if (this.serviceOffering.memory) {
            this.vm.memory = this.serviceOffering.memory
          }
        }

        if (!this.template.deployasis && this.template.childtemplates && this.template.childtemplates.length > 0) {
          this.vm.diskofferingid = ''
          this.vm.diskofferingname = ''
          this.vm.diskofferingsize = ''
        } else if (this.diskOffering) {
          this.vm.diskofferingid = this.diskOffering.id
          this.vm.diskofferingname = this.diskOffering.displaytext
          this.vm.diskofferingsize = this.diskOffering.disksize
        }

        if (this.affinityGroups) {
          this.vm.affinitygroup = this.affinityGroups
        }

        if (this.sshKeyPairs && this.sshKeyPairs.length > 0) {
          this.vm.keypairs = this.sshKeyPairs
        }
      }
    }
  },
  serviceOffering (oldValue, newValue) {
    if (oldValue && newValue && oldValue.id !== newValue.id) {
      this.dynamicscalingenabled = this.isDynamicallyScalable()
    }
  },
  template (oldValue, newValue) {
    if (oldValue && newValue && oldValue.id !== newValue.id) {
      this.dynamicscalingenabled = this.isDynamicallyScalable()
      this.doUserdataOverride = false
      this.doUserdataAppend = false
    }
  },
  beforeCreate () {
    this.createConditionApi = this.$store.getters.apis.createCondition || {}
    this.createConditionApiParams = {}
    this.createConditionApi.params.forEach(param => {
      this.createConditionApiParams[param.name] = param
    })
    this.createAutoScalePolicyApi = this.$store.getters.apis.createAutoScalePolicy || {}
    this.createAutoScalePolicyApiParams = {}
    this.createAutoScalePolicyApi.params.forEach(param => {
      this.createAutoScalePolicyApiParams[param.name] = param
    })
    this.createAutoScaleVmGroupApi = this.$store.getters.apis.createAutoScaleVmGroup || {}
    this.createAutoScaleVmGroupApiParams = {}
    this.createAutoScaleVmGroupApi.params.forEach(param => {
      this.createAutoScaleVmGroupApiParams[param.name] = param
    })
    this.createAutoScaleVmProfileApi = this.$store.getters.apis.createAutoScaleVmProfile || {}
    this.createAutoScaleVmProfileApiParams = {}
    this.createAutoScaleVmProfileApi.params.forEach(param => {
      this.createAutoScaleVmProfileApiParams[param.name] = param
    })
  },
  created () {
    this.initForm()
    this.dataPreFill = this.preFillContent && Object.keys(this.preFillContent).length > 0 ? this.preFillContent : {}
    this.fetchData()
  },
  provide () {
    return {
      vmFetchTemplates: this.fetchAllTemplates,
      vmFetchNetworks: this.fetchNetwork,
      vmFetchLoadBalancers: this.fetchLoadBalancer
    }
  },
  methods: {
    addStep (title, step) {
      this.steps.push({
        index: this.currentStep,
        title,
        step,
        detail: '',
        status: STATUS_PROCESS
      })
      this.setStepStatus(STATUS_PROCESS)
    },
    addStepDetail (title, step, detail) {
      this.steps.push({
        index: this.currentStep,
        title,
        step,
        detail: detail,
        status: STATUS_PROCESS
      })
      this.setStepStatus(STATUS_PROCESS)
    },
    setStepStatus (status) {
      const index = this.steps.findIndex(step => step.index === this.currentStep)
      this.steps[index].status = status
    },
    updateTemplateKey () {
      this.templateKey += 1
    },
    initForm () {
      this.formRef = ref()
      this.form = reactive({})
      this.rules = reactive({
        zoneid: [
          { required: true, message: `${this.$t('message.error.select')}` }
        ],
        scaleupduration: [
          { required: false, message: this.$t('message.error.required.input') },
          this.naturalNumberRule
        ],
        scaleupquiettime: [
          { required: false, message: this.$t('message.error.required.input') },
          this.naturalNumberRule
        ],
        scaledownduration: [
          { required: false, message: this.$t('message.error.required.input') },
          this.naturalNumberRule
        ],
        scaledownquiettime: [
          { required: false, message: this.$t('message.error.required.input') },
          this.naturalNumberRule
        ],
        name: [
          { required: true, message: this.$t('message.error.required.input') }
        ],
        autoscaleuserid: [
          { required: true, message: `${this.$t('message.error.select')}` }
        ],
        expungevmgraceperiod: [
          { required: true, message: this.$t('message.error.required.input') },
          this.naturalNumberRule
        ],
        maxmembers: [
          { required: true, message: this.$t('message.error.required.input') },
          this.naturalNumberRule
        ],
        minmembers: [
          { required: true, message: this.$t('message.error.required.input') },
          this.naturalNumberRule
        ],
        interval: [
          { required: true, message: this.$t('message.error.required.input') },
          this.naturalNumberRule
        ]
      })

      this.addNewScaleUpPolicy()
      this.addNewScaleDownPolicy()

      if (this.zone && this.zone.networktype !== 'Basic') {
        if (this.zoneSelected && this.vm.templateid && this.templateNics && this.templateNics.length > 0) {
          this.templateNics.forEach((nic, nicIndex) => {
            this.form['networkMap.nic-' + nic.InstanceID.toString()] = this.options.networks && this.options.networks.length > 0
              ? this.options.networks[Math.min(nicIndex, this.options.networks.length - 1)].id
              : null
          })
        }

        if (this.vm.templateid && this.templateProperties && Object.keys(this.templateProperties).length > 0) {
          this.templateProperties.forEach((props, category) => {
            props.forEach((property, propertyIndex) => {
              if (property.type && property.type === 'boolean') {
                this.form['properties.' + this.escapePropertyKey(property.key)] = property.value === 'TRUE'
              } else if (property.type && (property.type === 'int' || property.type === 'real')) {
                this.form['properties.' + this.escapePropertyKey(property.key)] = property.value
              } else if (property.type && property.type === 'string' && property.qualifiers && property.qualifiers.startsWith('ValueMap')) {
                this.form['properties.' + this.escapePropertyKey(property.key)] = property.value && property.value.length > 0
                  ? property.value
                  : this.getPropertyQualifiers(property.qualifiers, 'select')[0]
              } else if (property.type && property.type === 'string' && property.password) {
                this.form['properties.' + this.escapePropertyKey(property.key)] = property.value
                this.rules['properties.' + this.escapePropertyKey(property.key)] = [{
                  validator: async (rule, value) => {
                    if (!property.qualifiers) {
                      return Promise.resolve()
                    }
                    var minlength = this.getPropertyQualifiers(property.qualifiers, 'number-select').min
                    var maxlength = this.getPropertyQualifiers(property.qualifiers, 'number-select').max
                    var errorMessage = ''
                    var isPasswordInvalidLength = function () {
                      return false
                    }
                    if (minlength) {
                      errorMessage = this.$t('message.validate.minlength').replace('{0}', minlength)
                      isPasswordInvalidLength = function () {
                        return !value || value.length < minlength
                      }
                    }
                    if (maxlength !== Number.MAX_SAFE_INTEGER) {
                      if (minlength) {
                        errorMessage = this.$t('message.validate.range.length').replace('{0}', minlength).replace('{1}', maxlength)
                        isPasswordInvalidLength = function () {
                          return !value || (maxlength < value.length || value.length < minlength)
                        }
                      } else {
                        errorMessage = this.$t('message.validate.maxlength').replace('{0}', maxlength)
                        isPasswordInvalidLength = function () {
                          return !value || value.length > maxlength
                        }
                      }
                    }
                    if (isPasswordInvalidLength()) {
                      return Promise.reject(errorMessage)
                    }
                    return Promise.resolve()
                  }
                }]
              } else {
                this.form['properties.' + this.escapePropertyKey(property.key)] = property.value
              }
            })
          })
        }

        if (this.vm.templateid && this.templateLicenses && this.templateLicenses.length > 0) {
          this.rules.licensesaccepted = [{
            validator: async (rule, value) => {
              if (!value) {
                return Promise.reject(this.$t('message.license.agreements.not.accepted'))
              }
              return Promise.resolve()
            }
          }]
        }
      }
    },
    getPropertyQualifiers (qualifiers, type) {
      var result = ''
      switch (type) {
        case 'select':
          result = []
          if (qualifiers && qualifiers.includes('ValueMap')) {
            result = qualifiers.replace('ValueMap', '').substr(1).slice(0, -1).split(',')
            for (var i = 0; i < result.length; i++) {
              result[i] = result[i].replace(/"/g, '')
            }
          }
          break
        case 'number-select':
          var min = 0
          var max = Number.MAX_SAFE_INTEGER
          if (qualifiers) {
            var match = qualifiers.match(/MinLen\((\d+)\)/)
            if (match) {
              min = parseInt(match[1])
            }
            match = qualifiers.match(/MaxLen\((\d+)\)/)
            if (match) {
              max = parseInt(match[1])
            }
          }
          result = { min: min, max: max }
          break
        default:
      }
      return result
    },
    fillValue (field) {
      this.form[field] = this.dataPreFill[field]
    },
    fetchZoneByQuery () {
      return new Promise(resolve => {
        let zones = []
        let apiName = ''
        const params = {}
        if (this.templateId) {
          apiName = 'listTemplates'
          params.listall = true
          params.templatefilter = this.isNormalAndDomainUser ? 'executable' : 'all'
          params.id = this.templateId
        } else if (this.networkId) {
          params.listall = true
          params.id = this.networkId
          apiName = 'listNetworks'
        } else if (this.lbRuleId) {
          params.listall = true
          params.id = this.lbRuleId
          apiName = 'listLoadBalancerRules'
        }
        if (!apiName) return resolve(zones)

        api(apiName, params).then(json => {
          let objectName
          const responseName = [apiName.toLowerCase(), 'response'].join('')
          for (const key in json[responseName]) {
            if (key === 'count') {
              continue
            }
            objectName = key
            break
          }
          const data = json?.[responseName]?.[objectName] || []
          zones = data.map(item => item.zoneid)
          return resolve(zones)
        }).catch(() => {
          return resolve(zones)
        })
      })
    },
    async fetchData () {
      const zones = await this.fetchZoneByQuery()
      if (zones && zones.length === 1) {
        this.selectedZone = zones[0]
        this.dataPreFill.zoneid = zones[0]
      }
      if (this.dataPreFill.zoneid) {
        this.fetchDataByZone(this.dataPreFill.zoneid)
      } else {
        this.fetchZones(null, zones)
        _.each(this.params, (param, name) => {
          if (param.isLoad) {
            this.fetchOptions(param, name)
          }
        })
      }
      this.fetchUserData()
    },
    isOfferingConstrained (serviceOffering) {
      return 'serviceofferingdetails' in serviceOffering && 'mincpunumber' in serviceOffering.serviceofferingdetails &&
        'maxmemory' in serviceOffering.serviceofferingdetails && 'maxcpunumber' in serviceOffering.serviceofferingdetails &&
        'minmemory' in serviceOffering.serviceofferingdetails
    },
    updateOverrideRootDiskShowParam (val) {
      if (val) {
        this.showRootDiskSizeChanger = false
      } else {
        this.rootDiskSelected = null
      }
      this.showOverrideDiskOfferingOption = val
    },
    async fetchDataByZone (zoneId) {
      this.fillValue('zoneid')
      this.options.zones = await this.fetchZones(zoneId)
      this.onSelectZoneId(zoneId)
    },
    fetchNetwork () {
      const param = this.params.networks
      this.fetchOptions(param, 'networks')
    },
    fetchLoadBalancer () {
      this.selectedLbId = null
      const param = this.params.loadbalancers
      this.fetchOptions(param, 'loadbalancers')
    },
    fetchCountersList () {
      api('listNetworks', {
        listAll: true,
        id: this.defaultNetworkId
      }).then(response => {
        const services = response.listnetworksresponse?.network?.[0]?.service
        const index = services.map(svc => { return svc.name }).indexOf('Lb')
        if (index === -1) {
          this.selectedLbProdiver = null
          this.countersList = []
          return
        }
        this.selectedLbProdiver = services[index].provider[0].name
        api('listCounters', {
          listAll: true,
          provider: this.selectedLbProdiver
        }).then(response => {
          this.countersList = response.counterresponse?.counter || []
        })
      })
    },
    fetchUserData () {
      api('listUsers', {
        domainid: store.getters.project && store.getters.project.id ? null : store.getters.userInfo.domainid,
        account: store.getters.project && store.getters.project.id ? null : store.getters.userInfo.account
      }).then(json => {
        this.usersList = json.listusersresponse?.user || []
      })
    },
    addNewScaleUpPolicy () {
      const newScaleUpPolicy = {
        id: this.scaleUpCounter,
        name: 'ScaleUpPolicy-' + this.scaleUpCounter,
        scaleupduration: null,
        scaleupquiettime: 300,
        conditions: []
      }
      this.scaleUpPolicies.push(newScaleUpPolicy)
      this.selectedScaleUpPolicyId = this.scaleUpCounter
      this.scaleUpCounter++
      this.fetchScaleUpConditions()
    },
    removeScaleUpPolicy () {
      if (this.scaleUpPolicies.length === 1) {
        return
      }
      this.scaleUpPolicies = this.scaleUpPolicies.filter(policy => policy.id !== this.selectedScaleUpPolicyId)
      this.selectedScaleUpPolicyId = this.scaleUpPolicies[this.scaleUpPolicies.length - 1].id
      this.fetchScaleUpConditions()
    },
    fetchScaleUpConditions () {
      this.selectedScaleUpPolicy = this.scaleUpPolicies.filter(policy => policy.id === this.selectedScaleUpPolicyId)[0]
      this.scaleUpConditions = this.selectedScaleUpPolicy.conditions
    },
    addNewScaleDownPolicy () {
      const newScaleDownPolicy = {
        id: this.scaleDownCounter,
        name: 'ScaleDownPolicy-' + this.scaleDownCounter,
        scaledownduration: null,
        scaledownquiettime: 300,
        conditions: []
      }
      this.scaleDownPolicies.push(newScaleDownPolicy)
      this.selectedScaleDownPolicyId = this.scaleDownCounter
      this.scaleDownCounter++
      this.fetchScaleDownConditions()
    },
    removeScaleDownPolicy () {
      if (this.scaleDownPolicies.length === 1) {
        return
      }
      this.scaleDownPolicies = this.scaleDownPolicies.filter(policy => policy.id !== this.selectedScaleDownPolicyId)
      this.selectedScaleDownPolicyId = this.scaleDownPolicies[this.scaleDownPolicies.length - 1].id
      this.fetchScaleDownConditions()
    },
    fetchScaleDownConditions () {
      this.selectedScaleDownPolicy = this.scaleDownPolicies.filter(policy => policy.id === this.selectedScaleDownPolicyId)[0]
      this.scaleDownConditions = this.selectedScaleDownPolicy.conditions
    },
    resetData () {
      this.vm = {
        name: null,
        zoneid: null,
        zonename: null,
        templateid: null,
        templatename: null,
        keypair: null,
        affinitygroupids: [],
        affinitygroup: [],
        serviceofferingid: null,
        serviceofferingname: null,
        ostypeid: null,
        ostypename: null,
        rootdisksize: null,
        disksize: null
      }
      this.zoneSelected = false
      this.formRef.value.resetFields()
      this.fetchData()
    },
    updateFieldValue (name, value) {
      if (name === 'templateid') {
        this.tabKey = 'templateid'
        this.form.templateid = value
        this.resetFromTemplateConfiguration()
        let template = ''
        for (const key in this.options.templates) {
          var t = _.find(_.get(this.options.templates[key], 'template', []), (option) => option.id === value)
          if (t) {
            this.template = t
            this.templateConfigurations = []
            this.selectedTemplateConfiguration = {}
            this.templateNics = []
            this.templateLicenses = []
            this.templateProperties = {}
            this.updateTemplateParameters()
            template = t
            break
          }
        }
        if (template) {
          var size = template.size / (1024 * 1024 * 1024) || 0 // bytes to GB
          this.dataPreFill.minrootdisksize = Math.ceil(size)
          this.updateTemplateLinkedUserData(this.template.userdataid)
          this.userdataDefaultOverridePolicy = this.template.userdatapolicy
        }
      } else if (['cpuspeed', 'cpunumber', 'memory'].includes(name)) {
        this.vm[name] = value
        this.form[name] = value
      } else {
        this.form[name] = value
      }
    },
    updateComputeOffering (id) {
      this.form.computeofferingid = id
      setTimeout(() => {
        this.updateTemplateConfigurationOfferingDetails(id)
      }, 500)
    },
    updateDiskOffering (id) {
      if (id === '0') {
        this.form.diskofferingid = undefined
        return
      }
      this.form.diskofferingid = id
    },
    updateOverrideDiskOffering (id) {
      if (id === '0') {
        this.form.overridediskofferingid = undefined
        return
      }
      this.form.overridediskofferingid = id
    },
    updateMultiDiskOffering (value) {
      this.form.multidiskoffering = value
    },
    updateNetworks (ids) {
      this.form.networkids = ids
    },
    updateDefaultNetworks (id) {
      this.defaultNetworkId = id
      this.fetchLoadBalancer()
      this.fetchCountersList()
    },
    escapePropertyKey (key) {
      return key.split('.').join('\\002E')
    },
    updateLoadBalancers (id) {
      if (id === '0') {
        this.form.loadbalancerid = undefined
        this.selectedLbId = null
      } else {
        this.form.loadbalancerid = id
        this.selectedLbId = id
      }
    },
    updateSecurityGroups (securitygroupids) {
      this.securitygroupids = securitygroupids || []
    },
    async validateNumber (rule, value) {
      if (value && (isNaN(value) || value <= 0)) {
        return Promise.reject(this.$t('message.error.number'))
      }
      return Promise.resolve()
    },
    isNumber (value) {
      if (value && (isNaN(value) || value < 0)) {
        return false
      }
      return true
    },
    getOperator (val) {
      if (val === 'GT' || val === 'gt') return this.$t('label.operator.greater')
      if (val === 'GE' || val === 'ge') return this.$t('label.operator.greater.or.equal')
      if (val === 'LT' || val === 'lt') return this.$t('label.operator.less')
      if (val === 'LE' || val === 'le') return this.$t('label.operator.less.or.equal')
      if (val === 'EQ' || val === 'eq') return this.$t('label.operator.equal')
      return val
    },
    addScaleUpCondition () {
      if (!this.newScaleUpCondition.counterid) {
        this.$refs.newScaleUpConditionCounterId.classList.add('error')
      } else {
        this.$refs.newScaleUpConditionCounterId.classList.remove('error')
      }

      if (!this.newScaleUpCondition.relationaloperator) {
        this.$refs.newScaleUpConditionRelationalOperator.classList.add('error')
      } else {
        this.$refs.newScaleUpConditionRelationalOperator.classList.remove('error')
      }

      if (!this.newScaleUpCondition.threshold || !this.isNumber(this.newScaleUpCondition.threshold)) {
        this.$refs.newScaleUpConditionThreshold.classList.add('error')
      } else {
        this.$refs.newScaleUpConditionThreshold.classList.remove('error')
      }

      if (!this.newScaleUpCondition.counterid || !this.newScaleUpCondition.relationaloperator || !this.newScaleUpCondition.threshold) {
        return
      }
      const countername = this.countersList.filter(counter => counter.id === this.newScaleUpCondition.counterid).map(counter => { return counter.name }).join(',')
      this.fetchScaleUpConditions()
      this.scaleUpConditions = this.scaleUpConditions.filter(condition => condition.counterid !== this.newScaleUpCondition.counterid)
      this.scaleUpConditions.push({
        counterid: this.newScaleUpCondition.counterid,
        countername: countername,
        relationaloperator: this.newScaleUpCondition.relationaloperator,
        threshold: this.newScaleUpCondition.threshold
      })
      this.selectedScaleUpPolicy.conditions = this.scaleUpConditions

      this.newScaleUpCondition = {
        counterid: null,
        relationaloperator: 'GT',
        threshold: null
      }
    },
    deleteScaleUpCondition (counterId) {
      this.scaleUpConditions = this.scaleUpConditions.filter(condition => condition.counterid !== counterId)
      this.selectedScaleUpPolicy.conditions = this.scaleUpConditions
    },
    addScaleDownCondition () {
      if (!this.newScaleDownCondition.counterid) {
        this.$refs.newScaleDownConditionCounterId.classList.add('error')
      } else {
        this.$refs.newScaleDownConditionCounterId.classList.remove('error')
      }

      if (!this.newScaleDownCondition.relationaloperator) {
        this.$refs.newScaleDownConditionRelationalOperator.classList.add('error')
      } else {
        this.$refs.newScaleDownConditionRelationalOperator.classList.remove('error')
      }

      if (!this.newScaleDownCondition.threshold || !this.isNumber(this.newScaleDownCondition.threshold)) {
        this.$refs.newScaleDownConditionThreshold.classList.add('error')
      } else {
        this.$refs.newScaleDownConditionThreshold.classList.remove('error')
      }

      if (!this.newScaleDownCondition.counterid || !this.newScaleDownCondition.relationaloperator || !this.newScaleDownCondition.threshold) {
        return
      }
      const countername = this.countersList.filter(counter => counter.id === this.newScaleDownCondition.counterid).map(counter => { return counter.name }).join(',')
      this.fetchScaleDownConditions()
      this.scaleDownConditions = this.scaleDownConditions.filter(condition => condition.counterid !== this.newScaleDownCondition.counterid)
      this.scaleDownConditions.push({
        counterid: this.newScaleDownCondition.counterid,
        countername: countername,
        relationaloperator: this.newScaleDownCondition.relationaloperator,
        threshold: this.newScaleDownCondition.threshold
      })
      this.selectedScaleDownPolicy.conditions = this.scaleDownConditions

      this.newScaleDownCondition = {
        counterid: null,
        relationaloperator: 'LT',
        threshold: null
      }
    },
    deleteScaleDownCondition (counterId) {
      this.scaleDownConditions = this.scaleDownConditions.filter(condition => condition.counterid !== counterId)
      this.selectedScaleDownPolicy.conditions = this.scaleDownConditions
    },
    updateSshKeyPairs (names) {
      this.form.keypairs = names
      this.sshKeyPairs = names.map((sshKeyPair) => { return sshKeyPair.name })
    },
    updateUserData (id) {
      if (id === '0') {
        this.form.userdataid = undefined
        return
      }
      this.form.userdataid = id
      this.userDataParams = []
      api('listUserData', { id: id }).then(json => {
        const resp = json?.listuserdataresponse?.userdata || []
        if (resp) {
          var params = resp[0].params
          if (params) {
            var dataParams = params.split(',')
          }
          var that = this
          dataParams.forEach(function (val, index) {
            that.userDataParams.push({
              id: index,
              key: val
            })
          })
        }
      })
    },
    updateTemplateLinkedUserData (id) {
      if (id === '0') {
        return
      }
      this.templateUserDataParams = []

      api('listUserData', { id: id }).then(json => {
        const resp = json?.listuserdataresponse?.userdata || []
        if (resp) {
          var params = resp[0].params
          if (params) {
            var dataParams = params.split(',')
          }
          var that = this
          that.templateUserDataParams = []
          if (dataParams) {
            dataParams.forEach(function (val, index) {
              that.templateUserDataParams.push({
                id: index,
                key: val
              })
            })
          }
        }
      })
    },
    updateAffinityGroups (ids) {
      this.form.affinitygroupids = ids
    },
    async pollJob (jobId) {
      return new Promise(resolve => {
        const asyncJobInterval = setInterval(() => {
          api('queryAsyncJobResult', { jobId }).then(async json => {
            const result = json.queryasyncjobresultresponse
            if (result.jobstatus === 0) {
              return
            }

            clearInterval(asyncJobInterval)
            resolve(result)
          })
        }, 1000)
      })
    },
    createVmProfile (createVmGroupData, createVmGroupUserDataDetails) {
      this.addStep('message.creating.autoscale.vmprofile', 'createVmProfile')

      return new Promise((resolve, reject) => {
        const params = {
          ...createVmGroupUserDataDetails,
          ...{
            expungevmgraceperiod: createVmGroupData.expungevmgraceperiod,
            serviceofferingid: createVmGroupData.serviceofferingid,
            templateid: createVmGroupData.templateid,
            userdata: createVmGroupData.userdata,
            userdataid: createVmGroupData.userdataid,
            zoneid: createVmGroupData.zoneid
          }
        }
        if (createVmGroupData.autoscaleuserid) {
          params.autoscaleuserid = createVmGroupData.autoscaleuserid
        }
        var i = 0
        if (createVmGroupData.snmpcommunity) {
          params['counterparam[' + i + '].name'] = 'snmpcommunity'
          params['counterparam[' + i + '].value'] = createVmGroupData.snmpcommunity
          i++
        }
        if (createVmGroupData.snmpport) {
          params['counterparam[' + i + '].name'] = 'snmpport'
          params['counterparam[' + i + '].value'] = createVmGroupData.snmpport
          i++
        }
        var j = 0
        if (createVmGroupData.rootdisksize) {
          params['otherdeployparams[' + j + '].name'] = 'rootdisksize'
          params['otherdeployparams[' + j + '].value'] = createVmGroupData.rootdisksize
          j++
        }
        if (createVmGroupData.overridediskofferingid) {
          params['otherdeployparams[' + j + '].name'] = 'overridediskofferingid'
          params['otherdeployparams[' + j + '].value'] = createVmGroupData.overridediskofferingid
          j++
        }
        if (createVmGroupData.diskofferingid) {
          params['otherdeployparams[' + j + '].name'] = 'diskofferingid'
          params['otherdeployparams[' + j + '].value'] = createVmGroupData.diskofferingid
          j++
        }
        if (createVmGroupData.size) {
          params['otherdeployparams[' + j + '].name'] = 'disksize'
          params['otherdeployparams[' + j + '].value'] = createVmGroupData.size
          j++
        }
        if (createVmGroupData.securitygroupids) {
          params['otherdeployparams[' + j + '].name'] = 'securitygroupids'
          params['otherdeployparams[' + j + '].value'] = createVmGroupData.securitygroupids
          j++
        }
        if (createVmGroupData.keypairs) {
          params['otherdeployparams[' + j + '].name'] = 'keypairs'
          params['otherdeployparams[' + j + '].value'] = createVmGroupData.keypairs
          j++
        }
        if (createVmGroupData.affinitygroupids) {
          params['otherdeployparams[' + j + '].name'] = 'affinitygroupids'
          params['otherdeployparams[' + j + '].value'] = createVmGroupData.affinitygroupids
          j++
        }
        if (createVmGroupData.networkids) {
          params['otherdeployparams[' + j + '].name'] = 'networkids'
          params['otherdeployparams[' + j + '].value'] = createVmGroupData.networkids
          j++
        }

        const httpMethod = createVmGroupData.userdata ? 'POST' : 'GET'
        const args = httpMethod === 'POST' ? {} : params
        const data = httpMethod === 'POST' ? params : {}

        api('createAutoScaleVmProfile', args, httpMethod, data).then(async json => {
          const jobId = json.autoscalevmprofileresponse.jobid
          if (jobId) {
            const result = await this.pollJob(jobId)
            if (result.jobstatus === 2) {
              this.messageError = result.jobresult.errortext
              this.processStatus = STATUS_FAILED
              this.setStepStatus(STATUS_FAILED)
              return
            }
            resolve(result.jobresult.autoscalevmprofile)
          }
        }).catch(error => {
          this.messageError = error.response.headers['x-description']
          this.processStatus = STATUS_FAILED
          this.setStepStatus(STATUS_FAILED)
        })
      })
    },
    createCondition (counterid, relationaloperator, threshold) {
      return new Promise((resolve, reject) => {
        const params = {
          counterid: counterid,
          relationaloperator: relationaloperator,
          threshold: threshold
        }
        api('createCondition', params).then(async json => {
          const jobId = json.conditionresponse.jobid
          if (jobId) {
            const result = await this.pollJob(jobId)
            if (result.jobstatus === 2) {
              this.messageError = result.jobresult.errortext
              this.processStatus = STATUS_FAILED
              this.setStepStatus(STATUS_FAILED)
              return
            }
            resolve(result.jobresult.condition)
          }
        }).catch(error => {
          this.messageError = error.response.headers['x-description']
          this.processStatus = STATUS_FAILED
          this.setStepStatus(STATUS_FAILED)
        })
      })
    },
    createScalePolicy (action, name, conditionIds, duration, quiettime) {
      return new Promise((resolve, reject) => {
        const params = {
          name: name,
          action: action,
          duration: duration,
          quiettime: quiettime,
          conditionids: conditionIds
        }
        api('createAutoScalePolicy', params).then(async json => {
          const jobId = json.autoscalepolicyresponse.jobid
          if (jobId) {
            const result = await this.pollJob(jobId)
            if (result.jobstatus === 2) {
              this.messageError = result.jobresult.errortext
              this.processStatus = STATUS_FAILED
              this.setStepStatus(STATUS_FAILED)
              return
            }
            resolve(result.jobresult.autoscalepolicy)
          }
        }).catch(error => {
          this.messageError = error.response.headers['x-description']
          this.processStatus = STATUS_FAILED
          this.setStepStatus(STATUS_FAILED)
        })
      })
    },
    getText (option) {
      return _.get(option, 'displaytext', _.get(option, 'name'))
    },
    async handleSubmit (e) {
      console.log('wizard submit')
      e.preventDefault()
      if (this.loading.deploy) return
      this.formRef.value.validate().then(async () => {
        const values = toRaw(this.form)

        if (!values.templateid) {
          this.$notification.error({
            message: this.$t('message.request.failed'),
            description: this.$t('message.template.iso')
          })
          return
        }
        if (!values.computeofferingid) {
          this.$notification.error({
            message: this.$t('message.request.failed'),
            description: this.$t('message.step.2.continue')
          })
          return
        }

        if (!this.defaultNetworkId) {
          this.$notification.error({
            message: this.$t('message.request.failed'),
            description: this.$t('message.error.select.network')
          })
          return
        }

        const defaultNetwork = this.networks.filter(network => network.id === this.defaultNetworkId)[0]
        if (defaultNetwork.supportsvmautoscaling !== true) {
          this.$notification.error({
            message: this.$t('message.request.failed'),
            description: this.$t('message.error.select.network.supports.vm.autoscaling')
          })
          return
        }

        if (!values.loadbalancerid) {
          this.$notification.error({
            message: this.$t('message.request.failed'),
            description: this.$t('message.error.select.load.balancer')
          })
          return
        }

        if (this.error) {
          this.$notification.error({
            message: this.$t('message.request.failed'),
            description: this.$t('error.form.message')
          })
          return
        }

        const regex = /^([a-zA-Z0-9-]){0,255}$/
        if (!values.name || values.name.length === 0 || !regex.test(values.name)) {
          this.$notification.error({
            message: this.$t('message.request.failed'),
            description: this.$t('message.error.invalid.autoscale.vmgroup.name')
          })
          return
        }

        if (this.scaleUpPolicies.length === 0) {
          this.$notification.error({
            message: this.$t('message.request.failed'),
            description: this.$t('message.scaleup.policy.continue')
          })
          return
        }
        for (const policy of this.scaleUpPolicies) {
          if (!policy.name || policy.name.length === 0) {
            this.$notification.error({
              message: this.$t('message.request.failed'),
              description: this.$t('message.scaleup.policy.name.continue')
            })
            return
          }
          if (!policy.scaleupduration || parseInt(policy.scaleupduration) <= 0) {
            this.$notification.error({
              message: this.$t('message.request.failed'),
              description: this.$t('message.scaleup.policy.duration.continue')
            })
            return
          }
          if (policy.conditions.length === 0) {
            this.$notification.error({
              message: this.$t('message.request.failed'),
              description: this.$t('message.scaleup.policy.continue')
            })
            return
          }
          if (parseInt(policy.scaleupduration) < parseInt(values.interval)) {
            this.$notification.error({
              message: this.$t('message.request.failed'),
              description: this.$t('message.error.duration.less.than.interval')
            })
            return
          }
        }

        if (this.scaleDownPolicies.length === 0) {
          this.$notification.error({
            message: this.$t('message.request.failed'),
            description: this.$t('message.scaledown.policy.continue')
          })
          return
        }
        for (const policy of this.scaleDownPolicies) {
          if (!policy.name || policy.name.length === 0) {
            this.$notification.error({
              message: this.$t('message.request.failed'),
              description: this.$t('message.scaledown.policy.name.continue')
            })
            return
          }
          if (!policy.scaledownduration || parseInt(policy.scaledownduration) <= 0) {
            this.$notification.error({
              message: this.$t('message.request.failed'),
              description: this.$t('message.scaledown.policy.duration.continue')
            })
            return
          }
          if (policy.conditions.length === 0) {
            this.$notification.error({
              message: this.$t('message.request.failed'),
              description: this.$t('message.scaledown.policy.continue')
            })
            return
          }
          if (parseInt(policy.scaledownduration) < parseInt(values.interval)) {
            this.$notification.error({
              message: this.$t('message.request.failed'),
              description: this.$t('message.error.duration.less.than.interval')
            })
            return
          }
        }

        if (parseInt(values.maxmembers) < parseInt(values.minmembers)) {
          this.$notification.error({
            message: this.$t('message.request.failed'),
            description: this.$t('message.error.max.members.less.than.min.members')
          })
          return
        }

        this.loading.deploy = true

        let networkIds = []

        let createVmGroupData = {}
        // step 1 : select zone
        createVmGroupData.zoneid = values.zoneid
        // step 2: select template/iso
        createVmGroupData.templateid = values.templateid

        if (this.showRootDiskSizeChanger && values.rootdisksize && values.rootdisksize > 0) {
          createVmGroupData.rootdisksize = values.rootdisksize
        } else if (this.rootDiskSizeFixed > 0 && !this.template.deployasis) {
          createVmGroupData.rootdisksize = this.rootDiskSizeFixed
        }

        // step 3: select service offering
        createVmGroupData.serviceofferingid = values.computeofferingid
        if (this.serviceOffering && this.serviceOffering.iscustomized) {
          if (values.cpunumber) {
            createVmGroupData['details[0].cpuNumber'] = values.cpunumber
          }
          if (values.cpuspeed) {
            createVmGroupData['details[0].cpuSpeed'] = values.cpuspeed
          }
          if (values.memory) {
            createVmGroupData['details[0].memory'] = values.memory
          }
        }
        if (this.selectedTemplateConfiguration) {
          createVmGroupData['details[0].configurationId'] = this.selectedTemplateConfiguration.id
        }
        if (!this.serviceOffering.diskofferingstrictness && values.overridediskofferingid) {
          createVmGroupData.overridediskofferingid = values.overridediskofferingid
          if (values.rootdisksize && values.rootdisksize > 0) {
            createVmGroupData.rootdisksize = values.rootdisksize
          }
        }
        if (this.isCustomizedIOPS) {
          createVmGroupData['details[0].minIops'] = this.minIops
          createVmGroupData['details[0].maxIops'] = this.maxIops
        }
        // step 4: select disk offering
        if (!this.template.deployasis && this.template.childtemplates && this.template.childtemplates.length > 0) {
          if (values.multidiskoffering) {
            let i = 0
            Object.entries(values.multidiskoffering).forEach(([disk, offering]) => {
              const diskKey = `datadiskofferinglist[${i}].datadisktemplateid`
              const offeringKey = `datadiskofferinglist[${i}].diskofferingid`
              createVmGroupData[diskKey] = disk
              createVmGroupData[offeringKey] = offering
              i++
            })
          }
        } else {
          createVmGroupData.diskofferingid = values.diskofferingid
          if (values.size) {
            createVmGroupData.size = values.size
          }
        }
        if (this.isCustomizedDiskIOPS) {
          createVmGroupData['details[0].minIopsDo'] = this.diskIOpsMin
          createVmGroupData['details[0].maxIopsDo'] = this.diskIOpsMax
        }

        // step 6: select network
        if (this.zone.networktype !== 'Basic') {
          if (this.nicToNetworkSelection && this.nicToNetworkSelection.length > 0) {
            for (var j in this.nicToNetworkSelection) {
              var nicNetwork = this.nicToNetworkSelection[j]
              createVmGroupData['nicnetworklist[' + j + '].nic'] = nicNetwork.nic
              createVmGroupData['nicnetworklist[' + j + '].network'] = nicNetwork.network
            }
          } else {
            networkIds = values.networkids
            if (networkIds.length > 0) {
              createVmGroupData.networkids = values.networkids.join(',')
            } else {
              this.$notification.error({
                message: this.$t('message.request.failed'),
                description: this.$t('message.step.4.continue')
              })
              this.loading.deploy = false
              return
            }
          }
        }

        if (this.securitygroupids.length > 0) {
          createVmGroupData.securitygroupids = this.securitygroupids.join(',')
        }

        // advanced settings
        createVmGroupData.keypairs = this.sshKeyPairs.join(',')
        createVmGroupData.affinitygroupids = (values.affinitygroupids || []).join(',')
        const isUserdataAllowed = !this.userdataDefaultOverridePolicy || (this.userdataDefaultOverridePolicy === 'ALLOWOVERRIDE' && this.doUserdataOverride) || (this.userdataDefaultOverridePolicy === 'APPEND' && this.doUserdataAppend)
        if (isUserdataAllowed && values.userdata && values.userdata.length > 0) {
          createVmGroupData.userdata = this.$toBase64AndURIEncoded(values.userdata)
        }
        if (isUserdataAllowed) {
          createVmGroupData.userdataid = values.userdataid
        }

        // vm profile details
        createVmGroupData.autoscaleuserid = values.autoscaleuserid
        createVmGroupData.expungevmgraceperiod = values.expungevmgraceperiod

        createVmGroupData = Object.fromEntries(
          Object.entries(createVmGroupData).filter(([key, value]) => value !== undefined))

        const createVmGroupUserDataDetails = {}
        var idx = 0
        if (this.templateUserDataValues) {
          for (const [key, value] of Object.entries(this.templateUserDataValues)) {
            createVmGroupUserDataDetails['userdatadetails[' + idx + '].' + `${key}`] = value
            idx++
          }
        }
        if (isUserdataAllowed && this.userDataValues) {
          for (const [key, value] of Object.entries(this.userDataValues)) {
            createVmGroupUserDataDetails['userdatadetails[' + idx + '].' + `${key}`] = value
            idx++
          }
        }

        this.processStatusModalVisible = true
        this.processStatus = null

        // create autoscale vm profile
        const vmprofile = await this.createVmProfile(createVmGroupData, createVmGroupUserDataDetails)

        // create scaleup conditions and policy
        const scaleUpPolicyIds = []
        for (const policy of this.scaleUpPolicies) {
          this.setStepStatus(STATUS_FINISH)
          this.currentStep++
          this.addStepDetail('message.creating.autoscale.scaleup.conditions', 'createScaleUpConditions', policy.name)
          var scaleUpConditionIds = []
          for (const condition of policy.conditions) {
            const newCondition = await this.createCondition(condition.counterid, condition.relationaloperator, condition.threshold)
            scaleUpConditionIds.push(newCondition.id)
          }
          this.setStepStatus(STATUS_FINISH)
          this.currentStep++
          this.addStepDetail('message.creating.autoscale.scaleup.policy', 'createScaleUpPolicy', policy.name)
          const scaleUpPolicy = await this.createScalePolicy('ScaleUp', policy.name, scaleUpConditionIds.join(','), policy.scaleupduration, policy.scaleupquiettime)
          scaleUpPolicyIds.push(scaleUpPolicy.id)
        }

        // create scaledown conditions and policy
        const scaleDownPolicyIds = []
        for (const policy of this.scaleDownPolicies) {
          this.setStepStatus(STATUS_FINISH)
          this.currentStep++
          this.addStepDetail('message.creating.autoscale.scaledown.conditions', 'createScaleDownConditions', policy.name)
          var scaleDownConditionIds = []
          for (const condition of policy.conditions) {
            const newCondition = await this.createCondition(condition.counterid, condition.relationaloperator, condition.threshold)
            scaleDownConditionIds.push(newCondition.id)
          }
          this.setStepStatus(STATUS_FINISH)
          this.currentStep++
          this.addStepDetail('message.creating.autoscale.scaledown.policy', 'createScaleDownPolicy', policy.name)
          const scaleDownPolicy = await this.createScalePolicy('ScaleDown', policy.name, scaleDownConditionIds.join(','), policy.scaledownduration, policy.scaledownquiettime)
          scaleDownPolicyIds.push(scaleDownPolicy.id)
        }

        this.setStepStatus(STATUS_FINISH)
        this.currentStep++
        this.addStep('message.creating.autoscale.vmgroup', 'createVmGroup')

        // create autoscale vmgroup
        const params = {
          vmprofileid: vmprofile.id,
          scaleuppolicyids: scaleUpPolicyIds.join(','),
          scaledownpolicyids: scaleDownPolicyIds.join(','),
          lbruleid: values.loadbalancerid,
          name: values.name,
          maxmembers: values.maxmembers,
          minmembers: values.minmembers,
          interval: values.interval
        }
        api('createAutoScaleVmGroup', params).then(async response => {
          const jobId = response.autoscalevmgroupresponse.jobid
          const result = await this.pollJob(jobId)
          if (result.jobstatus === 2) {
            this.messageError = result.jobresult.errortext
            this.processStatus = STATUS_FAILED
            this.setStepStatus(STATUS_FAILED)
            return
          } else {
            this.setStepStatus(STATUS_FINISH)
            const vmgroup = result.jobresult.autoscalevmgroup
            this.$notification.success({
              message: this.$t('label.new.autoscale.vmgroup'),
              description: vmgroup.name,
              duration: 0
            })
            eventBus.emit('vm-refresh-data')
          }
          // Back to previous page
          this.processStatusModalVisible = false
          this.$router.back()
        }).catch(error => {
          this.messageError = error.response.headers['x-description']
          this.processStatus = STATUS_FAILED
          this.setStepStatus(STATUS_FAILED)
          this.loading.deploy = false
        }).finally(() => {
          this.loading.deploy = false
        })
      }).catch(err => {
        if (err) {
          if (err.errorFields) {
            this.formRef.value.scrollToField(err.errorFields[0].name)
          }
          if (err.licensesaccepted) {
            this.$notification.error({
              message: this.$t('message.license.agreements.not.accepted'),
              description: this.$t('message.step.license.agreements.continue')
            })
            return
          }

          this.$notification.error({
            message: this.$t('message.request.failed'),
            description: this.$t('error.form.message')
          })
        }
      })
    },
    fetchZones (zoneId, listZoneAllow) {
      this.zones = []
      return new Promise((resolve) => {
        this.loading.zones = true
        const param = this.params.zones
        const args = { showicon: true }
        if (zoneId) args.id = zoneId
        api(param.list, args).then(json => {
          const zoneResponse = (json.listzonesresponse.zone || []).filter(item => item.securitygroupsenabled === false)
          if (listZoneAllow && listZoneAllow.length > 0) {
            zoneResponse.map(zone => {
              if (listZoneAllow.includes(zone.id)) {
                this.zones.push(zone)
              }
            })
          } else {
            this.zones = zoneResponse
          }

          resolve(this.zones)
        }).catch(function (error) {
          console.log(error.stack)
        }).finally(() => {
          this.loading.zones = false
        })
      })
    },
    fetchOptions (param, name, exclude) {
      if (exclude && exclude.length > 0) {
        if (exclude.includes(name)) {
          return
        }
      }
      this.loading[name] = true
      param.loading = true
      param.opts = []
      const options = param.options || {}
      if (!('listall' in options) && !['zones', 'pods', 'clusters', 'hosts', 'dynamicScalingVmConfig', 'hypervisors'].includes(name)) {
        options.listall = true
      }
      api(param.list, options).then((response) => {
        param.loading = false
        _.map(response, (responseItem, responseKey) => {
          if (Object.keys(responseItem).length === 0) {
            this.rowCount[name] = 0
            this.options[name] = []
            return
          }
          if (!responseKey.includes('response')) {
            return
          }
          _.map(responseItem, (response, key) => {
            if (key === 'count') {
              this.rowCount[name] = response
              return
            }
            param.opts = response
            this.options[name] = response

            if (param.field) {
              this.fillValue(param.field)
            }
          })

          if (name === 'zones') {
            let zoneid = ''
            if (this.$route.query.zoneid) {
              zoneid = this.$route.query.zoneid
            } else if (this.options.zones.length === 1) {
              zoneid = this.options.zones[0].id
            }
            if (zoneid) {
              this.form.zoneid = zoneid
              this.onSelectZoneId(zoneid)
            }
          }
        })
      }).catch(function (error) {
        console.log(error.stack)
        param.loading = false
      }).finally(() => {
        this.loading[name] = false
      })
    },
    fetchTemplates (templateFilter, params) {
      const args = Object.assign({}, params)
      if (args.keyword || args.category !== templateFilter) {
        args.page = 1
        args.pageSize = args.pageSize || 10
      }
      args.zoneid = _.get(this.zone, 'id')
      args.templatefilter = templateFilter
      args.details = 'all'
      args.showicon = 'true'

      return new Promise((resolve, reject) => {
        api('listTemplates', args).then((response) => {
          resolve(response)
        }).catch((reason) => {
          // ToDo: Handle errors
          reject(reason)
        })
      })
    },
    fetchAllTemplates (params) {
      const promises = []
      const templates = {}
      this.loading.templates = true
      this.templateFilter.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[this.templateFilter[idx]] = _.isEmpty(resItem.listtemplatesresponse) ? { count: 0, template: [] } : resItem.listtemplatesresponse
          this.options.templates = { ...templates }
        })
      }).catch((reason) => {
        console.log(reason)
      }).finally(() => {
        this.loading.templates = false
      })
    },
    filterOption (input, option) {
      return option.label.toUpperCase().indexOf(input.toUpperCase()) >= 0
    },
    onSelectZoneId (value) {
      this.dataPreFill = {}
      this.zoneId = value
      this.zone = _.find(this.options.zones, (option) => option.id === value)
      this.zoneSelected = true
      this.selectedZone = this.zoneId
      this.form.zoneid = this.zoneId
      this.form.templateid = undefined
      this.tabKey = 'templateid'
      _.each(this.params, (param, name) => {
        if (this.networkId && name === 'networks') {
          param.options = {
            id: this.networkId
          }
        }
        if (this.lbRuleId && name === 'loadbalancers') {
          param.options = {
            id: this.lbRuleId
          }
        }
        if (!('isLoad' in param) || param.isLoad) {
          this.fetchOptions(param, name, ['zones'])
        }
      })
      if (this.tabKey === 'templateid') {
        this.fetchAllTemplates()
      }
      this.updateTemplateKey()
      this.formModel = toRaw(this.form)
    },
    handleSearchFilter (name, options) {
      this.params[name].options = { ...this.params[name].options, ...options }
      this.fetchOptions(this.params[name], name)
    },
    onUserdataTabChange (key, type) {
      this[type] = key
      this.userDataParams = []
    },
    fetchTemplateNics (template) {
      var nics = []
      this.nicToNetworkSelection = []
      if (template && template.deployasisdetails && Object.keys(template.deployasisdetails).length > 0) {
        var keys = Object.keys(template.deployasisdetails)
        keys = keys.filter(key => key.startsWith('network-'))
        for (var key of keys) {
          var propertyMap = JSON.parse(template.deployasisdetails[key])
          nics.push(propertyMap)
        }
        nics.sort(function (a, b) {
          return a.InstanceID - b.InstanceID
        })
        if (this.options.networks && this.options.networks.length > 0) {
          for (var i = 0; i < nics.length; ++i) {
            var nic = nics[i]
            nic.id = nic.InstanceID
            var network = this.options.networks[Math.min(i, this.options.networks.length - 1)]
            nic.selectednetworkid = network.id
            nic.selectednetworkname = network.name
            this.nicToNetworkSelection.push({ nic: nic.id, network: network.id })
          }
        }
      }
      return nics
    },
    groupBy (array, key) {
      const result = {}
      array.forEach(item => {
        if (!result[item[key]]) {
          result[item[key]] = []
        }
        result[item[key]].push(item)
      })
      return result
    },
    fetchTemplateProperties (template) {
      var properties = []
      if (template && template.deployasisdetails && Object.keys(template.deployasisdetails).length > 0) {
        var keys = Object.keys(template.deployasisdetails)
        keys = keys.filter(key => key.startsWith('property-'))
        for (var key of keys) {
          var propertyMap = JSON.parse(template.deployasisdetails[key])
          properties.push(propertyMap)
        }
        properties.sort(function (a, b) {
          return a.index - b.index
        })
      }
      return this.groupBy(properties, 'category')
    },
    fetchTemplateConfigurations (template) {
      var configurations = []
      if (template && template.deployasisdetails && Object.keys(template.deployasisdetails).length > 0) {
        var keys = Object.keys(template.deployasisdetails)
        keys = keys.filter(key => key.startsWith('configuration-'))
        for (var key of keys) {
          var configuration = JSON.parse(template.deployasisdetails[key])
          configuration.name = configuration.label
          configuration.displaytext = configuration.label
          configuration.iscustomized = true
          configuration.cpunumber = 0
          configuration.cpuspeed = 0
          configuration.memory = 0
          for (var harwareItem of configuration.hardwareItems) {
            if (harwareItem.resourceType === 'Processor') {
              configuration.cpunumber = harwareItem.virtualQuantity
              configuration.cpuspeed = harwareItem.reservation
            } else if (harwareItem.resourceType === 'Memory') {
              configuration.memory = harwareItem.virtualQuantity
            }
          }
          configurations.push(configuration)
        }
        configurations.sort(function (a, b) {
          return a.index - b.index
        })
      }
      return configurations
    },
    fetchTemplateLicenses (template) {
      var licenses = []
      if (template && template.deployasisdetails && Object.keys(template.deployasisdetails).length > 0) {
        var keys = Object.keys(template.deployasisdetails)
        const prefix = /eula-\d-/
        keys = keys.filter(key => key.startsWith('eula-')).sort()
        for (var key of keys) {
          var license = {
            id: this.escapePropertyKey(key.replace(' ', '-')),
            name: key.replace(prefix, ''),
            text: template.deployasisdetails[key]
          }
          licenses.push(license)
        }
      }
      return licenses
    },
    deleteFrom (options, values) {
      for (const value of values) {
        delete options[value]
      }
    },
    resetFromTemplateConfiguration () {
      this.deleteFrom(this.params.serviceOfferings.options, ['cpuspeed', 'cpunumber', 'memory'])
      this.deleteFrom(this.dataPreFill, ['cpuspeed', 'cpunumber', 'memory'])
      this.handleSearchFilter('serviceOfferings', {
        page: 1,
        pageSize: 10
      })
    },
    handleTemplateConfiguration () {
      if (!this.selectedTemplateConfiguration) {
        return
      }
      const params = {
        cpunumber: this.selectedTemplateConfiguration.cpunumber,
        cpuspeed: this.selectedTemplateConfiguration.cpuspeed,
        memory: this.selectedTemplateConfiguration.memory,
        page: 1,
        pageSize: 10
      }
      this.dataPreFill.cpunumber = params.cpunumber
      this.dataPreFill.cpuspeed = params.cpuspeed
      this.dataPreFill.memory = params.memory
      this.handleSearchFilter('serviceOfferings', params)
    },
    updateTemplateParameters () {
      if (this.template) {
        this.templateNics = this.fetchTemplateNics(this.template)
        this.templateConfigurations = this.fetchTemplateConfigurations(this.template)
        this.templateLicenses = this.fetchTemplateLicenses(this.template)
        this.templateProperties = this.fetchTemplateProperties(this.template)
        this.selectedTemplateConfiguration = {}
        setTimeout(() => {
          if (this.templateConfigurationExists) {
            this.selectedTemplateConfiguration = this.templateConfigurations[0]
            this.handleTemplateConfiguration()
            if ('templateConfiguration' in this.form.fieldsStore.fieldsMeta) {
              this.updateFieldValue('templateConfiguration', this.selectedTemplateConfiguration.id)
            }
            this.updateComputeOffering(null) // reset as existing selection may be incompatible
          }
        }, 500)
      }
    },
    onSelectTemplateConfigurationId (value) {
      this.selectedTemplateConfiguration = _.find(this.templateConfigurations, (option) => option.id === value)
      this.handleTemplateConfiguration()
      this.updateComputeOffering(null)
    },
    updateTemplateConfigurationOfferingDetails (offeringId) {
      this.rootDiskSizeFixed = 0
      var offering = this.serviceOffering
      if (!offering || offering.id !== offeringId) {
        offering = _.find(this.options.serviceOfferings, (option) => option.id === offeringId)
      }
      if (offering && offering.iscustomized && this.templateConfigurationExists && this.selectedTemplateConfiguration) {
        if ('cpunumber' in this.form.fieldsStore.fieldsMeta) {
          this.updateFieldValue('cpunumber', this.selectedTemplateConfiguration.cpunumber)
        }
        if ((offering.cpuspeed == null || offering.cpuspeed === undefined) && 'cpuspeed' in this.form.fieldsStore.fieldsMeta) {
          this.updateFieldValue('cpuspeed', this.selectedTemplateConfiguration.cpuspeed)
        }
        if ('memory' in this.form.fieldsStore.fieldsMeta) {
          this.updateFieldValue('memory', this.selectedTemplateConfiguration.memory)
        }
      }
      if (offering && offering.rootdisksize > 0) {
        this.rootDiskSizeFixed = offering.rootdisksize
        this.showRootDiskSizeChanger = false
      }
      this.form.rootdisksizeitem = this.showRootDiskSizeChanger && this.rootDiskSizeFixed > 0
      this.formModel = toRaw(this.form)
    },
    handlerError (error) {
      this.error = error
    },
    closeModal () {
      this.loading.deploy = false
      this.processStatusModalVisible = false
      this.currentStep = 0
      this.steps = []
      this.processStatus = null
      this.messageError = ''
    },
    onSelectDiskSize (rowSelected) {
      this.diskSelected = rowSelected
    },
    onSelectRootDiskSize (rowSelected) {
      this.rootDiskSelected = rowSelected
    },
    updateIOPSValue (input, value) {
      this[input] = value
    },
    handleNicsNetworkSelection (nicToNetworkSelection) {
      this.nicToNetworkSelection = nicToNetworkSelection
    }
  }
}
</script>

<style lang="less" scoped>
  .card-footer {
    text-align: right;
    margin-top: 2rem;

    button + button {
      margin-left: 8px;
    }
  }

  .ant-list-item-meta-avatar {
    font-size: 1rem;
  }

  .ant-collapse {
    margin: 2rem 0;
  }
</style>

<style lang="less" scoped>
  @import url('../../style/index');

  .ant-table-selection-column {
    // Fix for the table header if the row selection use radio buttons instead of checkboxes
    > div:empty {
      width: 16px;
    }
  }

  .ant-collapse-borderless > .ant-collapse-item {
    border: 1px solid @border-color-split;
    border-radius: @border-radius-base !important;
    margin: 0 0 1.2rem;
  }

  .zone-radio-button {
    width:100%;
    min-width: 345px;
    height: 60px;
    display: flex;
    padding-left: 20px;
    align-items: center;
  }

  .vm-info-card {
    .ant-card-body {
      min-height: 250px;
      max-height: calc(100vh - 150px);
      overflow-y: auto;
      scroll-behavior: smooth;
    }

    .resource-detail-item__label {
      font-weight: normal;
    }

    .resource-detail-item__details, .resource-detail-item {
      a {
        color: rgba(0, 0, 0, 0.65);
        cursor: default;
        pointer-events: none;
      }
    }
  }

  .form-item-hidden {
    display: none;
  }

  .form {
    display: flex;
    margin-right: -20px;
    margin-bottom: 20px;
    flex-direction: column;
    align-items: flex-start;

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

    &__item {
      display: flex;
      flex-direction: column;
      flex: 1;
      padding-right: 20px;
      margin-bottom: 20px;

      @media (min-width: 760px) {
        margin-bottom: 0;
      }

      input,
      .ant-select {
        margin-top: auto;
      }

    }

    &__label {
      font-weight: bold;
    }

    &__required {
      margin-right: 5px;
      color: red;
    }

    .error-text {
      display: none;
      color: red;
      font-size: 0.8rem;
    }

    .error {

      input {
        border-color: red;
      }
      .error-text {
        display: block;
      }

    }

  }
</style>
