/**
 * 级联选择
 * 自持自定义 cascader panel
 * @author xiufu.wang
 */
import ElCascader from 'mars-pro/packages/cascader';
import selectDatasourceMixin from 'mars-pro/packages/pro-select/src/mixins/select-datasource';
import Locale from 'mars-pro/src/mixins/locale';
import { ProConfigProvideMixin } from 'mars-pro/packages/pro-config-provide';
import { getElementWidth, getSingleTextWidth, isArray, objectProperty } from 'mars-pro/src/pro/util';
import debounce from 'throttle-debounce/debounce';
import { isLikeOption } from 'mars-pro/src/pro/resolve-form-selectdata';

export default {
  name: 'ProSelectCascader',
  componentName: 'ProSelectCascader',
  mixins: [selectDatasourceMixin, Locale, ProConfigProvideMixin],
  components: {
    ElCascader
  },
  inject: {
    elForm: {
      default: ''
    },

    elFormItem: {
      default: ''
    }
  },
  props: {
    value: {},
    //选择模式 single | multiple
    selectModel: [String, Boolean],
    // 启用不换行展示
    showOverflowTooltip: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      initVisible: false,
      initData: false,
      syncValue: false
    }
  },
  computed: {
    _elFormItemSize() {
      return (this.elFormItem || {}).elFormItemSize;
    },
    // 大小
    selectSize() {
      return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
    },
  },
  created() {
    this.activateGlobalTooltip = debounce(500, tooltip => tooltip.handleShowPopper())
  },
  methods: {
    addCacheOption(list) {
      if (!list) {
        return
      }
      this.$refs.elcascader.addCacheTempSelect(Array.isArray(list) ? list : [list])
    },
    // 重写并忽略selectDatasourceMixin.addSelectCacheOptions
    addSelectCacheOptions() {
      this.changeInitVisible()
    },
    //渲染下拉面板
    renderCustomerCascaderPanel(cascaderPanelContext) {
      const cascaderContext = cascaderPanelContext.$parent
      if (!this.initVisible) {
        this.initVisible = cascaderContext.dropDownVisible
      }
      if (!this.initVisible) {
        return null
      }
      const vnodes = this.$scopedSlots.customerCascaderPanel(cascaderPanelContext)
      return Array.isArray(vnodes) ? vnodes[0] : vnodes
    },
    changeInitVisible() {
      if (this.initVisible !== true) {
        this.initVisible = true
      }
    },
    handleInput(v) {
      this.$emit('input', v)
    },
    // showOverflowTooltip 处理
    handleMouseenter() {
      const configProvide = this.getConfigProvide()
      if (!this.showOverflowTooltip || !configProvide || this.value === null || this.value === undefined || !configProvide.proGlobalTooltip) {
        return
      }
      const el = this.$el
      let helpContext = ''
      if (this.selectModel === 'multiple') {
        const lastchild = el.querySelector('.el-cascader__tags').querySelector('.el-tag:last-child')
        if (!(lastchild.offsetLeft > lastchild.offsetParent.getBoundingClientRect().width)) {
          return
        }
        helpContext = [].map.call(lastchild.parentNode.childNodes, (r) => r.innerText).join(' | ')
      } else {
        helpContext = this.$refs.elcascader.inputValue
        const inputEl = el.querySelector('.el-input__inner')
        const textWidth = getSingleTextWidth(helpContext, window.getComputedStyle(inputEl).fontSize)
        const inputWidth = getElementWidth(inputEl)
        if (textWidth < inputWidth) {
          return
        }
      }
      const globalTooltipScope = configProvide.proGlobalTooltip
      const tooltip = globalTooltipScope.$refs.proGlobalTooltip;
      globalTooltipScope.tooltipContent = helpContext
      tooltip.referenceElm = el;
      tooltip.$refs.popper && (tooltip.$refs.popper.style.display = 'none');
      tooltip.doDestroy();
      tooltip.setExpectedState(true);
      this.activateGlobalTooltip(tooltip);
    },
    // showOverflowTooltip 处理
    handleMouseleave() {
      const configProvide = this.getConfigProvide()
      if (configProvide && configProvide.proGlobalTooltip) {
        const globalTooltipScope = configProvide.proGlobalTooltip
        const tooltip = globalTooltipScope.$refs.proGlobalTooltip;
        tooltip.setExpectedState(false);
        tooltip.handleClosePopper();
      }
    },
    /**
     * 级联选择和普通的下来选择控件不一样，所以这里只能支持从 elform.detailModel取值,逻辑如下:
     * 从缓存、cascader.store中获取，如果没有 就从elform.detailModel
     * @param {*} value 
     */
    handleSyncValueOptions(value) {
      //如果不在表单模式下，则忽略
      if (!this.elFormItem || !this.elForm) {
        return
      }
      this.$nextTick(() => {
        //忽略{value:?, label: ?}
        if (value && isLikeOption(value)) {
          return
        }
        //忽略空值
        if (!value || (Array.isArray(value) && value.length === 0)) {
          return
        }
        const isMultiple = this.selectModel === 'multiple';
        let isMatchLabel = false;
        const detailModel = objectProperty(this, 'elForm.detailModel', null)
        const config = objectProperty(this.getConfigProvide(), 'config', {})
        const prop = objectProperty(this, 'elFormItem.prop', null)
        let labelProp = config.getLabelPropFromDetailModel(prop) || [];
        labelProp = Array.isArray(labelProp) ? labelProp : [labelProp]
        let labelValue = null;
        for (let i = 0; i < labelProp.length; i++) {
          const textProp = labelProp[i];
          if (textProp) {
            labelValue = objectProperty(detailModel, textProp, null)
          }
          if (labelValue) {
            break;
          }
        }

        if (isMultiple) {
          const findOption = this.$refs.elcascader.getCheckedNodes(true);
          //如果匹配失败,则从detailModel组合
          if ((!findOption || findOption.length !== value.length) && labelValue && labelValue.length > 0) {
            this.$refs.elcascader.addCacheTempSelect((value || []).map((v, index) => ({ value: v, label: labelValue[index] })))
            //更新
            this.$refs.elcascader.computePresentContent()
          }
        } else {
          const findOption = this.$refs.elcascader.computePresentText();
          if (!findOption && labelValue) {
            this.$refs.elcascader.addCacheTempSelect([{ value: value, label: labelValue }])
            //更新
            this.$refs.elcascader.computePresentContent()
          }
        }
      })
    }
  },
  watch: {
    value: {
      handler: function (v) {
        this.handleSyncValueOptions(v)
      }
    }
  },
  render() {
    const { $attrs } = this
    const props = $attrs.props || {}
    const scopedSlots = this.$scopedSlots
    const realDataSource = this.realDataSource
    const _datas = {
      props: {
        clearable: true,
        value: this.value,
        size: this.selectSize,
        ...(props.lazy === true ? {} : { options: (this.initVisible || this.initData) ? this.selectDatas : [] }),
        ...$attrs,
        props: {
          emitPath: false,
          multiple: this.selectModel === 'multiple',
          //懒加载函数
          ...(realDataSource && realDataSource.isDataSource === true ? { lazyLoad: realDataSource.cascaderAsyncload } : {}),
          ...props,
          ...(this.isLoading ? { emptyText: this.t('el.cascader.loading') } : {})
        }
      },
      attrs: {
        ...$attrs
      },
      scopedSlots: {
        ...scopedSlots,
        ...(this.$scopedSlots.customerCascaderPanel ? { customerCascaderPanel: this.renderCustomerCascaderPanel } : {})
      },
      on: {
        'visible-change': this.changeInitVisible,
        ...this.$listeners,
        input: this.handleInput,
      },
      'class': {
        'pro-select-cascader': true,
        'pro-select-cascader--show-overflow-tooltip': this.showOverflowTooltip
      },
      nativeOn: {
        mouseenter: this.handleMouseenter,
        mouseleave: this.handleMouseleave,
        click: this.handleMouseleave
      },
      ref: 'elcascader'
    }
    return (
      <ElCascader {..._datas}></ElCascader>
    )
  },
  mounted() {
    this.handleSyncValueOptions(this.value)
  }
}

