//- UNCLASSIFIED
extends base
append base_help
	:markdown
		Display cluster chart using parameters:

			src = source url returning [ {x: N, y: N}, ... ]
			pivots = key,key,...
			w = drawing width
			h = drawing height
			debug = dump derived options
			node,children,value,size,parent = key names

append base_parms
	- tech = "d3"
	
append base_head

	style.
		path.arc {
			cursor: move;
			fill: #fff;
		}
		.node circle {
			fill: #fff;
			stroke: steelblue;
			stroke-width: 1.5px;
		}
		.node {
			font-size: 10px;
			pointer-events: none;
		}
		.link {
			fill: none;
			stroke: #ccc;
			stroke-width: 1.5px;
		}

	script.
		var opts = {
			ds: "/!{query.src}.tree?ID=#{query.id}&_sort=#{query.pivots}",
			w: parseInt("#{query.w}") || 200,
			h: parseInt("#{query.h}") || 200,
			debug: parseInt("#{query.debug}"),
			NODE: "#{query.node}" || "name",
			CHILDREN: "#{query.children}" || "children",
			VALUE: "#{query.value}" || "value",
			PARENT: "#{query.parent}" || "parent",
			SIZE: "#{query.size}" || "size"										
		};
		
		const {NODE, CHILDREN, VALUE, SIZE, PARENT} = opts;

append base_body

	script.
		function click(d) { 
			var isView = d.details.constructor == String;

			var doc = window.open(
				isView ? d.details : "",
				"_blank",
				"left="+d.x+"px,"
				+ "top="+d.y+"px,"
				+ "width=50,height=50,location=0,menubar=0,status=0,titlebar=0,toolbar=0");

			if ( !isView )
				doc.document.write(JSON.stringify( d.details ));
		}

		function mouse(e) {
			return [e.pageX - rx, e.pageY - ry];
		}

		function mousedown() {
			m0 = mouse(d3.event);
			d3.event.preventDefault();
		}

		function mousemove() {
			if (m0) {
				var m1 = mouse(d3.event),
				dm = Math.atan2(cross(m0, m1), dot(m0, m1)) * 180 / Math.PI,
				tx = "translate3d(0," + (ry - rx) + "px,0)rotate3d(0,0,0," + dm + "deg)translate3d(0," + (rx - ry) + "px,0)";
				svg
				.style("-moz-transform", tx)
				.style("-ms-transform", tx)
				.style("-webkit-transform", tx);
			}
		}

		function mouseup() {
			if (m0) {
				var m1 = mouse(d3.event),
					dm = Math.atan2(cross(m0, m1), dot(m0, m1)) * 180 / Math.PI,
					tx = "rotate3d(0,0,0,0deg)";

				rotate += dm;
				if (rotate > 360) rotate -= 360;
				else if (rotate < 0) rotate += 360;
				m0 = null;

				svg
				.style("-moz-transform", tx)
				.style("-ms-transform", tx)
				.style("-webkit-transform", tx);

				vis
				.attr("transform", "translate(" + rx + "," + ry + ")rotate(" + rotate + ")")
				.selectAll("g.node text")
				.attr("dx", function(d) { return (d.x + rotate) % 360 < 180 ? 8 : -8; })
				.attr("text-anchor", function(d) { return (d.x + rotate) % 360 < 180 ? "start" : "end"; })
				.attr("transform", function(d) { return (d.x + rotate) % 360 < 180 ? null : "rotate(180)"; });
			}
		}

		function cross(a, b) {
			return a[0] * b[1] - a[1] * b[0];
		}

		function dot(a, b) {
			return a[0] * b[0] + a[1] * b[1];
		}
		
		var 
			w = opts.w || 1200,
			h = opts.h || 500,
			rx = w / 2,
			ry = h / 2,
			m0,
			rotate = 0;

		var 
			cluster = d3.layout.cluster()
				.size([360, ry - 120])
				.sort(null),

			diagonal = d3.svg.diagonal.radial()
				.projection(function(d) { return [d.y, d.x / 180 * Math.PI]; }),

			svg = d3.select("#content").append("div")
				.style("width", w + "px")
				.style("height", h + "px"),

			vis = svg.append("svg:svg")
				.attr("width", w)
				.attr("height", h)
				.append("svg:g")
				.attr("transform", "translate(" + rx + "," + ry + ")");

		vis.append("svg:path")
			.attr("class", "arc")
			.attr("d", d3.svg.arc().innerRadius(ry - 120).outerRadius(ry).startAngle(0).endAngle(2 * Math.PI))
			.on("mousedown", mousedown);

		d3.select(window)
			.on("mousemove", mousemove)
			.on("mouseup", mouseup);

		BASE.Fetch( opts, recs => {
			var nodes = cluster.nodes(recs);

			var link = vis.selectAll("path.link")
				.data(cluster.links(nodes))
				.enter().append("svg:path")
				.attr("class", "link")
				.attr("d", diagonal);

			var node = vis.selectAll("g.node")
				.data(nodes)
				.enter().append("svg:g")
				.attr("class", "node")
				.attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; });

			node.append("svg:circle")
				.attr("r", 3);

			node.append("svg:text")
				.attr("dx", function(d) { return d.x < 180 ? 8 : -8; })
				.attr("dy", ".31em")
				.attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
				.attr("transform", function(d) { return d.x < 180 ? null : "rotate(180)"; })
				.text(function(d) { return d.name; });
		});

//- UNCLASSIFIED
