text: import { geoScaleToZoom } from '../geo';
  import { osmEntity } from '../osm';
  import { svgPointTransform } from './helpers';
  import { svgTagClasses } from './tag_classes';
  
  
  export function svgPoints(projection, context) {
  
      function markerPath(selection, klass) {
          selection
              .attr('class', klass)
              .attr('transform', 'translate(-8, -23)')
              .attr('d', 'M 17,8 C 17,13 11,21 8.5,23.5 C 6,21 0,13 0,8 C 0,4 4,-0.5 8.5,-0.5 C 13,-0.5 17,4 17,8 z');
      }
  
      function sortY(a, b) {
          return b.loc[1] - a.loc[1];
      }
  
  
      // Avoid exit/enter if we're just moving stuff around.
      // The node will get a new version but we only need to run the update selection.
      function fastEntityKey(d) {
          var mode = context.mode();
          var isMoving = mode && /^(add|draw|drag|move|rotate)/.test(mode.id);
          return isMoving ? d.id : osmEntity.key(d);
      }
  
  
      function drawTargets(selection, graph, entities, filter) {
          var fillClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
          var getTransform = svgPointTransform(projection).geojson;
          var activeID = context.activeID();
          var data = [];
  
          entities.forEach(function(node) {
              if (activeID === node.id) return;   // draw no target on the activeID
  
              data.push({
                  type: 'Feature',
                  id: node.id,
                  properties: {
                      target: true,
                      entity: node
                  },
                  geometry: node.asGeoJSON()
              });
          });
  
          var targets = selection.selectAll('.point.target')
              .filter(function(d) { return filter(d.properties.entity); })
              .data(data, function key(d) { return d.id; });
  
          // exit
          targets.exit()
              .remove();
  
          // enter/update
          targets.enter()
              .append('rect')
              .attr('x', -10)
              .attr('y', -26)
              .attr('width', 20)
              .attr('height', 30)
              .merge(targets)
              .attr('class', function(d) { return 'node point target ' + fillClass + d.id; })
              .attr('transform', getTransform);
      }
  
  
      function drawPoints(selection, graph, entities, filter) {
          var wireframe = context.surface().classed('fill-wireframe');
          var zoom = geoScaleToZoom(projection.scale());
  
          // Points with a direction will render as vertices at higher zooms..
          function renderAsPoint(entity) {
              return entity.geometry(graph) === 'point' &&
                  !(zoom >= 18 && entity.directions(graph, projection).length);
          }
  
          // All points will render as vertices in wireframe mode too..
          var points = wireframe ? [] : entities.filter(renderAsPoint);
          points.sort(sortY);
  
  
          var drawLayer = selection.selectAll('.layer-osm.points .points-group.points');
          var touchLayer = selection.selectAll('.layer-touch.points');
  
          // Draw points..
          var groups = drawLayer.selectAll('g.point')
              .filter(filter)
              .data(points, fastEntityKey);
  
          groups.exit()
              .remove();
  
          var enter = groups.enter()
              .append('g')
              .attr('class', function(d) { return 'node point ' + d.id; })
              .order();
  
          enter
              .append('path')
              .call(markerPath, 'shadow');
  
          enter
              .append('ellipse')
              .attr('cx', 0.5)
              .attr('cy', 1)
              .attr('rx', 6.5)
              .attr('ry', 3)
              .attr('class', 'stroke');
  
          enter
              .append('path')
              .call(markerPath, 'stroke');
  
          enter
              .append('use')
              .attr('transform', 'translate(-5, -19)')
              .attr('class', 'icon')
              .attr('width', '11px')
              .attr('height', '11px');
  
          groups = groups
              .merge(enter)
              .attr('transform', svgPointTransform(projection))
              .call(svgTagClasses());
  
          // Selecting the following implicitly
          // sets the data (point entity) on the element
          groups.select('.shadow');
          groups.select('.stroke');
          groups.select('.icon')
              .attr('xlink:href', function(entity) {
                  var preset = context.presets().match(entity, graph);
                  var picon = preset && preset.icon;
  
                  if (!picon) {
                      return '';
                  } else {
                      var isMaki = /^maki-/.test(picon);
                      return '#' + picon + (isMaki ? '-11' : '');
                  }
              });
  
  
          // Draw touch targets..
          touchLayer
              .call(drawTargets, graph, points, filter);
      }
  
  
      return drawPoints;
  }
  