// 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 style="width: 100%">
    <a-row :gutter="6">
      <a-col :md="24" :lg="layout === 'horizontal' ? 10 : 24">
        <a-checkbox
          :checked="checked"
          :disabled="forExternalNetProvider"
          @change="handleCheckChange">
          {{ checkBoxLabel }}
        </a-checkbox>
      </a-col>
      <a-col :md="24" :lg="layout === 'horizontal' ? 12 : 24">
        <a-form-item
          v-if="reversed !== checked"
          :label="selectLabel">
          <a-select
            v-model:value="selected"
            :disabled="forExternalNetProvider"
            showSearch
            optionFilterProp="label"
            :filterOption="(input, option) => {
              return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
            }"
            @change="val => { handleSelectChange(val) }">
            <a-select-option
              v-for="(opt) in selectSource"
              :key="opt.id"
              :disabled="opt.enabled === false"
              :label="opt.displaytext || opt.name || opt.description">
              {{ opt.displaytext || opt.name || opt.description }}
            </a-select-option>
          </a-select>
        </a-form-item>
      </a-col>
    </a-row>
  </div>
</template>

<script>

export default {
  name: 'CheckBoxSelectPair',
  props: {
    layout: {
      type: String,
      default: 'horizontal'
    },
    resourceKey: {
      type: String,
      required: true
    },
    checkBoxLabel: {
      type: String,
      required: true
    },
    defaultCheckBoxValue: {
      type: Boolean,
      default: false
    },
    defaultSelectValue: {
      type: String,
      default: null
    },
    selectOptions: {
      type: Array,
      required: true
    },
    selectLabel: {
      type: String,
      default: ''
    },
    reversed: {
      type: Boolean,
      default: false
    },
    forExternalNetProvider: {
      type: Boolean,
      default: false
    }
  },
  data () {
    return {
      checked: false,
      selectedOption: null,
      selectOptionsTimer: null
    }
  },
  created () {
    this.checked = this.defaultCheckBoxValue
    if (this.defaultSelectValue) {
      this.selectedOption = this.defaultSelectValue
    }
  },
  watch: {
    selectOptions () {
      clearTimeout(this.selectOptionsTimer)
      this.selectOptionsTimer = setTimeout(() => {
        this.handleSelectOptionsUpdated()
      }, 50)
    }
  },
  computed: {
    selectSource () {
      return this.selectOptions.map(item => {
        var option = { ...item }
        if (!('id' in option)) {
          option.id = option.name
        }
        return option
      })
    },
    selected () {
      return this.option || this.selectedOption
    },
    option () {
      if (this.forExternalNetProvider) {
        return this.selectOptions[0]?.name || null
      }
      return null
    }
  },
  methods: {
    arrayHasItems (array) {
      return array !== null && array !== undefined && Array.isArray(array) && array.length > 0
    },
    handleCheckChange (e) {
      this.checked = e.target.checked
      if (this.checked && !this.selectedOption) {
        this.selectedOption = this.selectSource?.filter(x => x.enabled !== false)?.[0]?.id || null
      }
      this.$emit('handle-checkselectpair-change', this.resourceKey, this.checked, this.selectedOption)
    },
    handleSelectChange (val) {
      this.selectedOption = val
      this.$emit('handle-checkselectpair-change', this.resourceKey, this.checked, this.selectedOption)
    },
    handleSelectOptionsUpdated () {
      if (!this.checked) return
      var enabledOptions = this.selectSource?.filter(x => x.enabled !== false) || []
      if (this.selectedOption && !enabledOptions.includes(this.selectedOption)) {
        this.handleSelectChange(enabledOptions[0]?.id || null)
      }
    }
  }
}
</script>

<style lang="less" scoped>
.ant-list-split .ant-list-item div {
  width: 100%;
}
</style>
