// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

<template>
  <a-spin :spinning="loadingData">
    <a-form
            :ref="formRef"
            :model="form"
            :rules="rules"
            layout="vertical"
            class="form"
            v-ctrl-enter="handleSubmit"
            @finish="handleSubmit">
      <div v-if="template && template.userdataid">
        <a-text type="primary">
            The template "{{ $t(this.template.name) }}" is linked to Userdata "{{ $t(this.template.userdataname) }}" 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 #bodyCell="{ column, record }">
                <template v-if="column.key === 'value'">
                  <a-input v-model:value="templateUserDataValues[record.key]" />
                </template>
              </template>
            </a-table>
          </a-input-group>
        </div><br/><br/>
      </div>
      <div v-if="userdataDefaultOverridePolicy === 'ALLOWOVERRIDE' || userdataDefaultOverridePolicy === 'APPEND' || !userdataDefaultOverridePolicy">
        <span v-if="userdataDefaultOverridePolicy === 'ALLOWOVERRIDE'" >
          {{ $t('label.user.data.do.override') }}
          <a-switch v-model:checked="doUserdataOverride" style="margin-left: 10px"/>
        </span>
        <span v-if="userdataDefaultOverridePolicy === 'APPEND'">
          {{ $t('label.user.data.do.append') }}
          <a-switch v-model:checked="doUserdataAppend" style="margin-left: 10px"/>
        </span>
        <a-step>
          <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">
                    <template #description>
                      <div>
                        <user-data-selection
                          :items="items"
                          :row-count="rowCount.userDatas"
                          :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 #bodyCell="{ column, record }">
                                <template v-if="column.key === 'value'">
                                  <a-input v-model:value="userDataValues[record.key]" />
                                </template>
                              </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>
      <div :span="24" class="action-button">
        <a-button @click="closeAction">{{ $t('label.cancel') }}</a-button>
        <a-button :loading="loadingData" ref="submit" type="primary" @click="handleSubmit">{{ $t('label.ok') }}</a-button>
      </div>
    </a-form>
  </a-spin>
</template>

<script>
import { ref, reactive, toRaw } from 'vue'
import { api } from '@/api'
import { genericCompare } from '@/utils/sort.js'
import UserDataSelection from '@views/compute/wizard/UserDataSelection'

export default {
  name: 'ResetUserData',
  components: {
    UserDataSelection
  },
  props: {
    resource: {
      type: Object,
      required: true
    },
    preFillContent: {
      type: Object,
      default: () => {}
    }
  },
  data () {
    return {
      items: [],
      total: 0,
      columns: [
        {
          dataIndex: 'name',
          title: this.$t('label.name'),
          sorter: (a, b) => genericCompare(a?.name || '', b?.name || ''),
          width: '40%'
        },
        {
          dataIndex: 'account',
          title: this.$t('account'),
          width: '30%'
        },
        {
          dataIndex: 'domain',
          title: this.$t('domain'),
          width: '30%'
        }
      ],
      selectedRowKeys: [],
      options: {
        page: 1,
        pageSize: 10,
        listall: false,
        response: 'json'
      },
      filter: '',
      rowCount: {},
      loading: {
        userDatas: false
      },
      loadingData: false,
      doUserdataOverride: false,
      doUserdataAppend: false,
      userdataTabList: [],
      userdataDefaultOverridePolicy: 'ALLOWOVERRIDE',
      userData: {},
      userDataParams: [],
      userDataParamCols: [
        {
          title: this.$t('label.key'),
          dataIndex: 'key'
        },
        {
          title: this.$t('label.value'),
          dataIndex: 'value',
          key: 'value'
        }
      ],
      userDataValues: {},
      templateUserDataCols: [
        {
          title: this.$t('label.user.data'),
          dataIndex: 'userdata'
        },
        {
          title: this.$t('label.user.data.policy'),
          dataIndex: 'userdataoverridepolicy'
        }
      ],
      templateUserDataParams: [],
      templateUserDataValues: {},
      template: {},
      userdataTabKey: 'userdataregistered',
      dataPreFill: {},
      userdata: {}
    }
  },
  created () {
    this.initForm()
    this.fetchData()
    this.loadUserdataTabList()
    this.fetchTemplateData()
    this.dataPreFill = this.preFillContent && Object.keys(this.preFillContent).length > 0 ? this.preFillContent : {}
  },
  methods: {
    initForm () {
      this.formRef = ref()
      this.form = reactive({})
      this.rules = reactive({})
    },
    fetchData () {
      this.loadingData = true
      this.items = []
      this.total = 0
      api('listUserData', this.options).then(response => {
        this.total = response.listuserdataresponse.count
        if (this.total !== 0) {
          this.items = response.listuserdataresponse.userdata
        }
      }).finally(() => {
        this.loadingData = false
      })
    },
    fetchTemplateData () {
      const params = {}
      params.id = this.resource.templateid
      params.isrecursive = true
      params.templatefilter = 'all'
      var apiName = 'listTemplates'
      api(apiName, params).then(json => {
        const templateResponses = json.listtemplatesresponse.template
        this.template = templateResponses[0]
        this.updateTemplateLinkedUserData(this.template.userdataid)
        this.userdataDefaultOverridePolicy = this.template.userdatapolicy
      })
    },
    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
              })
            })
          }
        }
      })
    },
    loadUserdataTabList () {
      this.userdataTabList = [{
        key: 'userdataregistered',
        tab: this.$t('label.user.data.registered')
      },
      {
        key: 'userdatatext',
        tab: this.$t('label.user.data.text')
      }]
    },
    onUserdataTabChange (key, type) {
      this[type] = key
      this.userDataParams = []
    },
    isUserAllowedToListUserDatas () {
      return Boolean('listUserData' in this.$store.getters.apis)
    },
    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.length > 0) {
          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
            })
          })
        }
      })
    },
    onSelectChange (selectedRowKeys) {
      this.selectedRowKeys = selectedRowKeys
    },
    handleSearch (keyword) {
      this.filter = keyword
      this.options.keyword = keyword
      this.fetchData()
    },
    handleTableChange (pagination) {
      this.options.page = pagination.current
      this.options.pageSize = pagination.pageSize
      this.fetchData()
    },
    handleSubmit () {
      if (this.loadingData) return
      const values = toRaw(this.form)
      this.loadingData = true
      console.log(values)
      const params = {
      }
      if (values.userdata && values.userdata.length > 0) {
        params.userdata = this.$toBase64AndURIEncoded(values.userdata)
      }
      if (values.userdataid) {
        params.userdataid = values.userdataid
      }
      var idx = 0
      if (this.templateUserDataValues) {
        for (const [key, value] of Object.entries(this.templateUserDataValues)) {
          params['userdatadetails[' + idx + '].' + `${key}`] = value
          idx++
        }
      }
      if (this.userDataValues) {
        for (const [key, value] of Object.entries(this.userDataValues)) {
          params['userdatadetails[' + idx + '].' + `${key}`] = value
          idx++
        }
      }
      params.id = this.resource.resetUserDataResourceId ? this.resource.resetUserDataResourceId : this.resource.id

      const resetUserDataApiName = this.resource.resetUserDataApiName ? this.resource.resetUserDataApiName : 'resetUserDataForVirtualMachine'
      const httpMethod = params.userdata ? 'POST' : 'GET'
      const args = httpMethod === 'POST' ? {} : params
      const data = httpMethod === 'POST' ? params : {}

      api(resetUserDataApiName, args, httpMethod, data).then(json => {
        this.$message.success({
          content: `${this.$t('label.action.user.data.reset')} - ${this.$t('label.success')}`,
          duration: 2
        })
        this.$emit('refresh-data')
        this.closeAction()
      }).catch(error => {
        this.$notifyError(error)
      }).finally(() => {
        this.loadingData = false
      })
    },
    closeAction () {
      this.$emit('close-action')
    }
  }
}
</script>

<style scoped lang="scss">
.form {
  width: 90vw;
  @media (min-width: 800px) {
    width: 45vw;
  }
}
</style>
