<template>
	<div
		id="chartContent"
		style="position:relative;height:100%"
		:style="{ 'min-width': minWid + 'px', 'min-height': minHei + 'px' }"
	>
		<div
			style="display: flex;justify-content: flex-end;height: 30px; margin-top:10px"
		>
			<a-button @click="switchOPen" v-if="enable" style="display: none;"
				>{{ isShow ? '隐藏图标' : '显示图标' }}
			</a-button>
			<a-button
				type="primary"
				@click="exportChartData"
				style="margin-left: 10px;"
				v-if="showExportBtn"
				>导出数据到控制台
			</a-button>
			<a-button
				type="default"
				@click="resetChart"
				v-if="showReset"
				style="width: 150px;"
				>重置
			</a-button>
		</div>
		<div
			:id="domUuid"
			style="height: calc(100% - 40px);width: 100%"
			v-if="isShowChart"
		></div>
		<div
			class="flex-center"
			:class="isRoad ? 'road_computed_blank' : 'relevance_blank'"
			style="height: 100%;width: 100%;"
			v-else
		></div>
		<a-dropdown
			:visible="dropdown.show && isShowContextMenu === true"
			:getPopupContainer="getPopupContainer"
			:trigger="['click']"
			style="position: absolute;z-index: 1"
			:style="{ left: dropdown.x, top: dropdown.y }"
		>
			<a class="ant-dropdown-link" href="#" />
			<a-menu slot="overlay">
				<a-menu-item
					v-if="!contextMenu && clickTarget.type === 'node'"
					key="1"
					@click="handleRemoveEntCls"
					>隐藏选中
				</a-menu-item>
				<a-menu-item
					v-if="contextMenu && contextMenu.indexOf('delete') > -1"
					key="2"
					@click="contextMenuDelete"
					>排除
				</a-menu-item>
				<!--<a-menu-item v-if="clickTarget.type === 'node'" key="2" @click="movePosition">移动位置</a-menu-item>-->
			</a-menu>
		</a-dropdown>
	</div>
</template>

<script>
import uuid from 'uuid'
import { NetChart } from '@/plugins/knowledge/zoomChart'

// const NetChart = window.NetChart
// const NetChart = null;
const colors = ['rgba(111,82,184,1)',
			'rgba(255,214,24,1)',
			'rgba(47,195,47,1)',
			'rgba(86,185,247,1)',
			'rgba(234,180,4,1)',
			'rgba(222,103,44,1)',
			'#FEDD00',
			'#00843D',
			'#009A44',
			'#4A7729',
			'#78BE20',
			'#007A33',
			'#BFB800',
			'#64A70B',
			'#006341',
			'#FDDA24',
			'#009639',
			'#43B02A',
			'#00205B',
			'#00629B',
			'#64CCC9',
			'#0093B2',
			'#004F71',
			'#006BA6',
			'#003DA5',
			'#003B5C',
			'#008578',
			'#0033A0',
			'#002855',
			'#003087',
			'#00778B',
			'#0082BA',
			'#00A9CE',
			'#002D72',
			'#001871',
			'#672146',
			'#AD1AAC',
			'#A9431E',
			'#D57800',
			'#643335',
			'#FFCD00',
			'#3E2B2E',
			'#BE6A14',
			'#A50034',
			'#F9423A',
			'#C8102E',
			'#E4002B',
			'#C5003E',
			'#EF3340',
			'#CB333B',
			'#FC4C02',
			'#FE5000',
			'#FF671F',
			'#2C2A29',
			'#FFA300',
			'#FBD872',
			'#333F48',
			'#C99700',
			'#ABCAE9',
			'#F4364C',
			'#7A7D81',
			'#C5299B',
			'#DB3EB1',
			'#B9975B',
		]

let g_root,
	chart,
	node_colors = {},
	link_colors = {}
let highLightCache = {}
let isShow = true
let _vue

let isDivisionColor = false
export default {
	props: {
		nodes: {
			type: Array,
			default: () => [],
		},
		links: {
			type: Array,
			default: () => [],
		},
		enable: {
			type: Boolean,
			default: false,
		},
		isDivisionColor: {
			type: Boolean,
			default: false,
		},
		isShowChart: {
			type: Boolean,
			default: false,
		},
		isShowContextMenu: {
			type: Boolean,
			default: false,
		},
		contextMenu: {
			type: Array,
			default: () => [],
		},
		isRoad: {
			type: Boolean,
			default: false,
		},
		isShowTree: {
			type: Boolean,
			default: false,
		},
		minWid: {
			type: Number,
			default: null,
		},
		minHei: {
			type: Number,
			default: null,
		},
		showExportBtn: {
			type: Boolean,
			default: false,
		},
		showRelKey: {
			// 默认关系之间的名称显示，默认显示true:relClsName [true:'relClsName', false:'relName']
			type: Boolean,
			default: true,
		},
		isEntChart: {
			type: Boolean,
			default: false,
		},
	},
	data() {
		_vue = this
		return {
			domUuid: uuid(),
			useNavigation: false,
			showReset: false,
			isShow,
			dropdown: {
				// 下拉菜单的样式配置
				show: false,
				x: null,
				y: null,
			},
			chartNodes: null,
			chartLinks: null,
			clickTarget: {},
			//moveid:'', // 要移动的id
			selectedEntClsIds: [], // 选中的实体类ids
		}
	},
	watch: {
		nodes: function() {
			this.chartNodes = this.nodes
		},
		links: function() {
			this.chartLinks = this.links
		},
		contextMenu: function() {
			console.log(this.contextMenu)
		},
	},
	methods: {
		getPopupContainer() {
			return document.getElementById('chartContent')
		},
		// 导出图表的数据（json格式）
		exportChartData() {
			const nodes = chart.nodes()
			const links = chart.links()
			const json = {
				nodes: [],
				links: [],
			}
			for (let i = 0; i < nodes.length; i++) {
				const node = nodes[i].data
				node.x = nodes[i].x
				node.y = nodes[i].y
				json.nodes.push(node)
			}
			for (let l = 0; l < links.length; l++) {
				json.links.push(links[l].data)
			}
			// 这里显示导出的数据，不要删
			console.log(JSON.stringify(json))
		},
		// 切换图标显示和隐藏
		switchOPen() {
			this.isShow = isShow = !isShow
			this.$emit('reloadChart', this.chartNodes, this.chartLinks)
			// this.$emit('reloadChart')
		},
		hidePopup() {
			this.dropdown.show = false
		},
		movePosition() {
			chart.reloadData({ nodes: [{ id: this.moveid, x: 300, y: 300 }] })
			// chart.replaceData({ nodes: [{id: this.moveid,x: 300, y: 300}] });
		},
		// 右键菜单删除
		contextMenuDelete() {
			this.dropdown.show = false
			this.$emit('delete', this.selectedEntClsIds)
		},
		// 批量隐藏 实体类
		handleRemoveEntCls() {
			this.dropdown.show = false
			chart.removeData({ nodes: this.selectedEntClsIds })
			this.selectedEntClsIds = [] // 清空上次删除的ids
		},
		/**
		 * 高亮时图表的样式
		 * */
		highLightStyle(start, end, nodes) {
			let nodeIds = []
			nodes.forEach((v) => {
				if (nodeIds.indexOf(v.endEntVOS.entID) === -1) {
					nodeIds.push(v.endEntVOS.entID)
				}
				if (nodeIds.indexOf(v.startEntVo.entID) === -1) {
					nodeIds.push(v.startEntVo.entID)
				}
			})
			highLightCache.nodeIds = nodeIds
			highLightCache.linkIds = computePath(nodes)
			chart.updateStyle()
		},
		/**
		 * 取消高亮
		 * */
		unhighLightStyle() {
			highLightCache = {}
			chart.updateStyle()
		},
		/**
		 * 重绘
		 * */
		reDraw(root, nodes, links) {
			g_root = root
			if (chart) {
				chart.replaceData({
					nodes: getNodes(nodes),
					links: getLinks(links),
				})
			} else {
				this.drawChart(root, nodes, links)
			}
		},
		addDraw(root, nodes, links) {
			if (chart) {
				chart.addData({
					nodes: getNodes(nodes),
					links: getLinks(links),
				})
			} else {
				this.drawChart(root, nodes, links)
			}
		},
		/*
		 * 画zoomchart
		 * */
		drawChart(root, nodes, links) {
			console.log(root, nodes, links)
			const vm = this

			g_root = root
			highLightCache = {}
			chart = new NetChart({
				container: document.getElementById(this.domUuid),
				area: {},
				legend: {
					enabled: true,
					margin: 20,
				},
				layout: this.isShowTree
					? {
							mode: 'hierarchy',
							nodeSpacing: 45,
							rowSpacing: 80,
					  }
					: {},
				navigation: this.useNavigation
					? {
							mode: 'focusnodes',
							autoZoomOnFocus: true,
							// initialNodes: g_root,
							initialNodes: nodes[0].entClsID,
							focusNodeExpansionRadius: 1,
							numberOfFocusNodes: 2,
							focusNodeTailExpansionRadius: 0.5,
					  }
					: {},
				style: {
					link: { fillColor: 'rgba(0,0,0,0.4)' },
					node: {
						lineWidth: 2,
						lineColor: '#09c',
						imageCropping: true,
					},
					nodeLabel: {
						// 节点label的显示样式
						padding: 0,
						borderRadius: 4,
						textStyle: { font: '16px Arial', fillColor: 'black' },
						backgroundStyle: { fillColor: 'rgba(255,255,255,0.7)' },
					}, // 节点label的显示样式,
					linkLabel: {
						// 线的label显示样式
						padding: 0,
						borderRadius: 20, //make as round as possible
						textStyle: { font: '20px Arial', fillColor: '#aaa' },
						backgroundStyle: {
							fillColor: 'rgba(255,255,255,0.6)',
							lineColor: 'rgba(0,0,0,0)',
						},
						rotateWithLink: true,
						scaleWithSize: true,
					}, // 线的label显示样式
					nodeStyleFunction: vm.nodeStyle, // 节点样式与配置的回调
					linkStyleFunction: linkStyle, // 关系样式与配置的回调
				},
				info: {
					enabled: true,
					nodeContentsFunction: function(data, item) {
						let html
						if (data.entName) {
							// 实体
							html =
								'<div class="chart_tooltip"><h3>实体名称：' +
								data.entName +
								'</h3>'
						} else if (data.entClsName) {
							// 实体类
							html =
								'<div class="chart_tooltip"><h3>实体类名称：' +
								data.entClsName +
								'</h3>'
						}
						if (
							data.entName === undefined &&
							data.entClsName === undefined
						)
							html = ''
						return html
					},
					linkContentsFunction: function(data, item) {
						let html =
							'<div class="chart_tooltip"><h3>关系名称：' +
							data.relClsName +
							'</h3>'
						if (data.relClsName === undefined) html = ''
						return html
					},
				},
				events: {
					onClick: function(event, args) {
						if (
							!event.ctrlKey &&
							!event.shiftKey &&
							args.clickNode &&
							vm.useNavigation
						) {
							chart.addFocusNode(args.clickNode)
						}
						vm.dropdown.show = false
						vm.$emit('c_click', event, args)
						event.preventDefault()
					},
					onSelectionChange: function(event, args) {
						// 选中的实体类事件
						vm.selectedEntClsIds = [] // 清空上一次选中
						for (let i = 0; i < event.selection.length; i++) {
							const item = {}
							item.id = event.selection[i].id
							item.label = event.selection[i].label
							vm.selectedEntClsIds.push(item)
						}
					},
					onDoubleClick: function(event, args) {
						// 双击事件
						vm.dropdown.show = false
						if (args.clickNode) {
							vm.$emit('changeRoot', args.clickNode.data.id, 1)
						}
						event.preventDefault()
					},
					onRightClick: function(event, args) {
						// 右键
						// vm.moveid = event.clickNode.id
						vm.dropdown.show = true
						vm.dropdown.x = event.x + 20 + 'px'
						vm.dropdown.y = event.y + 50 + 'px'
						if (args.clickNode) {
							vm.clickTarget.type = 'node'
							// vm.clickTarget.data = args.clickNode.data
							this.selectedEntClsIds = [
								{
									id: event.clickNode.id,
									label: event.clickNode.label,
								},
							]
						} else if (args.clickLink) {
							vm.clickTarget.type = 'link'
						} else {
							vm.hidePopup()
						}
						event.preventDefault()
					},
				},
			})
			document.oncontextmenu = function() {
				return false
			}
			this.reDraw(root, nodes, links)
		},
		// 重定义变量
		reloadData(obj) {
			this.useNavigation = obj.useNavigation
			this.showReset = obj.showReset
		},
		resetChart() {
			this.$emit('resetChart')
		},
		/**
		 * 销毁chart实例
		 * */
		destroyChart() {
			chart = undefined
		},
		nodeStyle(node) {
			// 定义节点的样式
			const vm = this
			let data = node.data.data ? node.data.data : node.data
			if (vm.isEntChart) {
				node.label = data.label
				let r = 90
				let g = 150
				let b = 220
				r -= (data.relNum - 1) * 5
				g -= (data.relNum - 1) * 5
				b -= (data.relNum - 1) * 5
				node.fillColor = 'rgba(' + r + ',' + g + ',' + b + ',1)'
				node.radius = 50 + (data.relNum - 1) * 10
			} else {
				if (data.entClsIcon && isShow) {
					node.image = data.entClsIcon
				}
				if (data.entIcon && isShow) {
					node.image = data.entIcon
				}
				node.label = data.label
				if (data.id === g_root) {
					if (!node.data.backGroundColor) {
						node.fillColor = 'orange'
					} else {
						node.fillColor = data.backGroundColor
					}
				} else {
					let lineColor = node_colors[data.entClsID]
					if (lineColor === undefined) {
						lineColor = getColor()
					}
					node.lineColor = lineColor
					node.fillColor = 'white'
					if (isDivisionColor) {
						// 根据创建和修改的时间，标记颜色
						if (data.createTime && !data.updateTime) {
							node.lineColor = '#f5222d'
						} else if (data.createTime == data.updateTime) {
							node.lineColor = '#1890ff'
						} else if (data.createTime != data.updateTime) {
							node.lineColor = '#52c41a'
						}
						node.lineWidth = 3
					} else {
						if (!!node.data.backGroundColor) {
							node.fillColor = data.backGroundColor
						}
					}
				}
			}

			// 如果当前节点在高亮节点集合中
			if (
				highLightCache.nodeIds &&
				highLightCache.nodeIds.indexOf(data.id) > -1
			) {
				node.fillColor = 'orange'
			}
		},
	},
	created() {
		window.isEntChart = this.isEntChart
		isDivisionColor = this.isDivisionColor
	},
	destroyed() {
		this.destroyChart()
	},
}

// 定义线的样式
function linkStyle(link) {
	// debugger
	let data = link.data.data ? link.data.data : link.data
	// link.label = data.label ? data.label : data.relName
	getLinkClass(link)

	if (
		highLightCache.linkIds &&
		highLightCache.linkIds.indexOf(data.id) > -1
	) {
		if (!link.data.backGroundColor) {
			link.fillColor = 'orange'
		} else {
			link.fillColor = data.backGroundColor
		}
		link.radius = 4
		link.label = ''
	}
}

// 格式化成zoomchart需要的nodes
function getNodes(nodes) {
	if(nodes){
		nodes.forEach((node, index) => {
			if (node.entID) node.id = node.entID
			if (node.label === undefined) node.label = node.entName
			if (!node_colors[node.entClsID]) {
				node_colors[node.entClsID] = colors[index % nodes.length]
			}
		})
		return nodes
	} else {
		return []
	}
}

// 格式化成zoomchart需要的links
function getLinks(links) {
	if(links){
		links.forEach((link, index) => {
			if (link.relID) link.id = link.relID
			if (link.from === undefined) link.from = link.startEntID
			if (link.to === undefined) link.to = link.endEntID
			if (!link_colors[link.relClsID]) {
				link_colors[link.relClsID] = colors[index % links.length]
			}
		})
		return links
	} else {
		return []
	}
}

// 生成随机颜色
function getColor() {
	let r = Math.floor(Math.random() * 255)
	let g = Math.floor(Math.random() * 255)
	let b = Math.floor(Math.random() * 255)
	return 'rgba(' + r + ',' + g + ',' + b + ',0.8)'
}

// 根据关系的classType生成不同的线的样式
function getLinkClass(link) {
	let data = link.data.data ? link.data.data : link.data
	if (data.classType === 'dashed') {
		link.toDecoration = 'arrow'
		link.lineDash = [10, 10, 2, 2]
	} else {
		link.toDecoration = 'arrow'
		link.items = [
			{
				text: _vue.showRelKey ? data.relClsName : data.relName,
				padding: 2,
				backgroundStyle: {
					fillColor: 'white',
					// lineColor: link_colors[data.relClsID]
					lineColor: 'black',
				},
				textStyle: {
					fillColor: 'black',
				},
			},
		]
	}
	return link
}

function computePath(nodes) {
	let linkIds = []
	const currentLinks = chart.links()
	nodes.forEach((v) => {
		let startId = v.startEntVo.entID,
			endId = v.endEntVOS.entID
		currentLinks.forEach((_v) => {
			if (startId === _v.from.id && endId === _v.to.id) {
				linkIds.push(_v.id)
			}
		})
	})
	return linkIds
}
</script>

<style>
.DVSL-menu-container.DVSL-menu-workaround {
	display: none;
}

.flex-center {
	position: relative;
}

.road_computed_blank,
.relevance_blank {
	width: auto;
	border-radius: 4px;
	background-size: cover;
}

.road_computed_blank {
	/* background-image: url('../../assets/banner (1).png'); */
}

.relevance_blank {
	background-size: 100% 100%;
	/* background-image: url('../../assets/banner (2).png'); */
}
</style>
