import { Graph, Cell, Node, Path } from '@antv/x6'
import Hierarchy from '@antv/hierarchy'

export default {
  data() {
    return {
      mindMapDataCurrent:{},
      positionCurrent:{},
      addTypeCurrent:'',
      styleConfig:{},
      mindmapAssistData:{
        mindmapDataUse:[],
        deletedMindmapData:[],// 用于撤销删除，恢复删除掉的数据
        mindmapDataRecoverUse:[],//用于 重做时 恢复思维导图数据
      },
    }
  },
  mounted() {
    
  },
  created() {
    this.styleConfig=this.$store.state.sand.styleConfig
    // 中心主题
    Graph.registerNode(
      'mindmap-topic',          
      {
        inherit: 'rect',
        markup: [
          {
            tagName: 'rect',
            selector: 'body',
          },
          {
            tagName: 'image',
            selector: 'leftImg',
          },
          {
            tagName: 'image',
            selector: 'rightImg',
          },
          {
            tagName: 'text',
            selector: 'text',
          },
        ],
        attrs: {
          body: {
            rx: 6,
            ry: 6,
            strokeWidth: 1,
            width:100,
            height:50
          },
          leftImg: {
            ref: 'body',
            refX: -16,
            refY: '50%',
            refY2: -8,
            width: 16,
            height: 16,
            'xlink:href':
              'https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*SYCuQ6HHs5cAAAAAAAAAAAAAARQnAQ',
            event: 'add:topic:left',
            class: 'left-topic-image',
          },
          rightImg: {
            ref: 'body',
            refX: '100%',
            refY: '50%',
            refY2: -8,
            width: 16,
            height: 16,
            'xlink:href':
              'https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*SYCuQ6HHs5cAAAAAAAAAAAAAARQnAQ',
            event: 'add:topic:right',
            class: 'right-topic-image',
          },
          text: {
            fontSize: 14,
            fill: this.$store.state.sand.styleConfig.color,
            textWrap:{
              width:-10
            }
          }
        },
      },
      true,
    )
    // 左分支主题
    Graph.registerNode(
      'mindmap-topic-left',          
      {
        inherit: 'rect',
        markup: [
          {
            tagName: 'rect',
            selector: 'body',
          },
          {
            tagName: 'image',
            selector: 'leftImg',
          },
          {
            tagName: 'image',
            selector: 'rightImg',
          },
          {
            tagName: 'text',
            selector: 'text',
          },
        ],
        attrs: {
          body: {
            rx: 6,
            ry: 6,
            strokeWidth: 1,
            width:100,
            height:50
          },
          leftImg: {
            ref: 'body',
            refX: -16,
            refY: '50%',
            refY2: -8,
            width: 16,
            height: 16,
            'xlink:href':
              'https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*SYCuQ6HHs5cAAAAAAAAAAAAAARQnAQ',
            event: 'add:topic:left',
            class: 'left-topic-image',
          },
          text: {
            fontSize: 14,
            fill: this.$store.state.sand.styleConfig.color,
            textWrap:{
              width:-10
            }
          }
        },
      },
      true,
    )    
    // 右分支主题
    Graph.registerNode(
      'mindmap-topic-right',          
      {
        inherit: 'rect',
        markup: [
          {
            tagName: 'rect',
            selector: 'body',
          },
          {
            tagName: 'image',
            selector: 'leftImg',
          },
          {
            tagName: 'image',
            selector: 'rightImg',
          },
          {
            tagName: 'text',
            selector: 'text',
          },
        ],
        attrs: {
          body: {
            rx: 6,
            ry: 6,
            strokeWidth: 1,
            width:100,
            height:50
          },
          rightImg: {
            ref: 'body',
            refX: '100%',
            refY: '50%',
            refY2: -8,
            width: 16,
            height: 16,
            'xlink:href':
              'https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*SYCuQ6HHs5cAAAAAAAAAAAAAARQnAQ',
            event: 'add:topic:right',
            class: 'right-topic-image',
          },
          text: {
            fontSize: 14,
            fill:this.$store.state.sand.styleConfig.color,
            textWrap:{
              width:-10
            }
          }
        },
      },
      true,
    )
    // 连接器
    Graph.registerConnector(
      'mindmap',
      (sourcePoint, targetPoint, routerPoints, options) => {
        const midX = sourcePoint.x + 10
        // const midY = sourcePoint.y
        const ctrX = (targetPoint.x - midX) / 5 + midX
        const ctrY = targetPoint.y
        const pathData = `
        M ${sourcePoint.x} ${sourcePoint.y}
        Q ${ctrX} ${ctrY} ${targetPoint.x} ${targetPoint.y}
        `
        return options.raw ? Path.parse(pathData) : pathData
      },
      true,
    )

    // 边
    Graph.registerEdge(
      'mindmap-edge',
      {
        inherit: 'edge',
        connector: {
          name: 'mindmap',
        },
        attrs: {
          line: {
            targetMarker: false,
            strokeWidth: 2,
          },
        },
        zIndex: 0,
      },
      true,
    )
  },
  methods: {
    setGraph(){
      // 添加左边节点
      this.graph.on('add:topic:left', ({ node }) => {
        if(this.operationType=='view') return 
        const { id } = node
        this.setCurrent(id)
        const type = node.prop('type')
        if (this.addChildNode(id, type,'left')) {
          this.mindMapRender()      
        }
      })
      // 添加右边节点
      this.graph.on('add:topic:right', ({ node }) => {
        if(this.operationType=='view') return 
        const { id } = node
        this.setCurrent(id)
        const type = node.prop('type')
        if (this.addChildNode(id, type,'right')) {
          this.mindMapRender()      
        }
      })
      // 改变大小 - 更新数据源
      this.graph.on('node:change:size', (args) => { 
        if(this.operationType=='view') return 
        if(args.node.shape.indexOf('mindmap')!==-1){
          let ids = args.node.id.split('-')
					let mindmapDataIndex = this.mindmapAssistData.mindmapDataUse.findIndex(mindmap => mindmap.mindmapData.id == ids[0])
					let mindMapDataCurrent = this.mindmapAssistData.mindmapDataUse[mindmapDataIndex]?this.mindmapAssistData.mindmapDataUse[mindmapDataIndex].mindmapData:{}

					let findId = ids[0]

					for (let i = 1; i < ids.length; i++) {
						const element = ids[i];
						findId = findId+'-'+element
						mindMapDataCurrent=mindMapDataCurrent.children.find(it => it.id==findId)
					}

					mindMapDataCurrent.width = args.node.size().width
					mindMapDataCurrent.height = args.node.size().height
        }
      })
      // 改变位置 - 更新数据源
      this.graph.on('node:change:position', (args) => { 
        if(this.operationType=='view') return 
        if(args.node.shape.indexOf('mindmap')!==-1 && Number(args.node.id)){

          let index = this.mindmapAssistData.mindmapDataUse.findIndex(it =>it.mindmapData.id == args.node.id)
          if(index!=-1){
            this.mindmapAssistData.mindmapDataUse[index].position = args.current
          }
        }
      })
      // tab 键添加节点-右边的 - 更新数据源
      this.graph.bindKey('tab', (e) => {
        if(this.operationType=='view') return 
        e.preventDefault()
        const selectedNodes = this.graph.getSelectedCells().filter((item) => {
          return item.shape.indexOf('mindmap')!=-1 && item.isNode()
        })
        if (selectedNodes.length) {
          const node = selectedNodes[0]
          this.setCurrent(node.id)
          let type = node.prop('type')
          let direction = node.shape.indexOf('left')!=-1?'left':'right'
          if (this.addChildNode(node.id, type,direction)) {
            this.mindMapRender()
          }
        }
      })
      // 撤销 - 入栈
      this.graph.history.on('undo', (args) => { 
        let mindmapNodes=args.cmds.filter(it => it.data.props && it.data.props.shape.indexOf('mindmap')!=-1 && it.data.node)
        if(!(mindmapNodes && mindmapNodes.length>0)) return 
        let mindmapUndoType=mindmapNodes[0].event
        
        if(mindmapUndoType=="cell:added"){
          this.mindmapDeleteRecordPush(mindmapNodes)
        }else if(mindmapUndoType=="cell:removed"){
          this.mindmapAddRecordPush()
        }
      })
      // 重做，出栈
      this.graph.history.on('redo', (args) => { 
        let mindmapNodes=args.cmds.filter(it => it.data.props && it.data.props.shape.indexOf('mindmap')!=-1 && it.data.node)
        if(!(mindmapNodes && mindmapNodes.length>0)) return
        this.mindmapRecover()
      })
    },
    // 生成思维导图初始化数据
    generateMindmapData(position,addType){
      let beId=this.mindmapAssistData.mindmapDataUse.length>0?
      parseInt(this.mindmapAssistData.mindmapDataUse[this.mindmapAssistData.mindmapDataUse.length-1].mindmapData.id)+1+'':'1'
      let mindmapData={
        id: beId,
        type: 'topic',
        label: '中心主题',
        width: 160,
        height: 50,
        direction:'double',
        children: [
          {
            id: beId+'-1',
            type: 'topic-branch',
            label: '分支主题1',
            width: 100,
            height: 40,
            direction:'left',
            children: [
              {
                id: beId+'-1-1',
                type: 'topic-child',
                label: '子主题1',
                width: 60,
                height: 30,
                direction:'left',
              },
              {
                id: beId+'-1-2',
                type: 'topic-child',
                label: '子主题2',
                width: 60,
                height: 30,
                direction:'left',
              },
            ],
          },
          {
            id: beId+'-2',
            type: 'topic-branch',
            label: '分支主题2',
            width: 100,
            height: 40,
            direction:'right',
          },
        ],
      }
      this.mindmapAssistData.mindmapDataUse.push({mindmapData,position,addType})
    },
    // 通过id设置当前操作的思维导图
    setCurrent(id){
      let rootId = id.split('-')[0]
      let index = this.mindmapAssistData.mindmapDataUse.findIndex(it =>it.mindmapData.id == rootId)
      this.mindMapDataCurrent = this.mindmapAssistData.mindmapDataUse[index]?this.mindmapAssistData.mindmapDataUse[index].mindmapData:{}
      this.positionCurrent = this.mindmapAssistData.mindmapDataUse[index]?this.mindmapAssistData.mindmapDataUse[index].position:{x:0,y:0}
      this.addTypeCurrent = this.mindmapAssistData.mindmapDataUse[index]?this.mindmapAssistData.mindmapDataUse[index].addType:'singleMindmap'
    },
    mindMapRender(i){
      this.graph.startBatch('renderMindmap')
      let mindMapType = i || i==0?this.mindmapAssistData.mindmapDataUse[i].addType:this.addTypeCurrent
      this.mindMapDataCurrent = i || i==0?this.mindmapAssistData.mindmapDataUse[i].mindmapData:this.mindMapDataCurrent
      this.positionCurrent = i || i==0?this.mindmapAssistData.mindmapDataUse[i].position:this.positionCurrent
      const result = Hierarchy.mindmap(this.mindMapDataCurrent, {
        direction: 'H',
        getHeight(d) {
          return d.height
        },
        getWidth(d) {
          return d.width
        },
        getHGap() {
          return 40
        },
        getVGap() {
          return 20
        },
        getSide: (d) => {
          return mindMapType.indexOf('double') != -1?d.data.direction || 'left':'right'
        }
      })
      const cells = []
      let xGap = this.positionCurrent?this.positionCurrent.x-result.x:0
      let yGap = this.positionCurrent?this.positionCurrent.y-result.y:0

      const traverse = (hierarchyItem) => {
        if (hierarchyItem) {
          const { data, children } = hierarchyItem
          let mindmapDirection = mindMapType.indexOf('double') != -1?data.direction:'right'
          let currentCell=this.graph.getCellById(data.id)

          if(!currentCell){
            // 没有 新增
            cells.push(
              this.graph.createNode({
                id: data.id,
                shape:mindmapDirection=='right'?'mindmap-topic-right':mindmapDirection=='left'?'mindmap-topic-left':'mindmap-topic',
                x: xGap+hierarchyItem.x,
                y: yGap+hierarchyItem.y,
                width: data.width,
                height: data.height,
                label: data.label,
                type: data.type,
                attrs:{
                  body: {
                    stroke: this.$store.state.sand.styleConfig.borderColor,
                    fill: this.$store.state.sand.styleConfig.backgroundColor
                  },
                  text:{
                    fill:this.$store.state.sand.styleConfig.color
                  }
                },
              }),
            )
          }else{
            // 有，更新下位置信息
            currentCell.position(xGap+hierarchyItem.x,yGap+hierarchyItem.y)
          }
   
          if (children) {
            children.forEach((item) => {
              const { id, data } = item
              let mindmapChildDirection = mindMapType.indexOf('double') != -1?data.direction:'right'
              let currentEdge=this.graph.getCellById(data.id)
              if(!currentEdge){
                cells.push(
                  this.graph.createEdge({
                    shape: 'mindmap-edge',
                    attrs:{
                      line:{
                        stroke:this.$store.state.sand.styleConfig.lineColor
                      }
                    },
                    source: {
                      cell: hierarchyItem.id,
                      anchor: {
                        name: 'center',
                        args: {
                          dx: mindmapChildDirection=='right'?'25%':mindmapChildDirection=='left'?'-25%':0,
                        },
                      },
                    },
                    target: {
                      cell: id,
                      anchor: {
                        name: mindmapChildDirection =='left'?'right':'left',
                      },
                    },
                  }),
                )
              }

              traverse(item)
            })
          }
        }
      }
      traverse(result)
      // 排下序，把边放最后面 不然 边 会找不到 节点
      let sortCells = cells.sort(cell => cell.shape.indexOf('edge'))

      this.graph.addCell(sortCells)
      this.graph.stopBatch('renderMindmap')

    },
    findItem(obj,id){
      if (obj.id === id) {
        return {
          parent: null,
          node: obj,
        }
      }
      const { children } = obj
      if (children) {
        for (let i = 0, len = children.length; i < len; i++) {
          const res = this.findItem(children[i], id)
          if (res) {
            return {
              parent: res.parent || obj,
              node: res.node,
            }
          }
        }
      }
      return null
    },
    addChildNode (id, type,direction='left'){
      // 重做不了 清空重做栈
      this.mindmapAssistData.mindmapDataRecoverUse = []

      const res = this.findItem(this.mindMapDataCurrent, id)
      const dataItem = res && res.node
      if (dataItem) {
        let item = null
        let addId ='1'
        if(dataItem.children && dataItem.children.length>0){
          let ids = dataItem.children[dataItem.children.length-1].id.split('-')
          addId = parseInt(ids[ids.length-1])+1+''
        }
        if (type === 'topic') {
          item = {
            id: `${id}-${addId}`,
            type: 'topic-branch',
            label: `分支主题${addId}`,
            width: 100,
            height: 40,
            direction
          }
        } else if (type === 'topic-branch' || type=='topic-child') {
          item = {
            id: `${id}-${addId}`,
            type: 'topic-child',
            label: `子主题${addId}`,
            width: 60,
            height: 30,
            direction
          }
        }
        if (item) {
          if (dataItem.children) {
            dataItem.children.push(item)
          } else {
            dataItem.children = [item]
          }
          return item
        }
      }
      return null
    },
    getMindmapDataUse(){
      return this.mindmapAssistData
    },
    mindmapDeleteRecordPush(mindmapNodes){
      let shouldOperations=[]
      this.mindmapAssistData.mindmapDataUse.map((item,index)=>{
        let levelIds = mindmapNodes.filter(mindMap => mindMap.data.id.startsWith(item.mindmapData.id)).map(mindMap => mindMap.data.id)
        if(!(levelIds && levelIds.length>0)) return 
        let mindMapIds=[...levelIds]
        for (let i = 0; i < levelIds.length; i++) {
          const element = levelIds[i]
          mindMapIds=mindMapIds.filter( id => id.indexOf(element) !=0 || id==element)
        }
        shouldOperations.push(mindMapIds)
      })
      // 入栈
      if(!this.canRedo){
        this.mindmapAssistData.mindmapDataRecoverUse=[JSON.stringify(this.mindmapAssistData.mindmapDataUse)]
      }else{
        this.mindmapAssistData.mindmapDataRecoverUse.push(JSON.stringify(this.mindmapAssistData.mindmapDataUse))
      }
      shouldOperations.map(it =>{
        it.map(it1 =>{
          this.deleteMindmapData(it1,this.mindmapAssistData.mindmapDataUse)
        })
      })
    },
    mindmapAddRecordPush(){
      // 入栈
      if(!this.canRedo){
        this.mindmapAssistData.mindmapDataRecoverUse=[JSON.stringify(this.mindmapAssistData.mindmapDataUse)]
      }else{
        this.mindmapAssistData.mindmapDataRecoverUse.push(JSON.stringify(this.mindmapAssistData.mindmapDataUse))
      }
      let recoverDeletedData=this.mindmapAssistData.deletedMindmapData.pop()
      if(recoverDeletedData && recoverDeletedData.length>0){
        // 添加
        recoverDeletedData.map(it =>{
          it.map(it1 =>{
            this.addMindmapData(it1,this.mindmapAssistData.mindmapDataUse)
          })
        })
      }
    },
    deleteMindmapData(id,data){
      let ids = id.split('-')
      let mindmapDataIndex = data.findIndex(mindmap => mindmap.mindmapData.id == ids[0])
      if(ids.length==1){
        data.splice(mindmapDataIndex,1)
        return 
      }

      let mindmapData = data[mindmapDataIndex].mindmapData
      let findId = ids[0]
      for (let i = 1; i < ids.length-1; i++) {
        const element = ids[i];
        findId = findId+'-'+element
        mindmapData=mindmapData.children.find(it => it.id==findId)
      }
      let endId = ids[ids.length-1]
      let endIndex = mindmapData.children.findIndex(it => it.id == findId+'-'+endId)
      mindmapData.children.splice(endIndex,1)
    },
    addMindmapData(item,data){
      let isRoot = item.mindmapData?true:false
      let id = isRoot?item.mindmapData.id:item.id
      
      if(isRoot){
        // 恢复根节点
        let mindmapDataIndexRoot=data.length
        for (let i = 0; i < data.length-1; i++) {
          const element = data[i];
          if((+id) < (+element.mindmapData.id)){
            mindmapDataIndexRoot=0
            break
          }else if((+id) > (+element.mindmapData.id) && (+id) < (+data[i+1].mindmapData.id)){
            mindmapDataIndexRoot=i+1
            break
          }
        }
        data.splice(mindmapDataIndexRoot,0,item)
        return
      }

      let ids = id.split('-')
      let mindmapDataIndex = data.findIndex(mindmap => {
        return mindmap.mindmapData.id == ids[0]
      })
      let mindmapData = data[mindmapDataIndex].mindmapData
      let findId = ids[0]
      for (let i = 1; i < ids.length-1; i++) {
        const element = ids[i];
        findId = findId+'-'+element
        mindmapData=mindmapData.children.find(it => it.id==findId)
      }
      let endId = ids[ids.length-1]
      let endIndex = mindmapData.children.length
      if(mindmapData.children.length==1){
        // 只有一个
        let prevIdx = mindmapData.children[0].id.substring(mindmapData.children[0].id.lastIndexOf('-')+1)
        if((+endId) < (+prevIdx)){
          endIndex=0
        }else{
          endIndex=1
        }
      }else{
        for (let i = 0; i < mindmapData.children.length-1; i++) {
          // 两个及以上
          const element = mindmapData.children[i];

          let prevIdx = element.id.substring(element.id.lastIndexOf('-')+1)
          let nextIdx = mindmapData.children[i+1].id.substring(mindmapData.children[i+1].id.lastIndexOf('-')+1)
          // 找到对应位置，前提 id是按顺序的
          if((+endId) < (+prevIdx)){
            endIndex=0
            break
          }else if((+endId) > (+prevIdx) && (+endId) < (+nextIdx)){
            endIndex=i+1
            break
          }
        }
      }
      mindmapData.children.splice(endIndex,0,item)
    },
    mindmapRecover(){
      // 重做添加时 恢复数据指针前进
      let recoverData = this.mindmapAssistData.mindmapDataRecoverUse.pop()
      if(recoverData) this.mindmapAssistData.mindmapDataUse=JSON.parse(recoverData) 
    },
  },
}
