text: import d3 from 'd3';
  import box from '@/lib/visualizations/d3box';
  import editorTemplate from './box-plot-editor.html';
  
  function boxPlotRenderer() {
    return {
      restrict: 'E',
      template: '<div></div>',
      link($scope, elm) {
        function calcIqr(k) {
          return (d) => {
            const q1 = d.quartiles[0];
            const q3 = d.quartiles[2];
            const iqr = (q3 - q1) * k;
  
            let i = -1;
            let j = d.length;
  
            // eslint-disable-next-line no-plusplus
            while (d[++i] < q1 - iqr);
            // eslint-disable-next-line no-plusplus
            while (d[--j] > q3 + iqr);
            return [i, j];
          };
        }
  
        $scope.$watch('[queryResult && queryResult.getData(), visualization.options]', () => {
          if ($scope.queryResult.getData() === null) {
            return;
          }
  
          const data = $scope.queryResult.getData();
          const parentWidth = d3.select(elm[0].parentNode).node().getBoundingClientRect().width;
          const margin = {
            top: 10, right: 50, bottom: 40, left: 50, inner: 25,
          };
          const width = parentWidth - margin.right - margin.left;
          const height = 500 - margin.top - margin.bottom;
  
          let min = Infinity;
          let max = -Infinity;
          const mydata = [];
          let value = 0;
          let d = [];
          const xAxisLabel = $scope.visualization.options.xAxisLabel;
          const yAxisLabel = $scope.visualization.options.yAxisLabel;
  
          const columns = $scope.queryResult.getColumnNames();
          const xscale = d3.scale.ordinal()
            .domain(columns)
            .rangeBands([0, parentWidth - margin.left - margin.right]);
  
          let boxWidth;
          if (columns.length > 1) {
            boxWidth = Math.min(xscale(columns[1]), 120.0);
          } else {
            boxWidth = 120.0;
          }
          margin.inner = boxWidth / 3.0;
  
          columns.forEach((column, i) => {
            d = mydata[i] = [];
            data.forEach((row) => {
              value = row[column];
              d.push(value);
              if (value > max) max = Math.ceil(value);
              if (value < min) min = Math.floor(value);
            });
          });
  
          const yscale = d3.scale.linear()
            .domain([min * 0.99, max * 1.01])
            .range([height, 0]);
  
          const chart = box()
            .whiskers(calcIqr(1.5))
            .width(boxWidth - 2 * margin.inner)
            .height(height)
            .domain([min * 0.99, max * 1.01]);
          const xAxis = d3.svg.axis()
            .scale(xscale)
            .orient('bottom');
  
  
          const yAxis = d3.svg.axis()
            .scale(yscale)
            .orient('left');
  
          const xLines = d3.svg.axis()
            .scale(xscale)
            .tickSize(height)
            .orient('bottom');
  
          const yLines = d3.svg.axis()
            .scale(yscale)
            .tickSize(width)
            .orient('right');
  
          function barOffset(i) {
            return xscale(columns[i]) + (xscale(columns[1]) - margin.inner) / 2.0;
          }
  
          d3.select(elm[0]).selectAll('svg').remove();
  
          const plot = d3.select(elm[0])
            .append('svg')
            .attr('width', parentWidth)
            .attr('height', height + margin.bottom + margin.top)
            .append('g')
            .attr('width', parentWidth - margin.left - margin.right)
            .attr('transform', `translate(${margin.left},${margin.top})`);
  
          d3.select('svg').append('text')
            .attr('class', 'box')
            .attr('x', parentWidth / 2.0)
            .attr('text-anchor', 'middle')
            .attr('y', height + margin.bottom)
            .text(xAxisLabel);
  
          d3.select('svg').append('text')
            .attr('class', 'box')
            .attr('transform', `translate(10,${(height + margin.top + margin.bottom) / 2.0})rotate(-90)`)
            .attr('text-anchor', 'middle')
            .text(yAxisLabel);
  
          plot.append('rect')
            .attr('class', 'grid-background')
            .attr('width', width)
            .attr('height', height);
  
          plot.append('g')
            .attr('class', 'grid')
            .call(yLines);
  
          plot.append('g')
            .attr('class', 'grid')
            .call(xLines);
  
          plot.append('g')
            .attr('class', 'x axis')
            .attr('transform', `translate(0,${height})`)
            .call(xAxis);
  
          plot.append('g')
            .attr('class', 'y axis')
            .call(yAxis);
  
          plot.selectAll('.box').data(mydata)
            .enter().append('g')
            .attr('class', 'box')
            .attr('width', boxWidth)
            .attr('height', height)
            .attr('transform', (_, i) => `translate(${barOffset(i)},${0})`)
            .call(chart);
        }, true);
      },
    };
  }
  
  function boxPlotEditor() {
    return {
      restrict: 'E',
      template: editorTemplate,
    };
  }
  
  export default function init(ngModule) {
    ngModule.directive('boxplotRenderer', boxPlotRenderer);
    ngModule.directive('boxplotEditor', boxPlotEditor);
  
    ngModule.config((VisualizationProvider) => {
      const renderTemplate =
          '<boxplot-renderer ' +
          'options="visualization.options" query-result="queryResult">' +
          '</boxplot-renderer>';
  
      const editTemplate = '<boxplot-editor></boxplot-editor>';
  
      const defaultOptions = {
        defaultRows: 8,
        minRows: 5,
      };
  
      VisualizationProvider.registerVisualization({
        type: 'BOXPLOT',
        name: 'Boxplot (Deprecated)',
        defaultOptions,
        renderTemplate,
        editorTemplate: editTemplate,
      });
    });
  }
  