<template>

  <div>
    <div v-for="(item, n) in items" :key="n">
      <slot name="item" :item="item" :isChecked="isChecked(item)" :onToggle="(isChecked) => onToggleOption(item, isChecked)" :isDisabled="disabled || isDisabled(item)">
        <itf-checkbox
          :value="isChecked(item)"
          :label="item.name"
          :disabled="disabled || isDisabled(item)"
          @input="onToggleOption(item, $event)"
        >
          {{ item[itemKey] || item }}
        </itf-checkbox>
      </slot>

      <div v-if="item[childrenKey] && item[childrenKey].length" class="ps-4 mb-2">
        <itf-nested-checkbox-group
          :value="value"
          @input="$emit('input', $event)"
          :items="item[childrenKey]"
          :disabled="disabled || isDisabled(item)"
          :item-key="itemKey"
          :children-key="childrenKey"
          :max="max"
          :disabled-ids="disabledIds"
        >
          <template v-for="(_, name) in $slots" #[name]="slotData">
            <slot :name="name" v-bind="slotData || {}"/>
          </template>
          <template v-for="(_, name) in $scopedSlots" #[name]="slotData">
            <slot :name="name" v-bind="slotData || {}"/>
          </template>
        </itf-nested-checkbox-group>
      </div>
    </div>

    <slot />
  </div>

</template>
<script>
  import { Vue, Component, Prop, Model } from 'vue-property-decorator';
  import itfCheckbox from './Checkbox';
  import itfTableRows from '@itfin/components/src/components/table/TableRows.vue';

  export default @Component({
    name: 'itfNestedCheckboxGroup',
    components: {
      itfTableRows,
      itfCheckbox
    },
  })
  class itfNestedCheckboxGroup extends Vue {
    @Model('input', { type: Array, default: () => [] }) value;

    @Prop(Array) items;
    @Prop(Boolean) disabled;
    @Prop({ type: Array, default: () => [] }) disabledIds;

    @Prop({ type: String }) itemKey;
    @Prop({ type: String, default: 'children' }) childrenKey;

    @Prop(Number) max;

    onToggleOption(value, isChecked) {
      const arr = this.value ? [ ...this.value ] : [];
      if (value[this.childrenKey] && value[this.childrenKey].length) {
        for (const child of value[this.childrenKey]) {
          const index = arr.findIndex(item => this.itemKey ? item[this.itemKey] === child[this.itemKey] : item === child);
          if (index !== -1 && isChecked === false) {
            arr.splice(index, 1);
          } else if (isChecked === true) {
            arr.push(child);
          }
        }
        this.$emit('input', arr);
        return;
      }
      const index = this.getCheckedIndex(value);
      if (index !== -1 && isChecked === false) {
        arr.splice(index, 1);
      } else if (isChecked === true) {
        arr.push(value);
      }
      this.$emit('input', arr);
    }

    getCheckedIndex(value) {
      if (this.itemKey) {
        return this.value && this.value.findIndex(item => item[this.itemKey] === value[this.itemKey]);
      }
      return this.value.indexOf(value);
    }

    isChecked(value) {
      if (value[this.childrenKey] && value[this.childrenKey].length) {
        return value[this.childrenKey].every(child => this.isChecked(child)) || this.getCheckedIndex(value) !== -1;
      }
      return this.getCheckedIndex(value) !== -1;
    }

    isDisabled(value) {
      if (this.disabledIds.includes(value)) {
        return true;
      }
      return this.getCheckedIndex(value) === -1 && (this.max !== 'undefined' && this.value.length >= this.max);
    }
  }
</script>
