function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }

function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }

function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }

function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }

function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }

function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }

function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }

function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }

/*
Copyright (c) 2018-2019 Uber Technologies, Inc.

This source code is licensed under the MIT license found in the
LICENSE file in the root directory of this source tree.
*/
import * as React from 'react';
import { Button } from '../button/index.js';
import { ButtonGroup, MODE } from '../button-group/index.js';
import { Input } from '../input/index.js';
import { useStyletron } from '../styles/index.js';
import { Paragraph4 } from '../typography/index.js';
import { COLUMNS, NUMERICAL_FORMATS, NUMERICAL_OPERATIONS } from './constants.js';
import FilterShell from './filter-shell.js';

function roundToFixed(value, precision) {
  var k = Math.pow(10, precision);
  return Math.round(value * k) / k;
}

function format(value, options) {
  var formatted = value.toString();

  switch (options.format) {
    case NUMERICAL_FORMATS.ACCOUNTING:
      {
        var abs = Math.abs(value);

        if (value < 0) {
          formatted = "($".concat(roundToFixed(abs, options.precision), ")");
          break;
        }

        formatted = "$".concat(roundToFixed(abs, options.precision));
        break;
      }

    case NUMERICAL_FORMATS.PERCENTAGE:
      {
        formatted = "".concat(roundToFixed(value, options.precision), "%");
        break;
      }

    case NUMERICAL_FORMATS.DEFAULT:
    default:
      formatted = roundToFixed(value, options.precision);
      break;
  }

  return formatted;
}

function validateInput(input) {
  return Boolean(parseFloat(input)) || input === '' || input === '-';
}

function NumericalFilter(props) {
  var _useStyletron = useStyletron(),
      _useStyletron2 = _slicedToArray(_useStyletron, 2),
      useCss = _useStyletron2[0],
      theme = _useStyletron2[1];

  var _React$useState = React.useState(false),
      _React$useState2 = _slicedToArray(_React$useState, 2),
      exclude = _React$useState2[0],
      setExclude = _React$useState2[1];

  var _React$useState3 = React.useState(0),
      _React$useState4 = _slicedToArray(_React$useState3, 2),
      comparator = _React$useState4[0],
      setComparator = _React$useState4[1];

  var _React$useState5 = React.useState(0),
      _React$useState6 = _slicedToArray(_React$useState5, 2),
      operator = _React$useState6[0],
      setOperator = _React$useState6[1];

  var _React$useState7 = React.useState(''),
      _React$useState8 = _slicedToArray(_React$useState7, 2),
      value = _React$useState8[0],
      setValue = _React$useState8[1];

  var isRange = comparator === 0;
  var min = React.useMemo(function () {
    return Math.min.apply(Math, _toConsumableArray(props.data));
  }, [props.data]);
  var max = React.useMemo(function () {
    return Math.max.apply(Math, _toConsumableArray(props.data));
  }, [props.data]);
  return React.createElement(FilterShell, {
    exclude: exclude,
    onExcludeChange: function onExcludeChange() {
      return setExclude(!exclude);
    },
    onApply: function onApply() {
      var operation = NUMERICAL_OPERATIONS.EQ;

      if (isRange) {
        switch (operator) {
          case 3:
            operation = NUMERICAL_OPERATIONS.GTE;
            break;

          case 2:
            operation = NUMERICAL_OPERATIONS.LTE;
            break;

          case 1:
            operation = NUMERICAL_OPERATIONS.GT;
            break;

          case 0:
          default:
            operation = NUMERICAL_OPERATIONS.LT;
            break;
        }
      }

      var parsed = parseFloat(value);
      props.setFilter({
        value: parsed,
        operation: operation,
        exclude: exclude
      }, "".concat(operation, " ").concat(parsed));
      props.close();
    }
  }, React.createElement(ButtonGroup, {
    mode: MODE.radio,
    selected: comparator,
    onClick: function onClick(_, index) {
      return setComparator(index);
    },
    overrides: {
      Root: {
        style: function style(_ref) {
          var $theme = _ref.$theme;
          return {
            marginBottom: $theme.sizing.scale500
          };
        }
      }
    }
  }, React.createElement(Button, {
    type: "button",
    overrides: {
      BaseButton: {
        style: {
          width: '100%'
        }
      }
    }
  }, "Range"), React.createElement(Button, {
    type: "button",
    overrides: {
      BaseButton: {
        style: {
          width: '100%'
        }
      }
    }
  }, "Single Value")), isRange && React.createElement(ButtonGroup, {
    mode: MODE.radio,
    selected: operator,
    onClick: function onClick(_, index) {
      return setOperator(index);
    },
    overrides: {
      Root: {
        style: function style(_ref2) {
          var $theme = _ref2.$theme;
          return {
            marginBottom: $theme.sizing.scale500
          };
        }
      }
    }
  }, React.createElement(Button, {
    type: "button",
    overrides: {
      BaseButton: {
        style: {
          width: '100%'
        }
      }
    }
  }, "<"), React.createElement(Button, {
    type: "button",
    overrides: {
      BaseButton: {
        style: {
          width: '100%'
        }
      }
    }
  }, ">"), React.createElement(Button, {
    type: "button",
    overrides: {
      BaseButton: {
        style: {
          width: '100%'
        }
      }
    }
  }, "\u2264"), React.createElement(Button, {
    type: "button",
    overrides: {
      BaseButton: {
        style: {
          width: '100%'
        }
      }
    }
  }, "\u2265")), React.createElement("div", {
    className: useCss({
      display: 'flex',
      justifyContent: 'space-between',
      marginLeft: theme.sizing.scale300,
      marginRight: theme.sizing.scale300
    })
  }, React.createElement(Paragraph4, null, format(min, props.options)), ' ', React.createElement(Paragraph4, null, format(max, props.options))), React.createElement("div", {
    className: useCss({
      display: 'flex',
      justifyContent: 'space-between'
    })
  }, React.createElement(Input, {
    overrides: {
      Root: {
        style: {
          width: '152px'
        }
      }
    },
    value: value,
    onChange: function onChange(event) {
      if (validateInput(event.target.value)) {
        setValue(event.target.value);
      }
    }
  })));
}

var NumericalCell = React.forwardRef(function (props, ref) {
  var _useStyletron3 = useStyletron(),
      _useStyletron4 = _slicedToArray(_useStyletron3, 2),
      useCss = _useStyletron4[0],
      theme = _useStyletron4[1];

  return React.createElement("div", {
    ref: ref,
    className: useCss(_objectSpread({}, theme.typography.font200, {
      color: props.highlight(props.value) ? theme.colors.negative : null,
      display: props.isMeasured ? 'inline-block' : null,
      fontFamily: "\"Lucida Console\", Monaco, monospace",
      paddingLeft: theme.sizing.scale600,
      paddingRight: theme.sizing.scale600,
      textAlign: 'right',
      width: props.isMeasured ? null : '100%'
    }))
  }, format(props.value, {
    format: props.format,
    precision: props.precision
  }));
});
NumericalCell.displayName = 'NumericalCell';
var defaultOptions = {
  title: '',
  sortable: true,
  filterable: true,
  format: NUMERICAL_FORMATS.DEFAULT,
  highlight: function highlight() {
    return false;
  },
  precision: 0
};

function NumericalColumn(options) {
  var normalizedOptions = _objectSpread({}, defaultOptions, {}, options);

  if (normalizedOptions.format !== NUMERICAL_FORMATS.DEFAULT && (options.precision === null || options.precision === undefined)) {
    normalizedOptions.precision = 2;
  }

  if (normalizedOptions.format === NUMERICAL_FORMATS.ACCOUNTING && (options.highlight === null || options.highlight === undefined)) {
    normalizedOptions.highlight = function (n) {
      return n < 0;
    };
  }

  return {
    kind: COLUMNS.NUMERICAL,
    title: normalizedOptions.title,
    sortable: normalizedOptions.sortable,
    filterable: normalizedOptions.filterable,
    renderCell: React.forwardRef(function (props, ref) {
      return React.createElement(NumericalCell, _extends({}, props, {
        ref: ref,
        format: normalizedOptions.format,
        highlight: normalizedOptions.highlight,
        precision: normalizedOptions.precision
      }));
    }),
    renderFilter: function RenderNumericalFilter(props) {
      return React.createElement(NumericalFilter, _extends({}, props, {
        options: normalizedOptions
      }));
    },
    buildFilter: function buildFilter(params) {
      return function (data) {
        var included = true;
        var left = roundToFixed(data, normalizedOptions.precision);
        var right = roundToFixed(params.value, normalizedOptions.precision);

        switch (params.operation) {
          case NUMERICAL_OPERATIONS.EQ:
            included = left === right;
            break;

          case NUMERICAL_OPERATIONS.GT:
            included = left > right;
            break;

          case NUMERICAL_OPERATIONS.GTE:
            included = left >= right;
            break;

          case NUMERICAL_OPERATIONS.LT:
            included = left < right;
            break;

          case NUMERICAL_OPERATIONS.LTE:
            included = left <= right;
            break;

          default:
            break;
        }

        return params.exclude ? !included : included;
      };
    },
    // initial sort should display largest values first
    sortFn: function sortFn(a, b) {
      return b - a;
    }
  };
}

export default NumericalColumn;