<!-- The <cluster-sk> custom element declaration.

  Displays digests in a force layout, i.e. as svg circles as if they were
  attached via springs that were proportional to the distance between the
  digest images.

  Attributes:
    disabled: Boolean, if set to true the keyboard shortcuts will be disabled.

  Events:
    digest-select - Event generated when a digest is selected. The event
      detail is an array containing the selected digests.

  Methods:
    setData(data) - Data describing digests in a d3 compatible format. i.e.:

        {
          "nodes": [
            {"name":"a3801be6d11aa0c9316daaa0b22ca3ac"},
            {"name":"0ae9d1ee00a9f6149a61dd1c2c372fc3"}
          ],
          "links":[
              {"source":0, "target":0, "value":0},
              {"source":0, "target":1, "value":5.0775},
              {"source":0, "target":2, "value":5.0725},
          ]
        }

    startUse - to be called before the element is atively being used.
               It registers the necessary keyboard shortcuts.

    endUse - to be called once the element is not used any more.

    setTextNodes(text, additive) - Takes a map from digests to the text to display
                next to the digest node.

                If additive is true then just add the text to nodes in addition to
                existing text, else remove all existing text first.

    newTriageStatus(digests, status) - Set the new triage status for the array
      of given digests.
-->
<link rel="import" href="bower_components/iron-icons/iron-icons.html">

<link rel="import" href="help-dialog-sk.html">
<link rel="import" href="shared-styles.html">

<dom-module id="cluster-sk">
  <template>
    <style type="text/css" media="screen" include="shared-styles">
        ::content .link {
          stroke: #ccc;
        }

        ::content .node {
          cursor: pointer;
          fill: #ccc;
          stroke: #000;
          stroke-width: 1.5px;
        }

        ::content .node.positive circle {
          fill: #1B9E77;
        }

        ::content .node.negative circle {
          fill: #E7298A;
        }

        ::content .node.untriaged circle {
          fill: #A6761D;
        }

        ::content .node.selected circle {
          stroke-width: 5px;
        }

        :host {
          display: block;
          width: 100%;
        }

        ::content svg {
          width: 100%;
        }

        ::content .selectionRect {
          stroke-width: 1px;
          stroke-dasharray: 5px;
          stroke: black;
          stroke-opacity: 0.7;
          fill: transparent;
        }
    </style>

    <div hidden$="{{!_data}}"><a on-tap="_openHelpDialog"><iron-icon icon="help"></iron-icon></a></div>
    <!-- help dialog -->
    <help-dialog-sk id="helpDialog">
      <table>
        <tr><th>A</th><td>Increase spring size</td></tr>
        <tr><th>Z</th><td>Descrease spring size</td></tr>
        <tr><th>S</th><td>Descrease node overlap</td></tr>
        <tr><th>X</th><td>Increase node overlap</td></tr>
        <tr><th>?</th><td>Help</td></tr>
        <tr><th>Ctrl+Click</th><td>Add to selection, works on both nodes and
            parameters.
        </td></tr>
      </table>
    </help-dialog-sk>
    <content>
      <svg id="cluster"></svg>
    </content>
  </template>
  <script>
    Polymer({
      is: 'cluster-sk',

      properties: {
        _data: {
          type: Object,
          value: null
        },
        disabled: {
          type: Boolean,
          value: false,
          notify: true
        }
      },

      ready: function () {
        // The list of selected digests.
        this.selected = [];
        // Controls the link distance multiplier between nodes.
        this.scale = 10;
        // Controls the electrostatic charge between nodes, used in the
        // Barnes-Hut layout.
        this.charge = -100;
        this.width = 960;
        this.height = 500;

        // d3 force layout object.
        this.force = null;
        this.dragging = false;

        // Wire up mouse events.
        this.svg = d3.select(this.$.cluster)
          .attr('width', this.width)
          .attr('height', this.height)
          .on('mousedown', this._mouseDown.bind(this))
          .on('mousemove', this._mouseMove.bind(this))
          .on('mouseup', this._mouseUp.bind(this));
      },

      setData: function(data) {
        this._data = data;
        this._reloadSVG();
      },

      startUse: function() {
        this._active = true;
        this.width = this.height = -1;
        this._resizeWatcher();
        this.listen(document, 'keypress', '_handleKeyDown');
      },

      endUse: function() {
        this._active = false;
        this.cancelAsync(this._resizeHandle);
        this.unlisten(document, 'keypress', '_handleKeyDown');
      },

      newTriageStatus: function (digests, status) {
        digests.forEach(function (digest) {
          var ele = $$$('#x' + digest, this);
          var selected = Polymer.dom(ele).classList.contains('selected');
          Polymer.dom(ele).setAttribute('class', 'node ' + status);
          Polymer.dom(ele).classList.toggle('selected', selected);
        }.bind(this));
        this._data.nodes.forEach(function (e) {
          if (digests.indexOf(e.name) != -1) {
            e.status = status;
          }
        }.bind(this));
      },

      // Takes a map from digests to the text to display next to the digest node.
      //
      // additive - If true then just add the text to nodes in addition to
      //            existing text, else remove all existing text first.
      setTextNodes: function (text, additive) {
        if (!additive) {
          this._clearTextNodes();
        }
        // Use a data attribute 'data-count' to store the number of non-empty
        // text strings attached to a node.
        node = this.svg.selectAll('.node').attr('data-count', function (d) {
          if (!additive) {
            return 1;
          }
          var count = +d3.select(this).attr('data-count') || 0;
          if (text[d.name]) {
            return count + 1;
          } else {
            return count;
          }
        }).append('text').attr('dx', 14).attr('dy', function (d) {
          return d3.select(this.parentElement).attr('data-count') * 20;
        }).text(function (d) {
          return text[d.name];
        });

      },

      _openHelpDialog: function() {
        this.$.helpDialog.open();
      },

      _mouseDown: function () {
        if (this.dragging) {
          return;
        }
        var p = d3.mouse(this);
        this.svg.append('rect').attr({
          rx: 6,
          ry: 6,
          class: 'selectionRect',
          x: p[0],
          y: p[1],
          width: 0,
          height: 0
        });
      },

      _mouseMove: function () {
        if (this.dragging) {
          return;
        }
        var s = this.svg.select('.selectionRect');
        if (s.empty()) {
          return;
        }
        var p = d3.mouse(this);
        var d = {
          x: parseInt(s.attr('x'), 10),
          y: parseInt(s.attr('y'), 10),
          width: parseInt(s.attr('width'), 10),
          height: parseInt(s.attr('height'), 10)
        };
        var dx = p[0] - d.x;
        var dy = p[1] - d.y;
        if (dx < 1) {
          d.x = p[0];
          d.width -= dx;
        } else {
          d.width = dx;
        }
        if (dy < 1) {
          d.y = p[1];
          d.height -= dy;
        } else {
          d.height = dy;
        }
        s.attr(d);
      },

      _mouseUp: function () {
        if (this.dragging) {
          return;
        }
        // Clear all old selections.
        $$('.node.selected').forEach(function (ele) {
          Polymer.dom(ele).classList.toggle('selected', false);
        });
        // Build the list of selected nodes.
        this.selected = [];
        var r = $$$('.selectionRect', this);
        var hits = $$$('svg', this).getIntersectionList(r.getBBox(), null);
        for (var i = 0; i < hits.length; i++) {
          var ele = hits.item(i);
          if (ele.nodeName == 'circle') {
            var p = ele.parentElement;
            Polymer.dom(p).classList.toggle('selected', true);
            // Note that we use getAttribute because SVG doesn't support
            // ele.dataset.* type access.
            this.selected.push(p.getAttribute('data-name'));
          }
        }
        this.fire('digest-select', this.selected.slice());

        // Remove the selectionRect.
        $$('.selectionRect', this.$.svg).forEach(function (ele) {
          Polymer.dom(ele.parentElement).removeChild(ele);
        });
      },

      _handleKeyDown: function (e) {
        if (this.disabled) {
          return;
        }

        var c = String.fromCharCode(e.keyCode).toUpperCase();
        switch (c) {
        case 'A':
          this.scale = this.scale * 2;
          this.force.start();
          break;
        case 'Z':
          this.scale = this.scale / 2;
          this.force.start();
          break;
        case 'S':
          this.charge = this.charge * 2;
          this.force.start();
          break;
        case 'X':
          this.charge = this.charge / 2;
          this.force.start();
          break;
        case '?':
          this._openHelpDialog();
          break;
        }
      },

      _dragstart: function (d) {
        this.dragging = true;
        var e = d3.event.sourceEvent;
        if (e.ctrlKey || e.shiftKey) {
          // Ctrl or Shift means to toggle the selected state of a digest.
          var index = this.selected.indexOf(d.name);
          Polymer.dom($$$('#x' + d.name, this)).classList.toggle('selected', index == -1);
          if (index == -1) {
            this.selected.push(d.name);
          } else {
            this.selected.splice(index, 1);
          }
        } else {
          this.selected = [d.name];
          $$('.node.selected').forEach(function (ele) {
            Polymer.dom(ele).classList.toggle('selected', false);
          });
          Polymer.dom($$$('#x' + d.name, this)).classList.toggle('selected', true);
        }

        this.fire('digest-select', this.selected.slice());
      },

      _dragend: function (d) {
        this.dragging = false;
      },

      _reloadSVG: function () {
        this.svg.selectAll('.link,.node').remove();

        this.force = d3.layout.force()
          .gravity(0.05)
          .linkDistance(function (d) { return d.value * this.scale; }.bind(this))
          .charge(function () { return this.charge; }.bind(this))
          .size([this.width, this.height])
          .nodes(this._data.nodes)
          .links(this._data.links)
          .start();

        this.force.drag()
          .on('dragstart', this._dragstart.bind(this))
          .on('dragend', this._dragend.bind(this));

        var link = this.svg.selectAll('.link')
          .data(this._data.links)
          .enter()
          .append('line')
          .attr('class', 'link');

        var node = this.svg.selectAll('.node')
          .data(this._data.nodes)
          .enter()
          .append('g')
          .attr('class', function (d) { return 'node ' + d.status; })
          .attr('data-name', function (d) { return d.name; })
          .attr('id', function (d) { return 'x' + d.name; })
          .call(this.force.drag);

        node.append('circle')
          .attr('r', 12);

        this.force.on('tick', function () {
          link
          .attr('x1', function (d) { return d.source.x; })
          .attr('y1', function (d) { return d.source.y; })
          .attr('x2', function (d) { return d.target.x; })
          .attr('y2', function (d) { return d.target.y; });

          node.attr('transform', function (d) { return 'translate(' + d.x + ',' + d.y + ')'; });
        });
      },

      // Watch the size of the svg parents element and when it changes then
      // then resize the svg element to match.
      _resizeWatcher: function () {
        if (this._active) {
          this._resizeHandle = this.async(this._resizeWatcher.bind(this), 300);
        }
        if (!this.force) {
          return;
        }

        var w = Math.round(window.getComputedStyle(this, null).getPropertyValue('width').slice(0, -2));
        var h = Math.round(window.getComputedStyle(this, null).getPropertyValue('height').slice(0, -2));
        if (w != this.width || h != this.height) {
          this.svg.attr('width', w).attr('height', h);
          this.force.size([
            w,
            h
          ]).start();

          // Measure again since the resize of svg might have caused a tiny change in the size of
          // the parent window.
          w = Math.round(window.getComputedStyle(this, null).getPropertyValue('width').slice(0, -2));
          h = Math.round(window.getComputedStyle(this, null).getPropertyValue('height').slice(0, -2));
          this.width = w;
          this.height = h;
        }
      },

      // Removes all the text on the digest nodes.
      _clearTextNodes: function () {
        var node = this.svg.selectAll('.node text').remove();
      }
    });
  </script>
</dom-module>
