<template>
  <div v-loading="loading" class="lab-view" >
    <div v-if="!labDesign.switch || showView">
      <lab-form v-if="!loading" :element="element" :model-data="modelData" />
    </div>
    <el-card v-else :body-style="{ padding: '12px' }">
      <span> 设计时嵌套视图不展示</span>
    </el-card>

    <el-dialog :visible.sync="windowVisible" center :title="windowConf.title" :width="windowConf.width" append-to-body destroy-on-close :close-on-click-modal="false" :close-on-press-escape="false">
      <lab-view v-if="windowVisible" key="windowRef" :element="windowForm" :model-data="windowData" />
    </el-dialog>
  </div>
</template>

<script>
import LabBase from "../../mixins/LabBase";
import Util from "../../utils/Util";

export default {
  name: "LabView",
  mixins: [LabBase],
  provide(){
    return {
      selfRegister: this.elementRegister,
      parentView: this,
      openWindow: this.openWindow,
      closeWindow: this.closeWindow,
      findElement: this.findElement,
      elementCheck: this.elementCheck
    }
  },
  inject: {
    /**
     * 加载组件对象,注入异步方法
     */
    loadView: {
      from: 'loadView',
      default: function () {
        return function (ele){
          return new Promise(resolve => { return resolve(ele)})
        }
      }
    }
  },
  props: {
    showView:{
      type: Boolean,
      default: false
    }
  },
  watch: {
    windowVisible(newVal){
      if (!newVal) {
        this.windowForm = {}
        this.windowData = {}
      }
    }
  },
  data() {
    return {
      loading: true,
      registerMap: {},
      windowVisible: false,
      windowConf: { title: '窗口', width: '80%'},
      windowData: {},
      windowForm: {}
    }
  },
  created() {
    this.loading = true
    this.$LabRender.autoFill(this.element, this)
    if (this.labDesign.switch) {
      this.elementCheck(this.element)
      this.loading = false
    } else if (this.element.elements && this.element.elements.length === 0) {
      this.loadView(this.element, this.modelData)
          .then((res) => {
            this.$resultMsg(this, res, true)
            if (res.code === 200) {
              this.elementCheck(this.element)
            }
            this.loading = false
          })
    } else {
      this.elementCheck(this.element)
      this.loading = false
    }
  },
  methods: {
    /**
     * 组件属性检查
     * @param item
     * @param prentRender 父级类型
     */
    elementCheck(item, prentRender) {
      if (item.checked) {
        return
      }
      if (!item.prentRender) {
        Reflect.set(item, 'prentRender', prentRender)
      }
      this.$LabRender.autoFill(item, this)
      if (item.elements.length > 0) {
        item.elements.forEach(ele => this.elementCheck(ele, item.render || prentRender))
      }
    },
    /**
     * 组件注册，通过组件mapper注册
     * @param el  组件dom对象实例
     */
    elementRegister(el) {
      if (this.labDesign.switch || !el || !el.element || !el.element.mapper) {
        return
      }
      const key = el.element.mapper
      const list = this.registerMap[key] || []
      const index = list.findIndex(item => item === el)
      if (index < 0) {
        list.push(el)
      } else {
        list.splice(index, 1, el)
      }
      this.$set(this.registerMap, key, list)
    },
    /**
     * 组件查找
     * @param key        唯一标识，组件mapper
     * @param matchObj   详细匹配对象，对比对象内所有属性值
     * @return {*[]|*}   查找到的组件实例集合
     */
    findElement(key, matchObj){
      if (Util.isEmpty(key) || Util.isEmpty(this.registerMap)){
        return null
      } else {
        const eles = this.registerMap[key]
        if (Util.isEmpty(eles)){
          return null
        } else if (eles.length === 1) {
          return eles[0]
        } else if (!Util.isEmpty(matchObj)){
          const props = Util.isEmpty(matchObj) ? [] : Object.keys(matchObj)
          for (let i = eles.length; i > 0; i--) {
            const item = eles[i]
            let match = false
            for (let i = 0; i < props.length; i++) {
              const value = Util.callPropValue(item, props[i])
              const matchVal = Util.callPropValue(matchObj, props[i])
              match = value === matchVal
              if (!match) {
                break
              }
            }
            if (match) {
              return item
            }
          }
        }
        return null;
      }
    },
    /**
     * 打开窗口
     * @param form    窗口渲染视图
     * @param data    窗口数据
     * @param conf    窗口配置
     */
    openWindow(form, data, conf) {
      this.windowForm = form
      if (data) {
        this.windowData = Util.copy(data)
      }
      if (conf) {
        Util.copyAttr(conf, this.windowConf)
      }
      this.windowVisible = true
    },
    /**
     * 窗口关闭
     */
    closeWindow() {
      this.windowVisible = false
    }
  }
}
</script>

<style scoped>

</style>
