const StructureChart = (data, loadApiData, setMsg, waterText) => {
	var newDownData = data.downward && data.downward.children ? data.downward.children : [];
	var newUpData = data.upward && data.upward.children ? data.upward.children : [];
	newDownData.forEach((v, i) => {
		v.indexNum = i;
	})
	newUpData.forEach((v, i) => {
		v.indexNum = i;
	})
	data = {...data, downward: { children: newDownData }, upward: { children: newUpData }};
	var tree = document.getElementById('structure-chart');
	var zoom, rootData, rootName, lines, treeG;
	var width = tree.clientWidth;
	var height = (document.documentElement.clientHeight || document.body.clientHeight) - 44;

	var scale = 1;
	var directions = ['upward', 'downward'];
	var treeData = {};
	let drawing = function (data) {
		var rootRectWidth = 0; //根节点rect的宽度
		var rootRectHeight = 0; //根节点rect的高度
		var downwardLength = 0, upwardLength = 0;
		var forUpward;

		function zoomed() {
			var transform = d3.zoomTransform(event.target);
			treeG.attr("transform", "translate(" + transform.x + "," + transform.y + ") scale(" + transform.k + ")");
		}

		function expand(d) {
			if (d._children) {
				d.children = d._children;
				d.children.forEach(expand);
				d._children = null;
			}
		}

		function collapse(d) {
			if (d.children && d.children.length != 0) {
				d._children = d.children;
				d._children.forEach(collapse);
				d.children = null;
			}
		}

		var treeChart = function () { };
		treeChart.prototype.drawChart = function () {
			var self = this;
			directions.forEach(function (direction) {
				treeData[direction] = rootData[direction];
			});

			rootRectWidth = 284;
			lines = Math.ceil(rootName.length / 20);
			rootRectHeight = lines * 15 + 20;
			//获得upward第一级节点的个数
			if (rootData.upward && rootData.upward.children) {
				upwardLength = rootData.upward.children.length;
			} else {
				upwardLength = 0;
			}
			//获得downward第一级节点的个数
			if (rootData.downward && rootData.downward.children) {
				downwardLength = rootData.downward.children.length;
			} else {
				downwardLength = 0;
			}
			self.graphTree(self.getTreeConfig());
		};

		treeChart.prototype.getTreeConfig = function () {
			var treeConfig = {
				'margin': {
					'top': 0,
					'right': 0,
					'bottom': 0,
					'left': 0
				}
			}

			treeConfig.chartWidth = width;
			treeConfig.chartHeight = height;
			treeConfig.centralHeight = treeConfig.chartHeight / 2;
			treeConfig.centralWidth = treeConfig.chartWidth / 2;
			treeConfig.linkLength = 140;
			treeConfig.duration = 500; //动画时间
			return treeConfig;
		};
		treeChart.prototype.graphTree = function (config) {
			var self = this;
			var linkLength = config.linkLength;
			var duration = config.duration;
			var id = 0;
			zoom = d3.zoom()
				.scaleExtent([0.5, 2])
				.on('zoom', zoomed);
			var svg = d3.select('#structure-chart')
				.append('svg')
				.attr('width', config.chartWidth)
				.attr('height', config.chartHeight)
				.attr('xmlns', 'http://www.w3.org/2000/svg')
				.attr('class', 'svgbox')
				.call(zoom);
			treeG = svg.append('g')
				.attr('class', 'gbox')
				.attr('transform', 'translate(' + (0) + ',' + (0) + ')');

			//箭头(下半部分)
			var markerDown = svg.append("marker")
				.attr("id", "resolvedDown")
				.attr("markerUnits", "strokeWidth") //设置为strokeWidth箭头会随着线的粗细发生变化
				.attr("markerUnits", "userSpaceOnUse")
				.attr("viewBox", "0 -5 10 10") //坐标系的区域
				.attr("refX", 30) //箭头坐标
				.attr("refY", 0)
				.attr("markerWidth", 12) //标识的大小
				.attr("markerHeight", 12)
				.attr("orient", "90") //绘制方向，可设定为：auto（自动确认方向）和 角度值
				.attr("stroke-width", 2) //箭头宽度
				.append("path")
				.attr("d", "M0,-4L10,0L0,4") //箭头的路径
				.attr('fill', '#1e8bee'); //箭头颜色  
			//箭头(上半部分)
			var markerUp = svg.append("marker")
				.attr("id", "resolvedUp")
				.attr("markerUnits", "strokeWidth") //设置为strokeWidth箭头会随着线的粗细发生变化
				.attr("markerUnits", "userSpaceOnUse")
				.attr("viewBox", "0 -4 10 10") //坐标系的区域
				.attr("refX", -20) //箭头坐标
				.attr("refY", 0)
				.attr("markerWidth", 12) //标识的大小
				.attr("markerHeight", 12)
				.attr("orient", "90") //绘制方向，可设定为：auto（自动确认方向）和 角度值
				.attr("stroke-width", 2) //箭头宽度
				.append("path")
				.attr("d", "M0,-4L10,0L0,4") //箭头的路径
				.attr('fill', '#1e8bee'); //箭头颜色
			function drowLine(d) {
				let { target, source, indexNum, lenNum } = d;
				let addiY = source.y, addiY2 = source.y, resultY = target.y;
				if (forUpward) { // 向上
					if (source.name == 'origin') {
						addiY = source.y - rootRectHeight - 40;
					} else {
						addiY2 = source.y - 44 - 12 - 12;
						addiY = source.y - rootRectHeight - 44 - 12 - 12;
					}
					resultY = target.y - 12;
				}
				if (!forUpward) { // 向下
					if (source.name == 'origin') {
						addiY = source.y + rootRectHeight + 40;
					} else {
						addiY2 = source.y + 44 + 12 + 12;
						addiY = source.y + rootRectHeight + 44 + 12 + 12;
					}
					resultY = target.y + 12;
				}
				let line = d3.line()
					.x(d => d.x)
					.y(d => d.y)
					.curve(d3.curveStepAfter);
				if (source.depth > 0) {
					if (indexNum === 0) {
						return line([
							{ x: source.x, y: addiY2 },
							{ x: source.x, y: addiY },
							{ x: target.x, y: addiY },
							{ x: target.x, y: resultY }
						])
					} else if (indexNum + 1 === lenNum) {
						return line([
							{ x: source.x, y: addiY },
							{ x: target.x, y: addiY },
							{ x: target.x, y: resultY }
						])
					} else {
						return line([
							{ x: target.x, y: addiY },
							{ x: target.x, y: resultY }
						])
					}
				} else {
					if (indexNum === 0) {
						return line([
							{ x: source.x, y: source.y },
							{ x: source.x, y: addiY },
							{ x: target.x, y: addiY },
							{ x: target.x, y: resultY }
						])
					} else if (indexNum + 1 === lenNum) {
						return line([
							{ x: source.x, y: addiY },
							{ x: target.x, y: addiY },
							{ x: target.x, y: resultY }
						])
					} else {
						return line([
							{ x: target.x, y: addiY },
							{ x: target.x, y: resultY }
						])
					}
				}
			}
			// Initialize the tree nodes and update chart.
			function update(source, originalData, g) {
				var direction = originalData['direction'];
				forUpward = direction == 'upward';
				var node_class = direction + 'Node';
				var link_class = direction + 'Link';
				var downwardSign = (forUpward) ? -1 : 1;

				var isExpand = false;
				var nodeSpace = 150;
				var tree = d3.tree().nodeSize([nodeSpace, 0])
				const treeRoot = d3.hierarchy(originalData);
				tree(treeRoot)
				const nodes = treeRoot.descendants();
				const links = treeRoot.links();
				var offsetX = -config.centralWidth;
				nodes.forEach(function (d) {
					d.y = downwardSign * (d.depth * linkLength) + config.centralHeight;
					d.x = d.x - offsetX;
					if (d.data.name == 'origin') {
						d.x = config.centralWidth;
						d.y += downwardSign * 0; // 上下两树图根节点之间的距离
					}
				});

				// Update the node.
				var node = g.selectAll('g.' + node_class)
					.data(nodes, function (d) {
						return d.data.id || (d.data.id = ++id);
					});
				var nodeEnter = node.enter().append('g')
					.attr('class', node_class)
					.attr('transform', function (d) {
						return 'translate(' + d.x + ',' + d.y + ')';
					})
					.style('cursor', function (d) {
						return (d.data.name == 'origin') ? '' : (d.children || d._children) ? 'pointer' : '';
					});

				nodeEnter.append("svg:rect")
					.attr("x", function (d) {
						return (d.data.name == 'origin') ? -(rootRectWidth / 2) : -70;
					})
					.attr("y", function (d) {
						return (d.data.name == 'origin') ? -(rootRectHeight / 2) : forUpward ? -58 : 12;
					})
					.attr("width", function (d) {
						return (d.data.name == 'origin') ? rootRectWidth : 140;
					})
					.attr("height", function (d) {
						if (d.data.name == 'origin') {
							return rootRectHeight;
						} else {
							return 40 + 6;
						}
					})
					.style("stroke", function (d) {
						if (d.data.name == 'origin') {
							return "#80c6f6"
						} else {
							return (d.data.type == '2') ? "#db7093" : "#1e8bee";
						}
					})
					.attr("stroke-width", function (d) {
						if (d.data.name == 'origin') {
							return 1
						} else {
							return 0.5
						}
					})
					.style("fill", function (d) {
						if (d.data.name != "origin") {
							return '#fff';
						} else {
							return '#1e8bee'; // 根节点背景色
						}
					});

				nodeEnter.append('circle').attr('r', 1e-6); // 是否展开按钮

				nodeEnter.append("text")
					.attr("class", "linkname")
					.attr("x", function (d) {
						return 0;
					})
					.attr('dy', function (d) {
						if (d.data.name == 'origin') {
							if (lines == 1) {
								return '.35em'
							} else {
								return (rootRectHeight / 2) - 30;
							}
						} else {
							return forUpward ? '-40' : '26';
						}
					})
					.attr("text-anchor", function (d) {
						return 'middle';
					})
					.text(function (d) {
						if (d.data.name == 'origin') {
							return rootName.length > 20 ? rootName.substr(0, 20) : rootName;
						}
						return (d.data.name.length > 10) ? d.data.name.substr(0, 10) : d.data.name;
					})
					.attr('fill-opacity', 1)
					.attr('cursor', "pointer")
					.attr('fill', function (d) {
						return (d.data.name == 'origin') ? '#d5d5d5' : '#000';
					})
					.attr('font-size', function (d) {
						return (d.data.name == 'origin') ? 14 : 12;
					})
				nodeEnter.append("text")
					.attr("class", "linkname")
					.attr("x", 0)
					.attr("dy", function (d) {
						if (d.data.name == 'origin') {
							if (lines == 1) {
								return '.35rem'
							} else {
								return (rootRectHeight / 2) - 12;
							}
						} else {
							return forUpward ? '-29' : '40';
						}
					})
					.attr("text-anchor", function () {
						return 'middle';
					})
					.text(function (d) {
						if (d.data.name == 'origin') {
							return rootName.substr(20, rootName.length);
						}
						return d.data.name.substr(10, d.data.name.length);
					})
					.attr('fill-opacity', 1)
					.attr('cursor', "pointer")
					.attr('fill', function (d) {
						return (d.data.name == 'origin') ? '#d5d5d5' : '#000';
					})
					.attr('font-size', function (d) {
						return (d.data.name == 'origin') ? 14 : 12;
					})
				nodeEnter.append("text")
					.attr("x", 0)
					.attr("dy", function (d) {
						return (d.data.name == 'origin') ? '.35em' : forUpward ? '-16' : '54';
					})
					.attr("text-anchor", "middle")
					.attr("class", "linkname")
					.style("fill", "#727272")
					.style('font-size', 11)
					.text(function (d) {
						var str = (d.data.name == 'origin') ? '' : d.data.desc;
						return str;
					});
				nodeEnter.append("text")
					.attr("x", "-30")
					.attr("dy", function (d) {
						return (d.data.name == 'origin') ? '.35em' : forUpward ? '20' : '-16';
					})
					.attr("text-anchor", "start")
					.attr("class", "linkname")
					.style("fill", "#1e8bee")
					.style('font-size', 10)
					.style('padding', 5)
					.text(function (d) {
						return d.data.sign;
					});
				nodeEnter.append("text")
					.attr("x", "10")
					.attr("dy", function (d) {
						return (d.data.name == 'origin') ? '.35em' : forUpward ? '20' : '-16';
					})
					.attr("text-anchor", "start")
					.attr("class", "linkname")
					.style("fill", "#1e8bee")
					.style('font-size', 10)
					.text(function (d) {
						return (d.data.name == 'origin') ? "" : d.data.sign2;
					});

				// Transition nodes to their new position.原有节点更新到新位置
				var nodeUpdate = g.selectAll('g.' + node_class).transition()
					.duration(duration)
					.attr('transform', function (d) {
						return 'translate(' + d.x + ',' + d.y + ')';
					});
				nodeUpdate.select('circle')
					.attr('r', function (d) {
						return (d.data.name == 'origin') ? 0 : (d.data.isSearch == 'N') ? 0 : 6;
					})
					.attr('cy', function (d) {
						return (d.data.name == 'origin') ? -20 : (forUpward) ? -64 : 64;
					})
					.style('fill', function (d) {
						return d.data.isSearch == 'Y' ? "#fff" : "";
					})
					.style('stroke', function (d) {
						return d.data.isSearch == 'Y' ? "#1c90ee" : "";
					})
					.style('fill-opacity', function (d) {
						if (d.children) {
							return 0.35;
						}
					});
				//代表是否展开的+-号
				nodeEnter.append("svg:text")
					.attr("class", "isExpand")
					.attr("x", "0")
					.attr("dy", function (d) {
						return forUpward ? -60 : 68;
					})
					.attr("text-anchor", "middle")
					.style("fill", "#1c90ee")
					.text(function (d) {
						if (d.data.name == 'origin') {
							return '';
						}
						return d.data.isSearch == 'Y' ? "+" : "";
					})
					.style("font-size", function (d) {
						return '12px'
					})
					.on('click', click)

				nodeUpdate.select('text').style('fill-opacity', 1)

				var nodeExit = node.exit().transition()
					.duration(duration)
					.attr('transform', function (d) {
						return 'translate(' + source.x + ',' + source.y + ')';
					})
					.remove();
				nodeExit.select('circle')
					.attr('r', 1e-6)
				nodeExit.select('text')
					.style('fill-opacity', 1e-6);

				var link = g.selectAll('path.' + link_class)
					.data(links, function (d, i) {
						d.indexNum = links[i].target.data.indexNum;
						d.lenNum = links[i].source.children.length || 0;
						return d.target.data.id;
					});
				link.enter().insert('path', 'g')
					.attr('class', link_class)
					.attr('stroke', function (d) {
						return '#333'
					})
					.attr('fill', "none")
					.attr('stroke-width', '1px')
					.attr('opacity', 0.5)
					.attr('d', function (d) {
						return drowLine(d);
					})
					.attr("marker-end", function (d) {
						return forUpward ? "url(#resolvedUp)" : "url(#resolvedDown)";
					}) //根据箭头标记的id号标记箭头;
					.attr("id", function (d, i) {
						return "mypath" + i;
					})
				link.transition()
					.duration(duration)
					.attr('d', d => {
						return drowLine(d);
					});
				link.exit().transition()
					.duration(duration)
					.attr('d', function (d) {
						return drowLine(d);
					})
					.remove();

				function click(e) {
					var direction = originalData['direction'];
					forUpward = direction == 'upward';
					isExpand = !isExpand;
					const d = e.target.__data__;
					if (d.data.name == 'origin') {
						return;
					}
					if (d.children) {
						d._children = d.children;
						d.children = null;
						d3.select(this).text('+').style({
							'font-size': '12px'
						})
						update(d, originalData, g);
					} else {
						d.children = d._children;
						d._children = null;
						let param = {
							key: d.data.name,
							formatFlag: 2
						}
						// 获取新数据
						loadApiData(param.key, ({ code, data }) => {
							if (code == 200) {
								if (forUpward == true) {
									let newChild = data.upward.children || [];
									newChild.forEach((v, i) => {
										v.indexNum = i;
									})
									d.children = newChild;
								} else if (forUpward == false) {
									let newChild = data.downward.children || [];
									newChild.forEach((v, i) => {
										v.indexNum = i;
									})
									d.children = newChild;
								}
								if (d.data.name == 'origin') {
									d.children.forEach(expand);
								}
								d3.select(this).text('-').style({
									'font-size': '12px'
								})
								update(d, originalData, g);
							}
						})
					}
				}
			}
			function initChart() {
				for (var d in directions) {
					var direction = directions[d];
					var data = treeData[direction];
					if (data) {
						data.x0 = config.centralWidth;
						data.y0 = config.centralHeight;
						if (data.children) {
							data.children.forEach(collapse);
						}
						update(data, data, treeG);
					}
				}
			}
			initChart();
			//放大
			d3.select("#big").on('click', () => {
				if (scale < 4) {
					scale += 0.2;
				}
				zoom.scale(scale);
				treeG.transition()
					.duration(500)
					.attr("transform", "translate(" + zoom.translate() + ")scale(" + scale + ")");
			})
			// 缩小
			d3.select("#small").on('click', () => {
				if (scale > 0.2) {
					scale -= 0.2;
				}
				zoom.scale(scale);
				treeG.transition()
					.duration(500)
					.attr("transform", "translate(" + zoom.translate() + ")scale(" + scale + ")");
			})
			// 保存
			d3.select("#save").on('click', () => {
				var svgNode = tree.querySelector('.svgbox');
				var gNode = tree.querySelector('.gbox');
				var saveMain = document.getElementById('saveMain'); // 需要保存的内容的暂存处理空间
				gNode.setAttribute('transform', `translate(0,0) scale(1)`);
				var _gData = gNode.getBoundingClientRect();
				var _svgWidth = svgNode.getAttribute('width');
				var _svgHeight = svgNode.getAttribute('height');
				var maxW = Math.max(_gData.width, _svgWidth)*1.5;
				var maxH = Math.max(_gData.height, _svgHeight)*1.5;
				var svgXml = tree.innerHTML;
				// 将所需保存的内容放到暂存空间
				saveMain.innerHTML = svgXml;
				var saveMainSvg = saveMain.querySelector('.svgbox');
				var saveMainG = saveMain.querySelector('.gbox');
				saveMainSvg.setAttribute('width', maxW);
				saveMainSvg.setAttribute('height', maxH);
				saveMainG.setAttribute('transform', `translate(${maxW/2},0) scale(1)`)
				var newSvgXml = saveMain.innerHTML;
				// 将内容转化为图片，并保存
				var image = new Image();
				const imgUrl = 'data:image/svg+xml;base64,' + window.btoa(unescape(encodeURIComponent(newSvgXml)));
				image.src = imgUrl;
				var time = maxW > 8000 ? maxW/8000*500 : 500;
				setTimeout(function() {
					var canvas = document.createElement('canvas'); //准备空画布
					canvas.width = maxW;
					canvas.height = maxH;
					var context = canvas.getContext('2d'); //取得画布的2d绘图上下文
					if (waterText) {
						var shuiyinCvs = shuiyin().shuiyinCvs;
						var pat = context.createPattern(shuiyinCvs, "repeat");
						context.fillStyle = pat;
					} else {
						context.fillStyle = "#fff";
					}
					context.fillRect(0, 0, maxW, maxH);
					context.drawImage(image, 0, 0);
					//前台下载图片
					var qual = 1;
					if (canvas.width > 3000) {
						qual = 0.8;
					} else if (canvas.width > 8000) {
						qual = 0.6;
					}
					const downUrl = canvas.toDataURL('image/jpeg', qual);
					var a = document.createElement("a");
					a.href = downUrl;
					var filename = `${rootName}${new Date().toLocaleDateString()}结构图.jpeg`;
					a.download = filename;
					a.click();
				}, time);
	 		})
		};
		var d3GenerationChart = new treeChart(d3);
		d3GenerationChart.drawChart();
	};
	let getData = function (data) {
		if (data.downward) {
			data.downward.direction = 'downward';
			data.downward.name = 'origin';
		}
		if (data.upward) {
			data.upward.direction = 'upward';
			data.upward.name = 'origin';
		}
		rootData = data;
		rootName = rootData.rootName;
		drawing();
	};
	jQuery(document).ready(function () {
		var child = document.getElementById("structure-chart");
		child.innerHTML = '';
		getData(data);
	});
	// 设置水印
	function shuiyin() {
		var cvs = document.createElement('canvas');
		var ctx = cvs.getContext('2d');
		cvs.width = 180;
		cvs.height = 160;
		ctx.fillStyle = "rgba(255, 255, 255, 1)";
		ctx.fillRect(0, 0, 180, 160);
		ctx.fill();
		ctx.rotate(-30*Math.PI/180);
		ctx.font = "19px 微软雅黑";
		ctx.textAlign = 'left';
		ctx.textBaseline = 'Middle';
		// ctx.strokeStyle = '#c0c0c0';
		// ctx.strokeText(waterText, -30, 80);
		ctx.fillStyle = '#ddd';
		ctx.fillText(waterText, -30, 125);
		ctx.rotate(30*Math.PI/180);
		const shuiyinUrl = cvs.toDataURL('image/jpeg', 1);
		// new Image().src = shuiyinUrl;
		return {
			shuiyinImg: shuiyinUrl,
			shuiyinCvs: cvs
		};
	}
}
export default StructureChart;