<template>
<div>
  	<div id="BeeSwarm"></div>
    <div id="tooltip">
		<strong class="system">&nbsp;</strong>
		<span class="label">&nbsp;</span>
	</div>
</div> 
</template>

<script>

import { EventBus } from '../main.js'
import * as Plotly from 'plotly.js'

export default {
  name: 'DataSpace',
  data () {
    return {
      dataInstances: '',
      PositiveValue: 75,
      NegativeValue: 25,
    }
  },
  methods: {
    initializeBeeSwarm () {   
      var svg = d3.select("#BeeSwarm");
      svg.selectAll("*").remove();
      var svg = d3.select("#tooltip");
      svg.selectAll("*").remove();
      
      var tooltip = d3.select("#tooltip")

      var width = 2500
      var height = 125
      var rectWidth = 20
      var rectHeight = 10
      
      var nodeR = 6
      var nodeStrokeW = 1.5
      
      var scale = 0.8

      var predictions = JSON.parse(this.dataInstances[2])

      var len = predictions.length;
      var instances = new Array(len);
      for (var i = 0; i < len; ++i) instances[i] = i
      instances.sort(function (a, b) { return predictions[a] < predictions[b] ? -1 : predictions[a] > predictions[b] ? 1 : 0; })

      predictions.sort()

      var colorInstances = []
      for (let i = 0; i < predictions.length; i++) {
        if (predictions[i] > 50 && predictions[i] > this.PositiveValue) {
          colorInstances.push("#33a02c")
        } else if (predictions[i] > 50 && predictions[i] <= this.PositiveValue) {
          colorInstances.push("#b2df8a")
        } else if (predictions[i] <= 50 && predictions[i] > this.NegativeValue) {
          colorInstances.push("#fb9a99")
        } else {
          colorInstances.push("#e31a1c")
        }
      }
  
      var data = d3.range(instances.length).map(function(d, i) {
        return {
          x : predictions[i],
          y : 0, // doesn't matter, will be reset before it matters
          r : nodeR,
          col: colorInstances[i],
          system : 'Predicted Probability',
          label : '(%)'
        }
      })
      
      var dx = function(d) { return d.x }
      var dy = function(d) { return d.y }
      var dr = function(d) { return d.r }
      var colorX = function(d) { return d.col }
      
      var extent = d3.extent(data, dx)
      
      // the range is set in such a way that portions of nodes are not drawn outside the g
      var xScale = d3.scale.linear()
        .domain(extent)
        .range([50, width-50])
        
      var norm = d3.random.normal(0, 4.0)
      
      var chart = d3.select("#BeeSwarm").append("svg")
          .attr("width", 2500)
          .attr("height", 125)
          .attr("pointer-events", "all")		
        .append("g")
          .attr("transform", "translate(0,0)")
          .on("mousemove", function() {
            var x = d3.event.pageX - 24 // subtract translation
            followMe.transition()
              .duration(10)
              .attr("x1", x).attr("x2", x)
          })
          .call(d3.behavior.zoom().x(xScale).scaleExtent([0.8, 10]).on("zoom", zoom))
        .append('g');
      
      // append a background rectangle to receive the pointer events
      // (otherwise zoom only works when the pointer is over a node)
      chart.append('rect')
        .attr('width', width)
        .attr('height', height)
        .attr('fill', 'white');
      
      var axis = d3.svg.axis().scale(xScale)
      chart.append("g").attr("class", "xAxis").call(axis)
      
      var followMe = chart.append("line")
        .attr("x1", 0).attr("x2", 0)
        .attr("y1", 0).attr("y2", 400)
        .style("stroke", "yellow")
        .style("stroke-width", '3px')

      function zoom() {
        chart.select(".xAxis").call(axis);
        
        if(scale != d3.event.scale)
          beeswarm()
        scale = d3.event.scale

        chart.selectAll("circle.node")
          .transition(10)
          .attr("cx", function(d) { return xScale(d.x) })
          .attr("cy", dy)
      }
      
      var nodes = chart.selectAll("circle.node")
        .data(data)
      
      beeswarm()
        
      nodes.enter().append("circle")
          .attr("class", "node")
          .attr("cx", function(d) { return xScale(d.x) })
          .attr("cy", dy)
          .attr("r", dr)
          .attr("fill", colorX)
          .style("stroke", "black")
          .style("stroke-width", 4)
          .on("mouseover", function(d) {
            tooltip.select(".system").html(d.system)
            return tooltip.select(".label").html(d.label)
          })
          .on("mouseout", function(d) {
            tooltip.select(".system").html("&nbsp;")
            return tooltip.select(".label").html("&nbsp;")
          })
          .on("click", function(d, i) {
            var inRange = function(dPrime, iPrime) {
              return Math.pow(i-iPrime, 2) <= 4
            }
          
            d3.selectAll("circle.node").filter(inRange).style("stroke", "yellow")
            d3.selectAll("circle.node").filter(function(dPrime, iPrime) { return !inRange(dPrime, iPrime) })
              .style("stroke", "black")
          })
      
      function beeswarm() {
        // reset vertical position
        data.map(function(d) {
          d.y = height / 2
        })
        for(var iter = 0; iter < 10; iter++) {
          var q = d3.geom.quadtree(data)
          for(var i = 0; i < data.length; i++)
            q.visit(collide(data[i]))
        }		
      }
        
      function collide(node) {
        var r = node.r + 16,
            nx1 = xScale(node.x) - r,
            nx2 = xScale(node.x) + r,
            ny1 = node.y - r,
            ny2 = node.y + r;
        return function(quad, x1, y1, x2, y2) {
          if (quad.point && (quad.point !== node)) {
            var x = xScale(node.x) - xScale(quad.point.x),
                y = node.y - quad.point.y,
                l = Math.sqrt(x * x + y * y),
                r = node.r + quad.point.r;
            if (l < r)
              node.y += norm()
          }
          return xScale(x1) > nx2
              || xScale(x2) < nx1
              || y1 > ny2
              || y2 < ny1	
        }
      }
    },
    reset () {
      var svg = d3.select("#BeeSwarm");
      svg.selectAll("*").remove();
    },
  },
  mounted () {
    EventBus.$on('SendtheChangeinRangePos', data => {this.PositiveValue = data})
    EventBus.$on('SendtheChangeinRangeNeg', data => {this.NegativeValue = data})
    EventBus.$on('quad', data => { this.dataInstances = data })
    EventBus.$on('quad', this.initializeBeeSwarm)

    EventBus.$on('reset', this.reset)
  }
}
</script>

<style>

text {
  font-family: sans-serif;
}

svg {
  display: block;
}

.nodeHighlighted {
  stroke: 'orange'
}

</style>