<script>
import NOptionsCascaderPaster from './options-cascader-paster'
import {Paster, prop} from '@uif/next/lib/utils/tools'

class CascaderPaster extends Paster {
  constructor (args) {
    super(args)
    this.index = args.index
    this.subPaster = null
  }

  // 更新
  update (event, options) {
    if (this.reference !== event.target) {
      // eslint-disable-next-line no-unused-expressions
      this.popperComponent?.setProps('options', options)
      this.reference = event.target
      this.destroyEngine()
    }
  }

  // 延迟隐藏
  toHidden () {
    // eslint-disable-next-line no-unused-expressions
    this.subPaster?.toHidden()
    this.time.out(() => this.hidden(), 200)
  }
}

export default {
  name: 'n-options-cascader',
  props: {
    // 贴片名：如果有wrap，则将有div包裹，如果没有，则由外部控制
    wrap: prop.string(),
    // 是否可见
    value: prop.boolean(),
    // 禁用
    disabled: prop.boolean(),
    // 是否多选
    multiple: prop.boolean(),
    /**
     * paster
     * **/
    // 触发方式，可选值为click, hover
    trigger: prop.inArray(['click', 'hover'], 'click'),
    // 提示框宽度
    width: prop.stringNumber(),
    // 自定义选项
    pasterOptions: prop.object(),
    /**
     * options
     * **/
    // SearchState
    state: prop.object(),
    // 选项
    options: prop.array(),
    // 最大高度
    maxHeight: prop.number(270),
    // 自定义渲染
    builders: prop.object(() => ({
      header: null,
      option: null,
      footer: null,
      empty: null
    })),
    // 延迟2分钟自动销毁
    autoDestroy: prop.boolean(),
    // 点击自动关闭 ADD
    autoClose: prop.boolean(true)
  },
  data () {
    return {
      pasterCtorComponent: NOptionsCascaderPaster,
      nValue: false
    }
  },
  render (h) {
    const {wrap, onClick, onMouseenter, onMouseleave, $scopedSlots} = this
    if (!wrap) {
      return $scopedSlots.default?.({onClick, onMouseenter, onMouseleave})
    }
    return h('div', {staticClass: wrap, on: {click: onClick, mouseenter: onMouseenter, mouseleave: onMouseleave}}, $scopedSlots.default?.())
  },
  watch: {
    value (value) {
      this.setNValue(value)
    },
    nValue (nValue) {
      if (this.value !== nValue) {
        this.$emit('input', nValue)
        this.$emit('update:value', nValue)
      }
    },
    // options 变更，更新 props
    options (value) {
      return this.paster?.popperComponent?.setProps('options', value)
    }
  },
  methods: {
    // 点击
    onOptionClick (option) {
      this.$emit('click', option)
      this.$emit('u-change', option)
      this.autoClose && this.setNValue(false)
    },
    /**
     * paster
     * **/
    // 设置状态
    setNValue (value) {
      if (this.nValue !== value) {
        this.nValue = value
        this.updateRootPaster(value)
      }
    },
    // 点击
    onClick () {
      if (this.trigger !== 'hover' && !this.disabled) {
        this.setNValue(true)
      }
    },
    // 鼠标移入
    onMouseenter () {
      if (!this.disabled && this.trigger === 'hover') {
        this.setNValue(true)
        return this.paster?.time.clear()
      }
    },
    // 鼠标移出
    onMouseleave () {
      if (!this.disabled && this.trigger === 'hover') {
        this.onPasterMouseleave()
      }
    },
    // paster 鼠标移出
    onPasterMouseleave () {
      if (this.trigger === 'hover') {
        this.paster.toHidden()
      } else {
        return this.paster.subPaster?.toHidden()
      }
    },
    // 展开顶层选项
    updateRootPaster (value) {
      if (!this.paster) {
        const _paster = this.paster = new CascaderPaster({
          index: 1,
          reference: this.$el,
          ctor: {
            creator: this,
            component: this.pasterCtorComponent,
            props: {
              builders: this.builders,
              maxHeight: this.maxHeight,
              multiple: this.multiple,
              state: this.state,
              options: this.options,
              index: 1
            },
            scopedSlots: this.$scopedSlots,
            nativeOn: {
              mouseenter: () => this.paster.time.clear(),
              mouseleave: () => this.onPasterMouseleave()
            },
            on: {
              enter: (arg) => this.showSubPaster(_paster, arg),
              leave: () => _paster.subPaster?.toHidden(),
              'option-click': this.onOptionClick
            }
          },
          options: {
            placement: 'bottom-start',
            offset: [0, 4],
            styles: {
              width: this.width + 'px'
            },
            ...this.pasterOptions
          },
          autoDestroy: this.autoDestroy,
          onStateChange: (value) => this.setNValue(value)
        })
      }
      value ? this.paster.show() : this.paster.hidden()
    },
    // 获取子paster
    showSubPaster (paster, {event, options}) {
      // 初始化
      if (!paster.subPaster) {
        const _paster = paster.subPaster = new CascaderPaster({
          index: paster.index + 1,
          reference: event.target,
          ctor: {
            creator: this,
            component: this.pasterCtorComponent,
            parentNode: paster.popperElement,
            props: {
              builders: this.builders,
              maxHeight: this.maxHeight,
              multiple: this.multiple,
              state: this.state,
              options,
              index: paster.index + 1,
              hasArrow: true
            },
            scopedSlots: this.$scopedSlots,
            nativeOn: {
              mouseenter: () => _paster.time.clear(),
              mouseleave: () => _paster?.toHidden()
            },
            on: {
              enter: (arg) => this.showSubPaster(_paster, arg),
              leave: () => _paster.subPaster?.toHidden(),
              'option-click': this.onOptionClick
            }
          },
          options: {
            placement: 'right-start',
            offset: [-8, 4],
            styles: {
              width: this.width + 'px'
            },
            ...this.pasterOptions
          }
        })
      }
      // 更新
      paster.subPaster.update(event, options)
      // 显示
      paster.subPaster.show()
    }
  }
}
</script>
