//- UNCLASSIFIED

extends base
append base_parms
	- tech = "d3"

append base_help
	:markdown
		Display d3 world map chart using parameters:

			src = source url returning map [ { name: "...", code: "", doc: "", lat: N, lon: N, ... }, ... ]
			name = "name" || "name%..." || "" of source record(s)
			pivots = "key,key,..." || "" source record grouping keys
			w = drawing width
			h = drawing height
			debug = level of debugging alerts
			node,nodes,value,size,parent,doc = tree keys

append base_head
	style.
		.states :hover {
			fill: red;
		}

		.state-borders {
			fill: none;
			stroke: #fff;
			stroke-width: 0.5px;
			stroke-linejoin: round;
			stroke-linecap: round;
			pointer-events: none;
		}

	script.
		var opts = {
			ds: "#{query.pivots}"
				? "!{query.src}.tree?name=#{query[NAME]}&_sort=#{query.pivots}"
				: "#{query[NAME]}"
							? "!{query.src}.schema?name=#{query[NAME]}"
							: "!{query.src}" || "mapdata.json",

			url: "#{url}",
			family: "usmap,usmap",

			dims: {
				margin: {top: 20, right: 90, bottom: 30, left: 90},
				width: parseInt("#{query.w}") || 1200,
				height: parseInt("#{query.h}") || 500
			},
			debug: parseInt("#{query.debug}"),

			keys: {
				NODE: "#{query.node}" || "name",
				NODES: "#{query.nodes}" || "children",
				VALUE: "#{query.value}" || "value",
				PARENT: "#{query.parent}" || "parent",
				SIZE: "#{query.size}" || "size",
				DOC: "#{query.doc}" || "doc"
			}
		};
		
		const {NODE, NODES, VALUE, SIZE, PARENT, DOC} = opts.keys;

append base_body
	div(id="container")
	div(class="map",id="basic")
	script(src="/clients/topojson.min.js")
	script(src="/clients/datamaps/datamaps.world.min.js")
											
	// http://bl.ocks.org/micahstubbs/8e15870eb432a21f0bc4d3d527b2d14f
	// https://d3js.org/topojson.v3.min.js
	// https://unpkg.com/world-atlas@1.1.4/world/110m.json
	// https://unpkg.com/us-atlas@1.0.2/us/10m.json	
	// https://observablehq.com/@d3/bubble-map
	script.
		var		// map projection controls
			projs = {
				stereographic: d3.geoStereographic,
				orthographic: d3.geoOrthographic,
				azEqArea: d3.geoAzimuthalEqualArea,
				azEqDistance: d3.geoAzimuthalEquidistance,
				gnomonic: d3.geoGnomonic,
				eqEarth:  d3.geoEqualEarth,
				conicConformal: d3.geoConicConformal
			},
			body = d3.select("body"),
			input = "select".d3add(body, { value: "stereographic", id:"_layout"} );

		Object.keys(projs)
		.forEach( (proj,n) => input.insert("option").attr( "value", proj ).text( proj ) );

		if ( d3.version.startsWith("3.") ) // use datamaps
			Fetch( "/mapdata.json" , maps => {	// country base data
				var cmap = {};
				maps.forEach( map => {
					cmap[map.name.toUpperCase()] = {
						fillKey: map.code.toUpperCase(),
						info: map.doc
					}
				});

				Log(cmap);

				Fetch( opts, (evs,svg) => {		// event data
					var
						width = svg.attr("width"),
						height = svg.attr("height");

					var vmap = [];

					if (false)
					evs.forEach( ev => {
						vmap.push({
							name: ev.Source,
							radius: ev.Radius,
							longitude: ev.Location.x,
							latitude: ev.Location.y,
							fillKey: "VOXEL"
						});	
					});

					var
						map = new Datamap({
							//responsive: true,

							//bubbles: vmap,

							element: document.getElementById('basic')
							/*
							geographyConfig: {
								popupTemplate: function (geo,data) {
									return [
										geo ? geo.properties.name : "",
										data ? data.info : "nada"
									].join("<br>").tag("div",{class:"hoverinfo"});
								}
							},

							fills: {
								HIGH: '#afafaf',
								LOW: '#123456',
								MEDIUM: 'blue',
								VOXEL: 'red', //'rgb(1,0,0)',
								defaultFill: 'green'
							},

							data: cmap
							*/
						});
						/*
						map.bubbles(vmap, {
							popupTemplate: function (geo,data) {
								return [
									//geo ? geo.properties.name : "",
									data ? JSON.stringify(data) : "nada"
								].join("<br>").tag("div",{class:"hoverinfo"});
							}});

						map.legend();

						d3.select(window).on("resize", function () {
						map.resize();
					});	
						*/
				});
			});

		else 
			Fetch( "/stores/worldatlas.json" , worldatlas => {		// country outlines
				function update(layout) {
					//canvas.remove();
					var path = d3.geoPath( projs[layout](), context );

					context.beginPath();
					path(topojson.mesh( world ));
					context.stroke();
				}
				input.on( "change", () => {
					var 
						el = input._groups[0][0], //v3 use input[0][0],		// dom is a major Kludge!
						value = el.value,
						id = el.id;

					update(value);				
				});

				var 
					world = worldatlas[0],
					//context = d3.select("canvas").node().getContext("2d"),
					canvas = d3.select('#container')
							.append('canvas')
							.attr('width', opts.dims.width)
							.attr('height', opts.dims.height),

					context = canvas.node().getContext('2d');

				//Log("can", canvas, context, d3.select('#container'));
				update( "stereographic" );

				Fetch( "/mapdata.json" , maps => {	// country base data
					var cmap = {};
					maps.forEach( map => {
						cmap[map.name.toUpperCase()] = {
							fillKey: map.code.toUpperCase(),
							info: map.doc
						}
					});

					Log(cmap);

					Fetch( opts, (evs,svg) => {		// country event data
						var
							width = svg.attr("width"),
							height = svg.attr("height");

						var vmap = [];

						if (false)
						evs.forEach( ev => {
							vmap.push({
								name: ev.Source,
								radius: ev.Radius,
								longitude: ev.Location.x,
								latitude: ev.Location.y,
								fillKey: "VOXEL"
							});	
						});
					});
				});
			});

// UNCLASSIFIED