<template>
  <div>
    <!--  标题  -->
    <a-card>
      <a-page-header
        title="奥枫低代码前端编辑器"
        sub-title="af-lowcode"
        :backIcon="false"
        @back="() => null"
      >
        <template slot="extra">
          <a-button @click="test">测试</a-button>
          <a-button @click="editModeActive">编辑</a-button>
          <a-button @click="previewModeActive">预览</a-button>
          <a-button type="primary" @click="exportConfig">导出</a-button>
        </template>
      </a-page-header>
    </a-card>
    <!--  预览模式  -->
    <a-card v-if="preview">
      <LowCodeRender :page-config="config" :edit-mode="false"/>
    </a-card>
    <!--  编辑模式  -->
    <div v-show="!preview">
      <a-row :gutter="2">
        <!--    左侧    -->
        <a-col :span="4">
          <a-card>
            <a-tabs>
              <!--    UI库    -->
              <a-tab-pane key="1" tab="UI库">
                <LowCodeUIStore @refresh="refresh"/>
              </a-tab-pane>
              <!--    页面架构    -->
              <a-tab-pane key="2" tab="架构" style="overflow: scroll">
                <div style="margin-bottom: 3%; width: 200px">
                  <LowCodePageOrganization
                    :config="filterOrganizationConfig()"
                    v-if="showPageOrganization"
                    :select-tree-node="selectTreeNode"
                    @rename="rename"
                    @add="handleTreeAdd"
                    @split="handleSplit"
                    @pasteItem="handlePasteItem"
                    @componentMove="handleTreeDrag"
                    @deleteComponent="deleteComponentInTree"
                    @treeOrganizationClick="treeOrganizationClick"/>
                </div>
              </a-tab-pane>
            </a-tabs>
          </a-card>
        </a-col>
        <!--    中间主体编辑器    -->
        <a-col :span="15">
          <a-card>
            <!--       切换显示的组件       -->
            <div style="margin-bottom: 3%">
              <!--    添加页面组件按钮    -->
              <div style="float: right">
                <a-popover>
                  <template slot="content">
                    <p>添加页面组件</p>
                  </template>
                  <a-button @click="addPageContainer" >
                    <a-icon type="plus"/>
                  </a-button>
                </a-popover>
              </div>
              <!--    每个页面按钮切换栏    -->
              <a-menu v-model="mainPageMenu" mode="horizontal" @click="handleMainPageMenuChange">
                <template v-for="(page) in config.page">
                  <a-menu-item :key="page.id">{{ page.title + '(' + determinePageType(page.type) + ')' }}</a-menu-item>
                </template>
              </a-menu>
            </div>
            <!--      渲染器      -->
            <div v-if="activeMainPageType === 'page'">
              <LowCodeRender
                v-if="renderPage"
                ref="page_render"
                @spanDrag="handleDrag"
                @containerDelete="handleContainerDelete"
                @clickComponentInEditor="clickComponentInEditor"
                :page-config="{ data: config.data, page: config.page.filter(page => page.id === activeMainPage)}"/>
              <a-skeleton v-else/>
            </div>
            <div v-if="activeMainPageType === 'modal'">
              <LowCodeRender
                v-if="renderPage"
                ref="modal_render"
                @spanDrag="handleDrag"
                @containerDelete="handleContainerDelete"
                @clickComponentInEditor="clickComponentInEditor"
                :page-config="{ data: config.data, page: config.page.filter(page => page.id === activeMainPage)}"/>
              <a-skeleton v-else/>
            </div>
            <div v-if="activeMainPageType === 'draw'">
              <LowCodeRender
                v-if="renderPage"
                ref="draw_render"
                @spanDrag="handleDrag"
                @containerDelete="handleContainerDelete"
                @clickComponentInEditor="clickComponentInEditor"
                :page-config="{ data: config.data, page: config.page.filter(page => page.id === activeMainPage)}"/>
              <a-skeleton v-else/>
            </div>
          </a-card>
        </a-col>
        <!--    右侧    -->
        <a-col :span="5">
          <LowCodeEditorPanel
            ref="rightPanel"
            @openModal="openModal"
            @controlRender="controlRender"
            :disable-event-editor="disableEventEditor"
            :editorPropertiesConfig="editorPropertiesConfig"/>
        </a-col>
      </a-row>
    </div>
    <!--  所有的弹窗，包括：
        新增页面容器弹框
        自定义JS函数弹框
        事件编辑弹框
        自定义生命周期函数弹框
        自定义Logic参数JS弹框
        自定义Logic回调弹框
        运行目标组件参数编辑弹框
        -->
    <LowCodeEditorModal
      ref="allModal"
      @changeOuterValue="changeOuterValue"
      @refresh="refresh"
      :event-editor-current="eventEditorCurrent"
      :editor-properties-config="editorPropertiesConfig"/>
  </div>
</template>

<script>
import LowCodeRender from '@vue2-client/base-client/components/common/LowCodeComponent/LowCodeRender.vue'
import * as lowcodeUtils from '@vue2-client/utils/lowcode/lowcodeUtils'
import codeMirror from '@vue2-client/components/CodeMirror/inedx.vue'
import lowcodeComponentMixin from '@vue2-client/utils/lowcode/lowcodeComponentMixin'
import LowCodePageOrganization from '@vue2-client/base-client/components/common/LowCodeComponent/LowCodePageOrganization.vue'
import LowCodeEditorModal from '@vue2-client/base-client/components/common/LowCodeComponent/LowCodeEditorModal.vue'
import LowCodeUIStore from '@vue2-client/base-client/components/common/LowCodeComponent/LowCodeUIStore.vue'
import LowCodeEditorPanel from '@vue2-client/base-client/components/common/LowCodeComponent/LowCodeEditorPanel.vue'

export default {
  name: 'LowCodeEditor',
  components: {
    LowCodeEditorModal,
    LowCodePageOrganization,
    LowCodeRender,
    codeMirror,
    LowCodeUIStore,
    LowCodeEditorPanel
  },
  props: {
    // 页面原始的配置，用于从琉璃中读取
    originalConfig: {
      type: Object,
      default: () => {
        return {
          page: []
        }
      }
    }
  },
  data () {
    return {
      // 主体窗口选择的标签
      mainPageMenu: ['none'],
      // 控制是否渲染页面
      preview: false,
      // 控制架构树显隐，用于刷新组件
      showPageOrganization: true,
      // 用于保存右侧编辑组件的属性
      editorPropertiesConfig: {},
      // 用于事件编辑的回显，在点击事件编辑按钮后，会将此变量赋值
      eventEditorCurrent: undefined,
      // 保存目标组件可以触发哪些事件
      supportedEventType: undefined,
      // 保存主体中，当前激活的标签栏ID
      activeMainPage: undefined,
      // 保存主体中，当前激活的标签栏类型
      activeMainPageType: undefined,
      // 指定架构树选中哪个节点
      selectTreeNode: undefined,
      // 禁用事件编辑
      disableEventEditor: false,
      // 控制右侧事件编辑刷新
      showEventEditor: true,
      // 控制渲染器更新
      renderPage: true
    }
  },
  provide () {
    return {
      // 将注册的组件传递给子组件
      componentsMap: {}
    }
  },
  methods: {
    controlRender (flag) {
      this.renderPage = flag
    },
    // 打开弹窗
    openModal (modalName) {
      this.$refs.allModal.changeModalVisible(modalName)
    },
    // 子组件修改父组件的值
    changeOuterValue (key, value) {
      this[key] = value
    },
    // 根据类型刷新组件
    refresh (type) {
      switch (type) {
        case 'Organization':
          this.refreshOrganization()
          return
        case 'eventEditor':
          this.$refs.rightPanel.refresh()
      }
    },
    // 添加页面容器
    addPageContainer () {
      this.$refs.allModal.changeModalVisible('addPage')
    },
    // 架构重命名
    rename (id, newName) {
      const target = lowcodeUtils.getConfig(id, this.config)
      if (target.type === 'page') {
        target.title = newName
      } else {
        target.name = newName
      }
      this.refreshOrganization()
    },
    // 架构树新增
    handleTreeAdd (id, type) {
      // 如果目标是行，则添加容器
      if (type === 'container') {
        // 获取行对象
        const rowConfig = lowcodeUtils.getPageIdAndRowIndexByRowId(id)
        const row = lowcodeUtils.getRowByRowId(rowConfig.pageId, rowConfig.rowIndex, this.config)
        // 如果是空行，直接添加容器
        if (row.body.length === 0) {
          row.body.push(lowcodeUtils.newContainer())
        } else {
          // 如果不是空行，将最后一个元素的span平分给新的容器
          const lastSpan = row.body[row.body.length - 1].span
          const firstSpan = Math.round(lastSpan / 2)
          const newSpan = lastSpan - firstSpan
          row.body[row.body.length - 1].span = firstSpan
          row.body.push(lowcodeUtils.newContainer(newSpan))
        }
      } else {
        // 如果不是行，则添加行
        const page = lowcodeUtils.getPageConfigById(id, this.config)
        page.body.push(
          {
            id: page.id + '_' + page.body.length,
            config: {
              align: 'top',
              gutter: 0,
              justify: 'start'
            },
            type: 'row',
            body: [
              lowcodeUtils.newContainer()
            ]
          }
        )
      }
      this.refreshOrganization()
    },
    // 为架构树过滤配置，只显示当前激活的页面配置
    filterOrganizationConfig () {
      const result = { page: [] }
      this.config.page.forEach(page => {
        if (page.id === this.activeMainPage) {
          result.page.push(page)
        }
      })
      return result
    },
    // 处理拆分
    handleSplit (id, isVertical) {
      // 获取目标对象，目标行和对象在行中的Index
      const target = lowcodeUtils.getComponentConfig(id, this.config)
      const row = lowcodeUtils.getRowConfigByComponentId(id, this.config)
      let index
      for (let i = 0; i < row.body.length; i++) {
        if (row.body[i].id === id) {
          index = i
          break
        }
      }
      // 将目标对象缓存
      const cache = JSON.parse(JSON.stringify(target))
      // 是否为垂直拆分
      if (isVertical) {
        const newPageId = 'container_page_' + lowcodeUtils.nanoidWithoutSymbol(2)
        // 垂直拆分，嵌套page容器
        const temp = {
          type: 'container_page',
          span: cache.span,
          id: 'container_' + lowcodeUtils.nanoidWithoutSymbol(6),
          page: [
            {
              id: newPageId,
              type: 'page',
              body: [
                {
                  id: newPageId + '_0',
                  type: 'row',
                  config: {
                    align: 'top',
                    gutter: 0,
                    justify: 'start'
                  },
                  body: []
                }
              ]
            }
          ]
        }
        cache.span = 24
        // 第一行放缓存的原始对象
        temp.page[0].body[0].body.push(cache)
        // 第二行新增容器
        temp.page[0].body[1] = {
          id: newPageId + '_1',
          type: 'row',
          config: {
            align: 'top',
            gutter: 0,
            justify: 'start'
          },
          body: []
        }
        temp.page[0].body[1].body.push(lowcodeUtils.newContainer())
        row.body.splice(index, 1, temp)
      } else {
        // 如果是水平拆分
        // 将原先对象span一分为二，添加容器
        const outerSpan = cache.span
        const firstSpan = Math.round(outerSpan / 2)
        const secondSpan = outerSpan - firstSpan
        cache.span = firstSpan
        row.body.splice(index, 1, cache, lowcodeUtils.newContainer(secondSpan))
      }
      this.refreshOrganization()
    },
    // 复制粘贴组件
    handlePasteItem (id, copyCache, type) {
      const target = lowcodeUtils.getConfig(id, this.config)
      // 页面中插入行
      if (type === 'page-row') {
        const content = copyCache.content
        const pageId = target.id
        content.id = pageId + '_' + target.body.length
        target.body.push(content)
      } else if (type === 'row-item') {
        // 行中插入组件
        target.body.push(copyCache.content)
      } else if (type === 'page') {
        // 复制页面
        this.config.page.push(copyCache)
        this.$message.success('复制成功！')
      }
      this.refreshOrganization()
    },
    // 点击架构树
    treeOrganizationClick (id) {
      // 如果是反选
      if (id === null) {
        // 清除编辑框
        this.editorPropertiesConfig = {}
        this.$store.commit('setTargetContainer', undefined)
        // 清除容器select
        lowcodeUtils.unCheckAll(this.config)
        return
      }
      let target
      if (id.includes('container_page')) {
        // 长度大于17证明是容器页面的行
        if (id.length > 17) {
          const rowConfig = lowcodeUtils.getPageIdAndRowIndexByRowId(id)
          target = lowcodeUtils.getRowByRowId(rowConfig.pageId, rowConfig.rowIndex, this.config)
        } else {
          target = lowcodeUtils.getContainerPageOuterByContainerPageId(id, this.config)
        }
      } else {
        // 包含page表示选中的是某一行
        if (id.includes('page')) {
          const rowConfig = lowcodeUtils.getPageIdAndRowIndexByRowId(id)
          target = lowcodeUtils.getRowByRowId(rowConfig.pageId, rowConfig.rowIndex, this.config)
        } else {
          target = lowcodeUtils.getComponentConfig(id, this.config)
        }
      }
      // 将组件选中
      this.clickComponentInEditor(target)
      if (!id.includes('container') && !(id.includes('page') && id.length > 11)) {
        this.twink(id)
      }
    },
    // 架构树拖拽事件
    handleTreeDrag (dragKey, dropKey, dragLevel, dropLevel, dropPosition, dragType) {
      // 只有三种情况可以拖拽
      // 1.平级挪
      // 2.高一级插
      // 3.行插子页面
      let dragEle, rowConfig, father, cache, deleteIndex

      // 复制移动组件，并将其从原位删除
      switch (dragLevel.type) {
        case 'row':
          rowConfig = lowcodeUtils.getPageIdAndRowIndexByRowId(dragKey)
          father = lowcodeUtils.getPageConfigById(rowConfig.pageId, this.config)
          dragEle = father.body[rowConfig.rowIndex]
          // 复制原始
          cache = JSON.parse(JSON.stringify(dragEle))
          // 删除原始
          deleteIndex = rowConfig.rowIndex
          father.body.splice(deleteIndex, 1, { placeHold: true })
          break
        case 'item':
          father = lowcodeUtils.getRowConfigByComponentId(dragKey, this.config).body
          dragEle = lowcodeUtils.getComponentConfig(dragKey, this.config)
          // 复制原始
          cache = JSON.parse(JSON.stringify(dragEle))
          // 删除原始
          for (let i = 0; i < father.length; i++) {
            const item = father[i]
            if (item.id === dragKey) {
              deleteIndex = i
              break
            }
          }
          father.splice(deleteIndex, 1, { placeHold: true })
          break
        case 'container_page':
          father = lowcodeUtils.getContainerPageRow(dragKey, this.config).body
          dragEle = lowcodeUtils.getContainerPageOuterByContainerPageId(dragKey, this.config)
          // 复制原始
          cache = JSON.parse(JSON.stringify(dragEle))
          // 删除原始
          for (let i = 0; i < father.length; i++) {
            const item = father[i]
            if (item.type === 'container_page' && item.page[0].id === dragKey) {
              deleteIndex = i
              break
            }
          }
          father.splice(deleteIndex, 1, { placeHold: true })
          break
      }

      let target, dropConfig, targetCache, targetIndex
      switch (dragType) {
        case 'move':
          // 1. 平级挪
          switch (dragLevel.type) {
            case 'row':
              // 移动行
              // 拿到父容器和目标Index
              dropConfig = lowcodeUtils.getPageIdAndRowIndexByRowId(dropKey)
              target = lowcodeUtils.getPageConfigById(dropConfig.pageId, this.config)
              // 保存目标
              targetCache = target.body[dropConfig.rowIndex]
              // 插入
              if (dropPosition < 0) {
                target.body.splice(dropConfig.rowIndex, 1, cache, targetCache)
              } else {
                target.body.splice(dropConfig.rowIndex, 1, targetCache, cache)
              }
              // 清理占位
              for (let i = 0; i < father.body.length; i++) {
                const item = father.body[i]
                if (item.placeHold) {
                  father.body.splice(i, 1)
                  break
                }
              }
              break
            case 'item':
              // 移动组件
              // 拿到父容器和目标Index
              if (dropLevel.type === 'container_page') {
                target = lowcodeUtils.getContainerPageRow(dropKey, this.config)
                for (let i = 0; i < target.body.length; i++) {
                  const item = target.body[i]
                  if (item.type === 'container_page' && item.page[0].id === dropKey) {
                    targetIndex = i
                    break
                  }
                }
              } else {
                target = lowcodeUtils.getRowByComponentId(dropKey, this.config)
                for (let i = 0; i < target.body.length; i++) {
                  const item = target.body[i]
                  if (item.id === dropKey) {
                    targetIndex = i
                    break
                  }
                }
              }
              // 保存目标
              targetCache = target.body[targetIndex]
              // 插入
              if (dropPosition < 0) {
                target.body.splice(targetIndex, 1, cache, targetCache)
              } else {
                target.body.splice(targetIndex, 1, targetCache, cache)
              }
              // 清理占位
              for (let i = 0; i < father.length; i++) {
                const item = father[i]
                if (item.placeHold) {
                  father.splice(i, 1)
                  break
                }
              }
              if (father.length === 0) {
                father.push(lowcodeUtils.newContainer())
              }
              break
            case 'container_page':
              // 移动容器页面
              // 拿到父容器和目标Index
              if (dropLevel.type === 'container_page') {
                target = lowcodeUtils.getContainerPageRow(dropKey, this.config)
                for (let i = 0; i < target.body.length; i++) {
                  const item = target.body[i]
                  if (item.type === 'container_page' && item.page[0].id === dropKey) {
                    targetIndex = i
                    break
                  }
                }
              } else {
                target = lowcodeUtils.getRowByComponentId(dropKey, this.config)
                for (let i = 0; i < target.body.length; i++) {
                  const item = target.body[i]
                  if (item.id === dropKey) {
                    targetIndex = i
                    break
                  }
                }
              }
              // 保存目标
              targetCache = target.body[targetIndex]
              // 插入
              if (dropPosition < 0) {
                target.body.splice(targetIndex, 1, cache, targetCache)
              } else {
                target.body.splice(targetIndex, 1, targetCache, cache)
              }
              // 清理占位
              for (let i = 0; i < father.length; i++) {
                const item = father[i]
                if (item.placeHold) {
                  father.splice(i, 1)
                  break
                }
              }
              if (father.length === 0) {
                father.push(lowcodeUtils.newContainer())
              }
          }
          break
        case 'higher':
          // 2.高一级插
          switch (dragLevel.type) {
            case 'row':
              // 行插页
              target = lowcodeUtils.getPageConfigById(dropKey, this.config)
              target.body.push(cache)
              for (let i = 0; i < father.body.length; i++) {
                const item = father.body[i]
                if (item.placeHold) {
                  father.body.splice(i, 1)
                  break
                }
              }
              break
            case 'item':
              // 组件插行
              rowConfig = lowcodeUtils.getPageIdAndRowIndexByRowId(dropKey)
              target = lowcodeUtils.getRowByRowId(rowConfig.pageId, rowConfig.rowIndex, this.config)
              target.body.push(cache)
              for (let i = 0; i < father.length; i++) {
                if (father[i].placeHold) {
                  father.splice(i, 1)
                  break
                }
              }
              if (father.length === 0) {
                father.push(lowcodeUtils.newContainer())
              }
              break
            case 'container_page':
              // 子页面插行
              rowConfig = lowcodeUtils.getPageIdAndRowIndexByRowId(dropKey)
              target = lowcodeUtils.getRowByRowId(rowConfig.pageId, rowConfig.rowIndex, this.config)
              target.body.push(cache)
              for (let i = 0; i < father.length; i++) {
                if (father[i].placeHold) {
                  father.splice(i, 1)
                  break
                }
              }
              if (father.length === 0) {
                father.push(lowcodeUtils.newContainer())
              }
              break
          }
          break
        case 'rowToContainer':
          // 3.行插子页面
          target = lowcodeUtils.getContainerPageOuterByContainerPageId(dropKey, this.config)
          target.page[0].body.push(cache)
          for (let i = 0; i < father.body.length; i++) {
            const item = father.body[i]
            if (item.placeHold) {
              father.body.splice(i, 1)
              break
            }
          }
          break
        case 'switch':
          switch (dragLevel.type) {
            case 'row':
              // 拿到父容器和目标Index
              dropConfig = lowcodeUtils.getPageIdAndRowIndexByRowId(dropKey)
              target = lowcodeUtils.getPageConfigById(dropConfig.pageId, this.config)
              // 保存目标
              targetCache = target.body[dropConfig.rowIndex]
              // 替换目标
              target.body.splice(dropConfig.rowIndex, 1, cache)
              // 将目标替换到原始
              for (let i = 0; i < father.body.length; i++) {
                const item = father.body[i]
                if (item.placeHold) {
                  father.body.splice(i, 1, targetCache)
                  break
                }
              }
              break
            case 'item':
              // 拿到父容器和目标Index
              if (dropLevel.type === 'container_page') {
                target = lowcodeUtils.getContainerPageRow(dropKey, this.config)
                for (let i = 0; i < target.body.length; i++) {
                  const item = target.body[i]
                  if (item.type === 'container_page' && item.page[0].id === dropKey) {
                    targetIndex = i
                    break
                  }
                }
              } else {
                target = lowcodeUtils.getRowByComponentId(dropKey, this.config)
                for (let i = 0; i < target.body.length; i++) {
                  const item = target.body[i]
                  if (item.id === dropKey) {
                    targetIndex = i
                    break
                  }
                }
              }
              // 保存目标
              targetCache = target.body[targetIndex]
              // 替换目标
              target.body.splice(targetIndex, 1, cache)
              // 将目标替换到原始
              for (let i = 0; i < father.length; i++) {
                const item = father[i]
                if (item.placeHold) {
                  father.splice(i, 1, targetCache)
                  break
                }
              }
              break
            case 'container_page':
              // 移动容器页面
              // 拿到父容器和目标Index
              if (dropLevel.type === 'container_page') {
                target = lowcodeUtils.getContainerPageRow(dropKey, this.config)
                for (let i = 0; i < target.body.length; i++) {
                  const item = target.body[i]
                  if (item.type === 'container_page' && item.page[0].id === dropKey) {
                    targetIndex = i
                    break
                  }
                }
              } else {
                target = lowcodeUtils.getRowByComponentId(dropKey, this.config)
                for (let i = 0; i < target.body.length; i++) {
                  const item = target.body[i]
                  if (item.id === dropKey) {
                    targetIndex = i
                    break
                  }
                }
              }
              // 保存目标
              targetCache = target.body[targetIndex]
              // 替换目标
              target.body.splice(targetIndex, 1, cache)
              // 将目标替换到原始
              for (let i = 0; i < father.length; i++) {
                const item = father[i]
                if (item.placeHold) {
                  father.splice(i, 1, targetCache)
                  break
                }
              }
              break
          }
      }

      this.refreshOrganization()
    },
    // 主页面标签切换
    handleMainPageMenuChange (value) {
      // 如果和之前选择的不一样
      if (value.key !== this.activeMainPage) {
        // 清空属性编辑
        this.editorPropertiesConfig = {}
        this.$store.commit('setTargetContainer', undefined)
        // 切换菜单
        this.activeMainPage = value.key
        for (let i = 0; i < this.config.page.length; i++) {
          if (this.config.page[i].id === this.activeMainPage) {
            this.activeMainPageType = this.config.page[i].type
            this.refreshOrganization()
            return
          }
        }
      }
    },
    // 将页面标签类型渲染为对应的文字
    determinePageType (type) {
      return lowcodeUtils.resolvePageType(type)
    },
    // 刷新架构
    refreshOrganization () {
      this.showPageOrganization = false
      this.$nextTick(() => {
        this.showPageOrganization = true
      })
    },
    // 拖拽完成后，将新的span赋值
    handleDrag (targetEle, nextEle) {
      const target = lowcodeUtils.getComponentConfig(targetEle.id, this.config.page)
      const targetNext = lowcodeUtils.getComponentConfig(nextEle.id, this.config.page)
      target.span = targetEle.span
      targetNext.span = nextEle.span
    },
    // 删除组件
    deleteComponentInTree (id, type) {
      if (type === 'page') {
        const page = lowcodeUtils.getPageConfigById(id, this.config)
        this.deletePage(page)
      } else if (type === 'component') {
        this.deleteComponent(id)
      } else if (type === 'row') {
        this.deleteRow(id)
      } else if (type === 'container_page') {
        this.deleteContainerPage(id)
      }
    },
    // 删除容器页面
    deleteContainerPage (id) {
      const target = lowcodeUtils.getContainerPageOuterByContainerPageId(id, this.config)
      target.type = 'container'
      delete target.page
      this.$store.commit('setTargetContainer', undefined)
      this.editorPropertiesConfig = {}
      this.refreshOrganization()
    },
    // 删除行
    deleteRow (id) {
      const pageId = id.substring(0, id.length - 2)
      const rowId = id.substring(id.length - 1)
      const page = lowcodeUtils.getPageConfigById(pageId, this.config)
      page.body.splice(rowId, 1)
      // 如果该列下没有任何内容，则将该列还原为容器
      if (page.body.length === 0) {
        const outerContainer = lowcodeUtils.getContainerPageOuterByContainerPageId(page.id, this.config)
        outerContainer.type = 'container'
        outerContainer.selected = false
        delete outerContainer.page
      }
      this.$store.commit('setTargetContainer', undefined)
      this.editorPropertiesConfig = {}
      this.refreshOrganization()
    },
    // 删除页面容器
    deletePage (page) {
      // 清空页面下所有组件的注册信息
      page.body.forEach(row => {
        row.body.forEach(item => {
          if (item.type === 'container_page') {
            // 如果是容器页面，递归
            this.deletePage(item.page)
          } else {
            delete this.$children[0]._provided.componentsMap[item.id]
          }
        })
      })
      for (let i = 0; i < this.config.page.length; i++) {
        if (this.config.page[i].id === page.id) {
          this.config.page.splice(i, 1)
          this.$store.commit('setTargetContainer', undefined)
          this.editorPropertiesConfig = {}
          this.refreshOrganization()
          return
        }
      }
    },
    // 删除组件
    deleteComponent (id, addOnSpan = true) {
      const row = lowcodeUtils.getRowConfigByComponentId(id, this.config)
      const target = lowcodeUtils.getComponentConfig(id, this.config)
      const deletedSpan = target.span
      let index
      for (let i = 0; i < row.body.length; i++) {
        if (target.id === row.body[i].id) {
          index = i
          break
        }
      }
      row.body.splice(index, 1)
      if (addOnSpan) {
        // 如果该组件之前还有组件，将该组件的span加给之前的组件
        if (index !== 0) {
          row.body[index - 1].span += deletedSpan
        } else if (row.body.length > 0) {
          row.body[0].span += deletedSpan
        }
        if (row.body[index - 1].span > 24) {
          row.body[index - 1].span = 24
        }
      }
      if (row.body.length === 0) {
        row.body.push(lowcodeUtils.newContainer())
      }
      // 从注册的全局Map中删除
      delete this.$children[0]._provided.componentsMap[id]
      this.$store.commit('setTargetContainer', undefined)
      this.editorPropertiesConfig = {}
      this.refreshOrganization()
    },
    // 容器删除
    handleContainerDelete (id) {
      let index
      const row = lowcodeUtils.getRowConfigByComponentId(id, this.config)
      for (let i = 0; i < row.body.length; i++) {
        const item = row.body[i]
        if (item.id === id) {
          index = i
          break
        }
      }
      row.body.splice(index, 1)
      this.$store.commit('setTargetContainer', undefined)
      // 如果删除后只剩一个容器，将该容器span设置为24
      if (row.body.length === 1) {
        row.body[0].span = 24
      } else if (row.body.length === 0) {
        row.body.push(lowcodeUtils.newContainer())
      }
      this.refreshOrganization()
    },
    // 切换预览模式
    previewModeActive () {
      this.preview = true
    },
    // 切换编辑模式
    editModeActive () {
      this.preview = false
    },
    // 选中某个组件
    clickComponentInEditor (configItem) {
      this.disableEventEditor = false
      if (!configItem) {
        return
      }
      // 同步选中架构
      // 将选中的节点清空，在$nextTick再赋值，保证组件能watch到改变
      this.selectTreeNode = undefined
      if (configItem.type === 'container_page') {
        this.$nextTick(() => {
          this.selectTreeNode = 'container_page_' + configItem.page[0].id
        })
      } else if (configItem.type === 'row' || !configItem.type) {
        const rowConfig = lowcodeUtils.getPageIdAndRowIndexByRowId(configItem.id)
        rowConfig.rowIndex++
        this.$nextTick(() => {
          this.selectTreeNode = 'row_' + rowConfig.pageId + '_' + rowConfig.rowIndex
        })
      } else {
        this.$nextTick(() => {
          this.selectTreeNode = configItem.id
        })
        lowcodeUtils.unCheckAll(this.config)
      }
      this.editorPropertiesConfig = {}
      // 如果选中的是容器
      if (configItem.type === 'container') {
        // 将所有已选中组件取消选择
        lowcodeUtils.unCheckAll(this.config)
        // 将目标设置为选定
        configItem.selected = true
        this.$store.commit('setTargetContainer', configItem)
        this.editorPropertiesConfig = configItem
        this.disableEventEditor = true
        this.editorPropertiesConfig.props = {}
        return
      }
      // 如果选中的是容器页面
      if (configItem.type === 'container_page') {
        // 选中容器页面中所有组件
        lowcodeUtils.unCheckAll(this.config)
        configItem.page.forEach(page => {
          page.body.forEach(row => {
            lowcodeUtils.checkRowAll(row)
          })
        })
        this.editorPropertiesConfig = configItem
        this.disableEventEditor = true
        this.editorPropertiesConfig.props = {}
        return
      }

      // 如果选中的是行
      if (configItem.type === 'row' || !configItem.type) {
        lowcodeUtils.checkRowAll(configItem, this.config)
        this.editorPropertiesConfig = configItem
        this.disableEventEditor = true
        this.editorPropertiesConfig.props = {}
        return
      }

      if (configItem.type === 'tabs') {
        console.warn('tabs', configItem)
        this.editorPropertiesConfig = configItem
        this.disableEventEditor = true
        this.editorPropertiesConfig.props = {}
        return
      }
      // 如果是组件对象
      // 拿注册的配置
      const configInJson = lowcodeUtils.getEditorConfigByType(configItem.type)
      if (configInJson) {
        this.editorPropertiesConfig = configItem
        // 为编辑器变量初始化
        if (configInJson.properties) {
          if (!this.editorPropertiesConfig.props) {
            this.editorPropertiesConfig.props = {}
          }
          const editableKeys = Object.keys(configInJson.properties)
          editableKeys.forEach(editableKey => {
            // 如果该值并不存在，则初始化
            if (!this.editorPropertiesConfig.props[editableKey]) {
              this.editorPropertiesConfig.props[editableKey] = ''
            } else {
              if (typeof this.editorPropertiesConfig.props[editableKey] === 'object') {
                this.editorPropertiesConfig.props[editableKey] = JSON.stringify(this.editorPropertiesConfig.props[editableKey])
              }
            }
          })
        }
        // 为编辑器事件初始化
        if (configInJson.selfEvent) {
          if (!this.editorPropertiesConfig.selfEvent) {
            this.editorPropertiesConfig.selfEvent = []
            configInJson.selfEvent.forEach(everyEvent => {
              this.editorPropertiesConfig.selfEvent.push(everyEvent)
            })
          }
        }
      } else {
        this.editorPropertiesConfig = 'unregistered'
      }
    },
    // 架构树点击某个节点后，在渲染器中，让组件闪烁
    twink (id) {
      const allRefs = Object.keys(this.$refs)
      allRefs.forEach(ref => {
        if (this.$refs[ref].twink) {
          this.$refs[ref].twink(id)
        }
      })
    },
    // 点击测试按钮
    test () {
      // 输出当前配置，和组件注册Map
      console.warn('config', this.config)
      console.warn('map', this.$children[0]._provided.componentsMap)
    },
    // 点击导出按钮
    exportConfig () {
      console.warn('导出', this.config)
      this.$emit('exportConfig', this.config)
    }
  },
  mounted () {
    // 将mixin中已经实现的通用响应方法添加
    this.supportedEventType = [...lowcodeComponentMixin.supportedEventType]
    let cache = {}
    if (!this.originalConfig.config) {
      cache = { page: [] }
    } else {
      cache = JSON.parse(JSON.stringify(this.originalConfig.config))
    }
    // 深拷贝外侧传来的配置
    this.$store.commit('setConfig', cache)
    const tempConfig = {
      page: [
        {
          id: 'page_deowoe',
          type: 'page',
          title: '1',
          body: [
            {
              id: 'page_deowoe_0',
              config: {
                align: 'top',
                gutter: 0,
                justify: 'start'
              },
              type: 'row',
              body: [
                {
                  type: 'XFormTable',
                  selected: false,
                  span: 24,
                  id: 'XFormTable_cWmejz',
                  props: {
                    queryParamsName: 'crud_dictionary_manage',
                    serviceName: 'af-system'
                  },
                  selfEvent: [
                    'action'
                  ],
                  onEvent: {
                    action: [
                      {
                        emitType: 'action',
                        eventType: 'changeProps',
                        target: 'XDescriptions_nE5IcB',
                        targetKey: 'content'
                      },
                      {
                        emitType: 'action',
                        eventType: 'showDraw',
                        visible: 'open',
                        containerId: 'page_e12Xon'
                      }
                    ]
                  }
                }
              ]
            }
          ]
        },
        {
          id: 'page_e12Xon',
          type: 'draw',
          title: '2',
          width: '70%',
          body: [
            {
              id: 'page_e12Xon_0',
              config: {
                align: 'top',
                gutter: 0,
                justify: 'start'
              },
              type: 'row',
              body: [
                {
                  type: 'XDescriptions',
                  selected: false,
                  span: 24,
                  id: 'XDescriptions_nE5IcB',
                  props: {
                    title: '详情',
                    content: {
                      d_id: 111,
                      d_f_remark: '-',
                      d_f_name: '设备区域',
                      d_f_key: '设备区域',
                      d_f_input_date: '2023-03-20 13:40:54'
                    },
                    configName: 'test_lowCode_descriptionConfig',
                    serviceName: 'af-system',
                    getRealData: false
                  },
                  selfEvent: []
                }
              ]
            },
            {
              id: 'page_e12Xon_1',
              config: {
                align: 'top',
                gutter: 0,
                justify: 'start'
              },
              type: 'row',
              body: [
                {
                  type: 'tabs',
                  span: 24,
                  id: 'Tabs_TFg731',
                  props: {},
                  body: [
                    {
                      key: 'Tabs_TFg731_1',
                      label: '1',
                      type: 'tab',
                      body: {
                        type: 'container_page',
                        span: 24,
                        id: 'container_ZX1Ixz',
                        page: [
                          {
                            id: 'container_page_ks',
                            type: 'page',
                            body: [
                              {
                                id: 'container_page_ks_0',
                                type: 'row',
                                config: {
                                  align: 'top',
                                  gutter: 0,
                                  justify: 'start'
                                },
                                body: [
                                  {
                                    type: 'container',
                                    selected: true,
                                    span: 24,
                                    id: 'container_UNOr8I',
                                    props: {}
                                  }
                                ]
                              }
                            ]
                          }
                        ]
                      }
                    },
                    {
                      key: '1',
                      label: '22',
                      type: 'tab',
                      body: {
                        type: 'container_page',
                        span: 24,
                        id: 'container_ToXInv',
                        page: [
                          {
                            id: 'container_page_U0',
                            type: 'page',
                            body: [
                              {
                                id: 'container_page_U0_0',
                                type: 'row',
                                config: {
                                  align: 'top',
                                  gutter: 0,
                                  justify: 'start'
                                },
                                body: [
                                  {
                                    type: 'container',
                                    selected: true,
                                    span: 24,
                                    id: 'container_sSWXao',
                                    props: {}
                                  }
                                ]
                              }
                            ]
                          }
                        ]
                      }
                    }
                  ],
                  selected: false
                }
              ]
            }
          ]
        }
      ]
    }
    this.$store.commit('setConfig', tempConfig)
    this.refreshOrganization()
  },
  computed: {
    config () {
      return this.$store.state.lowCode.config
    },
    targetContainer () {
      return this.$store.state.lowCode.targetContainer
    }
  }
}
</script>

<style scoped lang="less">

</style>
