<template>
  <div :class="[b(),className]"
       @mouseenter="handleMouseEnter"
       @mouseleave="handleMouseLeave"
       element-loading-spinner="el-icon-loading"
       element-loading-background="rgba(255,255,255,0)"
       v-loading="loading"
       :id="id"
       ref="containerRef"
       :style="[styleSizeName]">
    <component ref="main"
               :style="styleChartName"
               :is="dynamicComponent"
               :object="object"
               @dblclick.self="handleDblClick"
               @change="handleChange"
               @click.self="handleClick"
               :data-params="dataParams"
               :refList="refList"
               :option="option"
               :dataChart="dataChart">
    </component>
  </div>
</template>

<script>
import { ref, shallowRef, computed, nextTick, defineEmits, onMounted, reactive, watch, toRefs } from 'vue'
import create from "../../create";
import { getObj } from '@/api/components'
export default create({
  name: "vue",
  data () {
    return {
      loading: false,
      timeout: null,
      template: '',
      dynamicComponent: null,
    };
  },
  watch: {
    ids () {
      this.debounce(this.initVue)()
    },
    src () {
      this.debounce(this.initVue)()
    },
    isVue3 () {
      this.initVue()
    },
    remote () {
      this.initVue()
    },
    content (val) {
      this.initVue()
    }
  },
  computed: {
    isVue3 () {
      return this.option.vue3
    },
    ids () {
      return this.option.id
    },
    src () {
      return this.option.src;
    },
    content () {
      return this.option.content;
    },
    remote () {
      return this.option.remote;
    }
  },
  created () {
    this.initVue()
  },
  methods: {
    getSource (type) {
      const reg = new RegExp(`<${type}[^>]*>`);
      let content = this.template;
      let matches = content.match(reg);
      if (matches) {
        let start = content.indexOf(matches[0]) + matches[0].length;
        let end = content.lastIndexOf(`</${type}`);
        return content.slice(start, end)
      }
    },
    debounce (func, wait = 600) {
      let that = this;
      return function () {
        const context = this;
        const args = arguments;
        clearTimeout(that.timeout);
        that.timeout = setTimeout(function () {
          func.apply(context, args);
        }, wait);
      };
    },
    getTemplate () {
      return new Promise((resolve, reject) => {
        if (this.remote && (this.src || this.ids)) {
          this.loading = true
          let axiosObj = this.ids ? getObj(this.ids) : this.$axios.get(this.src)
          axiosObj.then(res => {
            resolve(this.ids ? res.data.data.content : res.data)
          }).catch(() => {
            resolve()
          })
        } else {
          resolve(this.content)
        }
      })
    },
    initVue () {
      this.loading = true
      this.dynamicComponent = {
        template: '<div><h1>组件加载中</h1></div>'
      }
      this.isVue3 ? this.renderVue3 ? this.renderVue3() : this.renderVue2 : this.renderVue2()
    },
    initStyle () {
      const styleCss = this.getSource("style");
      const styleId = 'style-' + this.id;
      const existingStyle = document.getElementById(styleId);
      if (existingStyle) existingStyle.remove();
      const style = document.createElement("style");
      style.id = styleId;
      style.innerHTML = `
          #${this.id} {
              ${styleCss || ''}
          }
        `;
      document.head.appendChild(style);
    },
    renderVue2 () {
      this.loading = true; // 先设置 loading 状态
      this.getTemplate().then(res => {
        this.$emit('remote-change', { id: this.component, content: res });
        this.template = res;

        const template = this.getSource("template");
        const script = this.getSource("script")?.replace(/export default/, "return") || '';
        this.initStyle()
        try {
          const obj = new Function(script)() || {};
          Object.assign(obj, {
            template,
            props: {
              object: Object,
              option: Object,
              dataParams:Object,
              dataChart: Object,
              refList: [Array, Object],
            },
          });
          this.dynamicComponent = shallowRef(obj);
        } catch (err) {
          console.log(err)
        }

      }).catch(error => {
        console.error('Preview mounting error:', error)
        this.initError()
      }).finally(() => {
        this.loading = false;
      });

    },
    initError () {
      this.dynamicComponent = {
        template: '<div><h1>组件语法错误</h1></div>'
      }
    }
  }
});
</script>

<style scoped>
.mount-container {
  width: 100%;
  height: 100%;
}
</style>


