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); }

/*
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 { Checkbox, StyledLabel } from '../checkbox/index.js';
import Search from '../icon/search.js';
import { Input, SIZE as INPUT_SIZE } from '../input/index.js';
import { useStyletron, withStyle } from '../styles/index.js';
import { Label3 } from '../typography/index.js';
import CellShell from './cell-shell.js';
import { COLUMNS } from './constants.js';
import FilterShell from './filter-shell.js';
import { matchesQuery, splitByQuery, HighlightCellText } from './text-search.js';

function InputBefore() {
  const [useCss, theme] = useStyletron();
  return React.createElement("div", {
    className: useCss({
      display: 'flex',
      alignItems: 'center',
      paddingLeft: theme.sizing.scale500
    })
  }, React.createElement(Search, {
    size: "18px"
  }));
}

function FilterQuickControls(props) {
  const [useCss, theme] = useStyletron();
  return React.createElement(React.Fragment, null, React.createElement("button", {
    type: "button",
    className: useCss({ ...theme.typography.font100,
      borderTop: 0,
      borderRight: 0,
      borderBottom: 0,
      borderLeft: 0,
      cursor: 'pointer'
    }),
    onClick: props.onSelectAll
  }, "Select All"), React.createElement("span", {
    className: useCss({ ...theme.typography.font100
    })
  }, " | "), React.createElement("button", {
    type: "button",
    className: useCss({ ...theme.typography.font100,
      borderTop: 0,
      borderRight: 0,
      borderBottom: 0,
      borderLeft: 0,
      cursor: 'pointer'
    }),
    onClick: props.onClearSelection
  }, "Clear"));
}

const StyledHighlightLabel = withStyle(StyledLabel, props => {
  const style = {
    whiteSpace: 'pre',
    color: props.$isActive ? props.$theme.colors.black : props.$theme.colors.mono600
  };

  if (!props.$isFirst) {
    // $FlowFixMe
    style.paddingLeft = null;
  }

  return style;
});
StyledHighlightLabel.displayName = "StyledHighlightLabel";

function HighlightCheckboxLabel(props) {
  const {
    children,
    ...restProps
  } = props;

  if (!props.query) {
    return React.createElement(StyledLabel, restProps, children);
  }

  return splitByQuery(children, props.query).map((el, i) => {
    if (matchesQuery(el, props.query)) {
      return React.createElement(StyledHighlightLabel, _extends({}, restProps, {
        key: i,
        $isFirst: !i,
        $isActive: true
      }), el);
    }

    return React.createElement(StyledHighlightLabel, _extends({}, restProps, {
      key: i,
      $isFirst: !i
    }), el);
  });
}

export function CategoricalFilter(props) {
  const [useCss, theme] = useStyletron();
  const [selection, setSelection] = React.useState(props.filterParams ? props.filterParams.selection : new Set());
  const [exclude, setExclude] = React.useState(props.filterParams ? props.filterParams.exclude : false);
  const [query, setQuery] = React.useState('');
  const categories = React.useMemo(() => {
    return props.data.reduce((set, category) => set.add(category), new Set());
  }, [props.data]);
  const checkboxStyles = useCss({
    marginBottom: theme.sizing.scale200
  });
  const showQuery = Boolean(categories.size >= 10);
  const filteredCategories = Array.from(categories, c => c).filter(c => matchesQuery(c, query));
  return React.createElement(FilterShell, {
    exclude: exclude,
    onExcludeChange: () => setExclude(!exclude),
    onApply: () => {
      props.setFilter({
        description: Array.from(selection).join(', '),
        exclude,
        selection
      });
      props.close();
    }
  }, showQuery && React.createElement(Input, {
    size: INPUT_SIZE.compact,
    overrides: {
      Before: InputBefore
    },
    value: query,
    onChange: event => setQuery(event.target.value),
    clearable: true
  }), !query && React.createElement("div", {
    style: {
      marginTop: showQuery ? theme.sizing.scale600 : null
    }
  }, React.createElement(FilterQuickControls, {
    onSelectAll: () => {
      categories.forEach(c => selection.add(c));
      setSelection(new Set(selection));
    },
    onClearSelection: () => {
      setSelection(new Set());
    }
  })), React.createElement("div", {
    className: useCss({
      maxHeight: '256px',
      overflowY: 'auto',
      marginTop: theme.sizing.scale600
    })
  }, !filteredCategories.length && React.createElement(Label3, null, "No Categories Found"), Boolean(filteredCategories.length) && filteredCategories.map((category, i) => React.createElement("div", {
    className: checkboxStyles,
    key: i
  }, React.createElement(Checkbox, {
    checked: selection.has(category),
    onChange: () => {
      if (selection.has(category)) {
        selection.delete(category);
      } else {
        selection.add(category);
      }

      setSelection(new Set(selection));
    },
    overrides: {
      Label: {
        component: HighlightCheckboxLabel,
        props: {
          query
        }
      }
    }
  }, category)))));
}
const CategoricalCell = React.forwardRef((props, ref) => {
  return React.createElement(CellShell, {
    ref: ref,
    isMeasured: props.isMeasured,
    isSelected: props.isSelected,
    onSelect: props.onSelect
  }, props.textQuery ? React.createElement(HighlightCellText, {
    text: props.value,
    query: props.textQuery
  }) : props.value);
});
CategoricalCell.displayName = 'CategoricalCell';

function CategoricalColumn(options) {
  return {
    kind: COLUMNS.CATEGORICAL,
    buildFilter: function (params) {
      return function (data) {
        const included = params.selection.has(data);
        return params.exclude ? !included : included;
      };
    },
    filterable: options.filterable === undefined ? true : options.filterable,
    mapDataToValue: options.mapDataToValue,
    maxWidth: options.maxWidth,
    minWidth: options.minWidth,
    renderCell: CategoricalCell,
    renderFilter: CategoricalFilter,
    sortable: options.sortable === undefined ? true : options.sortable,
    sortFn: function (a, b) {
      return a.localeCompare(b);
    },
    title: options.title
  };
}

export default CategoricalColumn;