'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = undefined;

var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

var _createClass2 = require('babel-runtime/helpers/createClass');

var _createClass3 = _interopRequireDefault(_createClass2);

var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');

var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);

var _get2 = require('babel-runtime/helpers/get');

var _get3 = _interopRequireDefault(_get2);

var _inherits2 = require('babel-runtime/helpers/inherits');

var _inherits3 = _interopRequireDefault(_inherits2);

var _dec,
    _class,
    _class2,
    _temp,
    _default_zhHans_number = Intl.NumberFormat('zh-Hans', { style: 'decimal' }).format,
    _percent_zhHans_number = Intl.NumberFormat('zh-Hans', { style: 'percent' }).format; /* eslint "import/no-extraneous-dependencies": "warn" */


// TODO change the d3 dependency in package.json to match specific modules


var _propTypes = require('prop-types');

var _d3Array = require('d3-array');

var _d3Axis = require('d3-axis');

var _d3Scale = require('d3-scale');

var _d3Selection = require('d3-selection');

var _lib = require('@instructure/ui-themeable/lib');

var _lib2 = _interopRequireDefault(_lib);

var _formatMessage = require('../../../../common/format-message');

var _formatMessage2 = _interopRequireDefault(_formatMessage);

var _D3Component2 = require('../D3Component');

var _D3Component3 = _interopRequireDefault(_D3Component2);

var _theme = require('./theme');

var _theme2 = _interopRequireDefault(_theme);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var styles = {
  template: function template(theme) {
    return '/*  imported from styles.css  */\n\n.Distribution__styles__bar {\n  fill: ' + theme.barFillColor + ';\n}\n\n.Distribution__styles__barContainer {\n}\n\n.Distribution__styles__xAxis {\n}\n\n.Distribution__styles__barLabel {\n  font-family: ' + theme.barLabelFontFamily + ';\n  font-size: ' + theme.barLabelFontSize + ';\n  text-anchor: middle;\n}\n';
  },
  'bar': 'Distribution__styles__bar',
  'barContainer': 'Distribution__styles__barContainer',
  'xAxis': 'Distribution__styles__xAxis',
  'barLabel': 'Distribution__styles__barLabel'
};


var MARGIN_T = 0;
var MARGIN_B = 28;

/**
 *   A component to render an a11y friendly distribution of scores across users.
 *   Underneath the chart is two accessible features:
 *     1. A keyboard friendly set of min(10, bucketCounts) buckets {0-10%, 10-20%, ..., 90-100%}
 *     with the number of users in that slice
 *     2. A screenreader-only block of content providing a table version of all the data
 *
 *     ```jsx_example
 *      <Distribution
 *        summaryDistribution={Array.from({length: 10}, () => Math.floor(Math.random() * 5))}
 *        visualDistribution={Array.from({length: 101}, () => Math.floor(Math.random() * 5))}
 *      />
 *      ```
 *  **/
// TODO: Less inheritance, more composition...
var Distribution = (_dec = (0, _lib2.default)(_theme2.default, styles), _dec(_class = (_temp = _class2 = function (_D3Component) {
  (0, _inherits3.default)(Distribution, _D3Component);

  function Distribution() {
    (0, _classCallCheck3.default)(this, Distribution);
    return (0, _possibleConstructorReturn3.default)(this, (Distribution.__proto__ || Object.getPrototypeOf(Distribution)).apply(this, arguments));
  }

  (0, _createClass3.default)(Distribution, [{
    key: 'calculateAxis',
    value: function calculateAxis(props) {
      // the x scale is static since it will always represent the BucketCount
      // percentiles, so we can avoid recalculating it on every update:
      this.x = (0, _d3Scale.scaleBand)().rangeRound([0, this.width]).paddingInner(props.barPaddingInner).paddingOuter(props.barPaddingOuter).domain((0, _d3Array.range)(props.visualDistribution.length));

      var highest = (0, _d3Array.max)(props.visualDistribution);
      this.y = (0, _d3Scale.scaleLinear)().rangeRound([this.height, props.barPaddingTop]).domain([0, highest]);

      this.xAxis = (0, _d3Axis.axisBottom)(this.x).tickSize([0]).tickValues((0, _d3Array.range)(props.visualDistribution.length));
    }
  }, {
    key: 'weightedAvg',
    value: function weightedAvg(data) {
      var partitions = data.length - 1;
      var totalStudents = (0, _d3Array.sum)(data);
      var avg = data.reduce(function (total, count, index) {
        // Assumes even weight of scores across distribution
        var score = index / partitions;
        return total + score * count;
      }, 0.0) / totalStudents;

      var avgPartition = Math.floor(avg * partitions);
      return {
        avg: avg,
        aboveAvg: (0, _d3Array.sum)(data.slice(avgPartition)),
        belowAvg: (0, _d3Array.sum)(data.slice(0, avgPartition))
      };
    }
  }, {
    key: 'summarizeChart',
    value: function summarizeChart() {
      var data = this.props.summaryDistribution || this.props.visualDistribution;
      if (data.length <= 1) {
        return '';
      }
      var avgInfo = this.weightedAvg(data);
      if (avgInfo.belowAvg + avgInfo.aboveAvg < 1) {
        return '';
      }

      var textForScreenreaders = avgInfo.aboveAvg + ' \u5B66\u751F\u5F97\u5206\u9AD8\u4E8E\u5E73\u5747\u6C34\u5E73\u3001\u5904\u5728\u5E73\u5747\u6C34\u5E73\u6216\u4F4E\u4E8E ' + avgInfo.belowAvg + '\u3002';

      data.forEach(function (datum, i) {
        if (datum > 0) {
          var _s, _n, _i, _v;

          textForScreenreaders += (_s = datum, _n = +_s, (_i = Math.floor(Math.abs(+_s)), _v = (_s + '.').split('.')[1].length, _i === 1 && _v === 0 ? _default_zhHans_number(datum) + '\u4E2A\u5B66\u751F\u8BC4\u5206\u4ECB\u4E8E' + _percent_zhHans_number(i / data.length) + '\u548C' + _percent_zhHans_number((i + 1) / data.length) + '\u4E4B\u95F4\u3002' : _default_zhHans_number(datum) + '\u4E2A\u5B66\u751F\u8BC4\u5206\u4ECB\u4E8E' + _percent_zhHans_number(i / data.length) + '\u548C' + _percent_zhHans_number((i + 1) / data.length) + '\u4E4B\u95F4\u3002'));
        }
      });

      return textForScreenreaders;
    }
  }, {
    key: 'createChart',
    value: function createChart(node, props) {
      // parentNode for IE11
      var parentWidth = (node.parentElement || node.parentNode || {}).offsetWidth;
      this.width = props.chartWidth || parentWidth;
      this.height = props.chartHeight;
      this.viewportHeight = this.height + MARGIN_T + MARGIN_B;

      this.calculateAxis(props);

      var svg = (0, _d3Selection.select)(node).attr('role', 'document').attr('aria-role', 'document').attr('width', '100%').attr('height', '100%').attr('viewBox', '0 0 ' + this.width + ' ' + this.viewportHeight).attr('preserveAspectRatio', 'xMidYMax').append('g');

      this.title = _D3Component3.default.addTitle(svg, '\u767E\u5206\u4F4D\u5206\u6570\u56FE');

      svg.append('g').attr('class', styles.xAxis).attr('aria-hidden', true).attr('transform', 'translate(0,' + this.height + ')').call(this.xAxis).selectAll('text').attr('class', styles.barLabel).attr('y', 9);

      var clipKey = 'clipPath' + this.width + 'x' + this.height;
      var clipPath = svg.append('clipPath').attr('id', clipKey);
      clipPath.append('rect').attr('x', 0).attr('y', 0).attr('width', this.width).attr('height', this.height);

      var barContainer = svg.append('g').attr('class', styles.barContainer).attr('clip-path', 'url(#' + clipKey + ')');

      this.barContainer = barContainer;

      return svg;
    }
  }, {
    key: 'updateChart',
    value: function updateChart(svg, props) {
      this.renderBars(this.barContainer, props, styles.bar);
    }
  }, {
    key: 'renderBars',
    value: function renderBars(node, props, barStyle) {
      this.chartData = props.visualDistribution;
      var height = this.height;
      var x = this.x;
      var y = this.y;

      var bars = node.selectAll('rect').data(this.chartData);
      var rects = bars.enter().append('rect').classed(barStyle, true).attr('x', function (d, i) {
        return x(i);
      }).attr('width', x.bandwidth());
      this.applyTransition(rects, function (rects) {
        return rects.attr('y', height).attr('height', 0);
      }, function (rects) {
        return rects.attr('y', y).attr('height', function (d) {
          return height - y(d);
        });
      });

      bars.exit().remove();
    }
  }, {
    key: 'render',
    value: function render() {
      return (0, _get3.default)(Distribution.prototype.__proto__ || Object.getPrototypeOf(Distribution.prototype), 'render', this).call(this);
    }
  }]);
  Distribution.displayName = 'Distribution'
  ;
  return Distribution;
}(_D3Component3.default), _class2.displayName = 'Distribution', _class2.propTypes = Object.assign({}, _D3Component3.default.propTypes, {
  /* *
   * * a fallback minimal distribution for tab-able, keyboard navigable buckets
   * * typically this will be ~ 10 buckets
   * */
  summaryDistribution: _propTypes.PropTypes.arrayOf(_propTypes.PropTypes.node),
  /* *
   * * A list of score values for each bucket.  Size of this array determines the number of buckets
   * */
  visualDistribution: _propTypes.PropTypes.arrayOf(_propTypes.PropTypes.node).isRequired
}), _class2.defaultProps = {
  animateDelay: 200,
  animateDuration: 900,
  barPaddingInner: 0.25, // Spacing between bars, so each is visible, could be accomplished by borders
  barPaddingOuter: 0, // Spacing between bars, so each is visible, could be accomplished by borders
  barPaddingTop: 0, // Spacing between highest bar and top of chart, pixels
  chartHeight: 200, // Height in pixels
  visualDistribution: []
}, _temp)) || _class);
exports.default = Distribution;