//- UNCLASSIFIED

extends base
append base_parms
	- tech = "d3"

append base_help
	:markdown
		Display sankey chart:

			src = source url
			w = drawing width
			h = drawing height
			debug = dump derived options

append base_head
	style.
		.node rect {
			cursor: move;
			fill-opacity: .9;
			shape-rendering: crispEdges;
		}
		.node text {
			pointer-events: none;
			text-shadow: 0 1px 0 #fff;
		}
		.link {
			fill: none;
			stroke: #000;
			stroke-opacity: .2;
		}
		.link:hover {
			stroke-opacity: .5;
		}

	script.
		var opts = {
			ds: 
				"!{query.src}"
					? "!{query.src}?name=#{query.name}&x:=#{query.x}&y:=#{query.y}&case:=name"
					:  "/stores/graph.json",
			dims: {
				margin: {top: 20, right: 90, bottom: 30, left: 90},
				width: parseInt("#{query.w}") || 1200,
				height: parseInt("#{query.h}") || 500
			},
			debug: parseInt("#{query.debug}" || "0"),
			
			keys: {
				NODE: "#{query.node}" || "name",
				CHILDREN: "#{query.children}" || "children",
				VALUE: "#{query.value}" || "value",
				DOC: "#{query.doc}" || "doc"
			}			
		};

		const {NODE, NODES, VALUE, SIZE, PARENT, DOC} = opts.keys;
		//const {isString,isArray,Fetch,Log} = BASE;

append base_body
	script(src="/clients/d3-addons/d3-arrary.min.js")
	script(src="/clients/d3-addons/d3-collection.min.js")
	script(src="/clients/d3-addons/d3-path.min.js")
	script(src="/clients/d3-addons/d3-shape.min.js")
	script(src="/clients/d3-addons/d3-sankey.min.js")
	script(src="/clients/d3-addons/d3-stdlib.js")
	script.
		// https://observablehq.com/@d3/sankey-diagram
		function color(name) {
			const color = d3.scaleOrdinal(d3.schemeCategory10);
			return name => color(name.replace(/ .*/, ""));
		}

		function format(d) {
			const f = d3.format(",.0f");
			return d => `${f(d)} TWh`;
		}

		Fetch( opts, (data,svg) => {
			/*
			const svg = d3.create("svg")
					.attr("viewBox", [0, 0, width, height]);
			*/
			function chart( graph ) {
				function partition(graph) {
					alert( `sankey${align[0].toUpperCase()}${align.slice(1)}` );
					var sankey = d3.sankey()
							//.nodeAlign(d3[`sankey${align[0].toUpperCase()}${align.slice(1)}`])
							.nodeWidth(15)
							.nodePadding(10)
							.extent([[1, 5], [width - 1, height - 5]]);

					return sankey({
						nodes: graph.nodes.map(d => Object.assign({}, d)),
						links: graph.links.map(d => Object.assign({}, d))
					});
				}

				var
					width = svg.attr("width"),
					height = svg.attr("height"),

					align = ["Left-aligned", "Right-aligned", "Centered", "Justified"]; 

				svg.attr("viewBox", [0, 0, width, height]);

				const {nodes, links} = partition( graph );

				Log( nodes, links );

				svg.append("g")
						.attr("stroke", "#000")
						.selectAll("rect")
						.data(nodes)
						.join("rect")
						.attr("x", d => d.x0)
						.attr("y", d => d.y0)
						.attr("height", d => d.y1 - d.y0)
						.attr("width", d => d.x1 - d.x0)
						.attr("fill", d => color(d.name))
						.append("title")
						.text(d => `${d.name}\n${format(d.value)}`);

				var link = svg.append("g")
						.attr("fill", "none")
						.attr("stroke-opacity", 0.5)
						.selectAll("g")
						.data(links)
						.join("g")
						.style("mix-blend-mode", "multiply");

				if (edgeColor === "path") {
					const gradient = link.append("linearGradient")
							.attr("id", d => {
								d.uid = DOM.uid("link");
								return d.uid.id;
							})
								  // (d.uid = DOM.uid("link")).id)
							.attr("gradientUnits", "userSpaceOnUse")
							.attr("x1", d => d.source.x1)
							.attr("x2", d => d.target.x0);

					gradient.append("stop")
							.attr("offset", "0%")
							.attr("stop-color", d => color(d.source.name));

					gradient.append("stop")
							.attr("offset", "100%")
							.attr("stop-color", d => color(d.target.name));
				}
			
				link.append("path")
						.attr("d", d3.sankeyLinkHorizontal())
						.attr("stroke", d => edgeColor === "none" ? "#aaa"
								: edgeColor === "path" ? d.uid 
								: edgeColor === "input" ? color(d.source.name) 
								: color(d.target.name))
						.attr("stroke-width", d => Math.max(1, d.width));

				link.append("title")
						.text(d => `${d.source.name} → ${d.target.name}\n${format(d.value)}`);

				svg.append("g")
						.style("font", "10px sans-serif")
						.selectAll("text")
						.data(nodes)
						.join("text")
						.attr("x", d => d.x0 < width / 2 ? d.x1 + 6 : d.x0 - 6)
						.attr("y", d => (d.y1 + d.y0) / 2)
						.attr("dy", "0.35em")
						.attr("text-anchor", d => d.x0 < width / 2 ? "start" : "end")
						.text(d => d.name);
			}
			
			chart( data[0] );
		});

//- UNCLASSIFIED
