import * as tslib_1 from "tslib";
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { BaseComponent, autobind, css, getRTL, getId } from '../../Utilities';
import { ColumnActionsMode } from './DetailsList.types';
import { FocusZone, FocusZoneDirection } from '../../FocusZone';
import { Icon } from '../../Icon';
import { Layer } from '../../Layer';
import { GroupSpacer } from '../GroupedList/GroupSpacer';
import { CollapseAllVisibility } from '../../GroupedList';
import { DetailsRowCheck } from './DetailsRowCheck';
import * as checkStylesModule from './DetailsRowCheck.scss';
import { SELECTION_CHANGE } from '../../utilities/selection/interfaces';
import * as stylesImport from './DetailsHeader.scss';
var styles = stylesImport;
var checkStyles = checkStylesModule;
var MOUSEDOWN_PRIMARY_BUTTON = 0; // for mouse down event we are using ev.button property, 0 means left button
var MOUSEMOVE_PRIMARY_BUTTON = 1; // for mouse move event we are using ev.buttons property, 1 means left button
var INNER_PADDING = 16;
var ISPADDED_WIDTH = 24;
export var SelectAllVisibility;
(function (SelectAllVisibility) {
    SelectAllVisibility[SelectAllVisibility["none"] = 0] = "none";
    SelectAllVisibility[SelectAllVisibility["hidden"] = 1] = "hidden";
    SelectAllVisibility[SelectAllVisibility["visible"] = 2] = "visible";
})(SelectAllVisibility || (SelectAllVisibility = {}));
var DetailsHeader = /** @class */ (function (_super) {
    tslib_1.__extends(DetailsHeader, _super);
    function DetailsHeader(props) {
        var _this = _super.call(this, props) || this;
        _this.state = {
            columnResizeDetails: undefined,
            groupNestingDepth: _this.props.groupNestingDepth,
            isAllCollapsed: _this.props.isAllCollapsed
        };
        _this._onToggleCollapseAll = _this._onToggleCollapseAll.bind(_this);
        _this._onSelectAllClicked = _this._onSelectAllClicked.bind(_this);
        _this._id = getId('header');
        return _this;
    }
    DetailsHeader.prototype.componentDidMount = function () {
        var selection = this.props.selection;
        this._events.on(selection, SELECTION_CHANGE, this._onSelectionChanged);
        var rootElement = ReactDOM.findDOMNode(this.refs.root);
        // We need to use native on this to avoid MarqueeSelection from handling the event before us.
        this._events.on(rootElement, 'mousedown', this._onRootMouseDown);
        this._events.on(rootElement, 'keydown', this._onRootKeyDown);
    };
    DetailsHeader.prototype.componentWillReceiveProps = function (newProps) {
        var groupNestingDepth = this.state.groupNestingDepth;
        if (newProps.groupNestingDepth !== groupNestingDepth) {
            this.setState({ groupNestingDepth: newProps.groupNestingDepth });
        }
    };
    DetailsHeader.prototype.render = function () {
        var _this = this;
        var _a = this.props, columns = _a.columns, ariaLabel = _a.ariaLabel, ariaLabelForSelectAllCheckbox = _a.ariaLabelForSelectAllCheckbox, selectAllVisibility = _a.selectAllVisibility, ariaLabelForSelectionColumn = _a.ariaLabelForSelectionColumn;
        var _b = this.state, isAllSelected = _b.isAllSelected, columnResizeDetails = _b.columnResizeDetails, isSizing = _b.isSizing, groupNestingDepth = _b.groupNestingDepth, isAllCollapsed = _b.isAllCollapsed;
        var showCheckbox = selectAllVisibility !== SelectAllVisibility.none;
        var _c = this.props.onRenderColumnHeaderTooltip, onRenderColumnHeaderTooltip = _c === void 0 ? this._onRenderColumnHeaderTooltip : _c;
        return (React.createElement(FocusZone, { role: 'row', "aria-label": ariaLabel, className: css('ms-DetailsHeader', styles.root, isAllSelected && ('is-allSelected ' + styles.rootIsAllSelected), (selectAllVisibility === SelectAllVisibility.hidden) && ('is-selectAllHidden ' + styles.rootIsSelectAllHidden), (!!columnResizeDetails && isSizing) && 'is-resizingColumn'), ref: 'root', onMouseMove: this._onRootMouseMove, "data-automationid": 'DetailsHeader', direction: FocusZoneDirection.horizontal },
            showCheckbox ? ([
                React.createElement("div", { key: '__checkbox', className: css('ms-DetailsHeader-cell', 'ms-DetailsHeader-cellIsCheck', styles.cell, styles.cellIsCheck, checkStyles.owner, isAllSelected && checkStyles.isSelected), "aria-labelledby": this._id + "-check", onClick: this._onSelectAllClicked, "aria-colindex": 0, role: 'columnheader' }, onRenderColumnHeaderTooltip({
                    hostClassName: css(styles.checkTooltip),
                    id: this._id + "-checkTooltip",
                    setAriaDescribedBy: false,
                    content: ariaLabelForSelectAllCheckbox,
                    children: (React.createElement(DetailsRowCheck, { id: this._id + "-check", "aria-label": ariaLabelForSelectionColumn, "aria-describedby": this._id + "-checkTooltip", "data-is-focusable": true, isHeader: true, selected: isAllSelected, anySelected: false, canSelect: true }))
                }, this._onRenderColumnHeaderTooltip)),
                ariaLabelForSelectAllCheckbox && !this.props.onRenderColumnHeaderTooltip ? (React.createElement("label", { key: '__checkboxLabel', id: this._id + "-checkTooltip", className: styles.accessibleLabel }, ariaLabelForSelectAllCheckbox)) : null
            ]) : null,
            groupNestingDepth > 0 && this.props.collapseAllVisibility === CollapseAllVisibility.visible ? (React.createElement("div", { className: css('ms-DetailsHeader-cell', styles.cell), onClick: this._onToggleCollapseAll, "data-is-focusable": true },
                React.createElement(Icon, { className: css('ms-DetailsHeader-collapseButton', styles.collapseButton, isAllCollapsed && ('is-collapsed ' + styles.collapseButtonIsCollapsed)), iconName: 'ChevronDown' }))) : (null),
            GroupSpacer({ count: groupNestingDepth - 1 }),
            columns.map(function (column, columnIndex) {
                return ([
                    React.createElement("div", { key: column.key, role: 'columnheader', "aria-sort": column.isSorted ? (column.isSortedDescending ? 'descending' : 'ascending') : 'none', "aria-disabled": column.columnActionsMode === ColumnActionsMode.disabled, "aria-colindex": (showCheckbox ? 1 : 0) + columnIndex, className: css('ms-DetailsHeader-cell', styles.cell, column.headerClassName, (column.columnActionsMode !== ColumnActionsMode.disabled) && ('is-actionable ' + styles.cellIsActionable), !column.name && ('is-empty ' + styles.cellIsEmpty), (column.isSorted || column.isGrouped || column.isFiltered) && 'is-icon-visible', column.isPadded && styles.cellWrapperPadded), style: { width: column.calculatedWidth + INNER_PADDING + (column.isPadded ? ISPADDED_WIDTH : 0) }, "data-automationid": 'ColumnsHeaderColumn', "data-item-key": column.key }, onRenderColumnHeaderTooltip({
                        hostClassName: css(styles.cellTooltip),
                        id: _this._id + "-" + column.key + "-tooltip",
                        setAriaDescribedBy: false,
                        content: column.columnActionsMode !== ColumnActionsMode.disabled ? column.ariaLabel : '',
                        children: (React.createElement("span", { id: _this._id + "-" + column.key, "aria-label": column.isIconOnly ? column.name : undefined, "aria-labelledby": column.isIconOnly ? undefined : _this._id + "-" + column.key + "-name ", className: css('ms-DetailsHeader-cellTitle', styles.cellTitle), "data-is-focusable": column.columnActionsMode !== ColumnActionsMode.disabled, role: column.columnActionsMode !== ColumnActionsMode.disabled ? 'button' : undefined, "aria-describedby": _this._id + "-" + column.key + "-tooltip", onContextMenu: _this._onColumnContextMenu.bind(_this, column), onClick: _this._onColumnClick.bind(_this, column), "aria-haspopup": column.columnActionsMode === ColumnActionsMode.hasDropdown },
                            React.createElement("span", { id: _this._id + "-" + column.key + "-name", className: css('ms-DetailsHeader-cellName', styles.cellName, (_a = {},
                                    _a[styles.iconOnlyHeader] = column.isIconOnly,
                                    _a)) },
                                (column.iconName || column.iconClassName) && (React.createElement(Icon, { className: css(styles.nearIcon, column.iconClassName), iconName: column.iconName })),
                                !column.isIconOnly ? column.name : undefined),
                            column.isFiltered && (React.createElement(Icon, { className: styles.nearIcon, iconName: 'Filter' })),
                            column.isSorted && (React.createElement(Icon, { className: css(styles.nearIcon, styles.sortIcon), iconName: column.isSortedDescending ? 'SortDown' : 'SortUp' })),
                            column.isGrouped && (React.createElement(Icon, { className: styles.nearIcon, iconName: 'GroupedDescending' })),
                            column.columnActionsMode === ColumnActionsMode.hasDropdown && !column.isIconOnly && (React.createElement(Icon, { className: css('ms-DetailsHeader-filterChevron', styles.filterChevron), iconName: 'ChevronDown' }))))
                    }, _this._onRenderColumnHeaderTooltip)),
                    column.ariaLabel && !_this.props.onRenderColumnHeaderTooltip ? (React.createElement("label", { key: column.key + "_label", id: _this._id + "-" + column.key + "-tooltip", className: styles.accessibleLabel }, column.ariaLabel)) : null,
                    (column.isResizable) && _this._renderColumnSizer(columnIndex)
                ]);
                var _a;
            }),
            isSizing && (React.createElement(Layer, null,
                React.createElement("div", { className: css(isSizing && styles.sizingOverlay), onMouseMove: this._onSizerMouseMove, onMouseUp: this._onSizerMouseUp })))));
    };
    /** Set focus to the active thing in the focus area. */
    DetailsHeader.prototype.focus = function () {
        return this.refs.root.focus();
    };
    DetailsHeader.prototype._renderColumnSizer = function (columnIndex) {
        var columns = this.props.columns;
        var column = this.props.columns[columnIndex];
        var columnResizeDetails = this.state.columnResizeDetails;
        return (React.createElement("div", { key: column.key + "_sizer", "aria-hidden": true, role: 'button', "data-is-focusable": false, onClick: stopPropagation, "data-sizer-index": columnIndex, onBlur: this._onSizerBlur, className: css('ms-DetailsHeader-cellSizer', styles.cellSizer, columnIndex < columns.length - 1 ? styles.cellSizerStart : styles.cellSizerEnd, (_a = {},
                _a['is-resizing ' + styles.cellIsResizing] = columnResizeDetails && columnResizeDetails.columnIndex === columnIndex,
                _a)), onDoubleClick: this._onSizerDoubleClick.bind(this, columnIndex) }));
        var _a;
    };
    DetailsHeader.prototype._onRenderColumnHeaderTooltip = function (tooltipHostProps, defaultRender) {
        return (React.createElement("span", { className: tooltipHostProps.hostClassName }, tooltipHostProps.children));
    };
    /**
     * double click on the column sizer will auto ajust column width
     * to fit the longest content among current rendered rows.
     *
     * @private
     * @param {number} columnIndex (index of the column user double clicked)
     * @param {React.MouseEvent} ev (mouse double click event)
     */
    DetailsHeader.prototype._onSizerDoubleClick = function (columnIndex, ev) {
        var _a = this.props, onColumnAutoResized = _a.onColumnAutoResized, columns = _a.columns;
        if (onColumnAutoResized) {
            onColumnAutoResized(columns[columnIndex], columnIndex);
        }
    };
    /**
     * Called when the select all toggle is clicked.
     */
    DetailsHeader.prototype._onSelectAllClicked = function () {
        var selection = this.props.selection;
        selection.toggleAllSelected();
    };
    DetailsHeader.prototype._onRootMouseDown = function (ev) {
        var columnIndexAttr = ev.target.getAttribute('data-sizer-index');
        var columnIndex = Number(columnIndexAttr);
        var columns = this.props.columns;
        if (columnIndexAttr === null || ev.button !== MOUSEDOWN_PRIMARY_BUTTON) {
            // Ignore anything except the primary button.
            return;
        }
        this.setState({
            columnResizeDetails: {
                columnIndex: columnIndex,
                columnMinWidth: columns[columnIndex].calculatedWidth,
                originX: ev.clientX
            }
        });
        ev.preventDefault();
        ev.stopPropagation();
    };
    DetailsHeader.prototype._onRootMouseMove = function (ev) {
        var _a = this.state, columnResizeDetails = _a.columnResizeDetails, isSizing = _a.isSizing;
        if (columnResizeDetails && !isSizing && ev.clientX !== columnResizeDetails.originX) {
            this.setState({ isSizing: true });
        }
    };
    DetailsHeader.prototype._onRootKeyDown = function (ev) {
        var _a = this.state, columnResizeDetails = _a.columnResizeDetails, isSizing = _a.isSizing;
        var _b = this.props, columns = _b.columns, onColumnResized = _b.onColumnResized;
        var columnIndexAttr = ev.target.getAttribute('data-sizer-index');
        if (!columnIndexAttr || isSizing) {
            return;
        }
        var columnIndex = Number(columnIndexAttr);
        if (!columnResizeDetails) {
            if (ev.which === 13 /* enter */) {
                this.setState({
                    columnResizeDetails: {
                        columnIndex: columnIndex,
                        columnMinWidth: columns[columnIndex].calculatedWidth
                    }
                });
                ev.preventDefault();
                ev.stopPropagation();
            }
        }
        else {
            var increment = void 0;
            if (ev.which === 13 /* enter */) {
                this.setState({
                    columnResizeDetails: undefined
                });
                ev.preventDefault();
                ev.stopPropagation();
            }
            else if (ev.which === 37 /* left */) {
                increment = getRTL() ? 1 : -1;
            }
            else if (ev.which === 39 /* right */) {
                increment = getRTL() ? -1 : 1;
            }
            if (increment) {
                if (!ev.shiftKey) {
                    increment *= 10;
                }
                this.setState({
                    columnResizeDetails: tslib_1.__assign({}, columnResizeDetails, { columnMinWidth: columnResizeDetails.columnMinWidth + increment })
                });
                if (onColumnResized) {
                    onColumnResized(columns[columnIndex], columnResizeDetails.columnMinWidth + increment);
                }
                ev.preventDefault();
                ev.stopPropagation();
            }
        }
    };
    /**
     * mouse move event handler in the header
     * it will set isSizing state to true when user clicked on the sizer and move the mouse.
     *
     * @private
     * @param {React.MouseEvent} ev (mouse move event)
     */
    DetailsHeader.prototype._onSizerMouseMove = function (ev) {
        var 
        // use buttons property here since ev.button in some edge case is not upding well during the move.
        // but firefox doesn't support it, so we set the default value when it is not defined.
        buttons = ev.buttons;
        var _a = this.props, onColumnIsSizingChanged = _a.onColumnIsSizingChanged, onColumnResized = _a.onColumnResized, columns = _a.columns;
        var columnResizeDetails = this.state.columnResizeDetails;
        if (buttons !== undefined && buttons !== MOUSEMOVE_PRIMARY_BUTTON) {
            // cancel mouse down event and return early when the primary button is not pressed
            this._onSizerMouseUp(ev);
            return;
        }
        if (ev.clientX !== columnResizeDetails.originX) {
            if (onColumnIsSizingChanged) {
                onColumnIsSizingChanged(columns[columnResizeDetails.columnIndex], true);
            }
        }
        if (onColumnResized) {
            var movement = ev.clientX - columnResizeDetails.originX;
            if (getRTL()) {
                movement = -movement;
            }
            onColumnResized(columns[columnResizeDetails.columnIndex], columnResizeDetails.columnMinWidth + movement);
        }
    };
    DetailsHeader.prototype._onSizerBlur = function (ev) {
        var columnResizeDetails = this.state.columnResizeDetails;
        if (columnResizeDetails) {
            this.setState({
                columnResizeDetails: undefined,
                isSizing: false
            });
        }
    };
    /**
     * mouse up event handler in the header
     * clear the resize related state.
     * This is to ensure we can catch double click event
     *
     * @private
     * @param {React.MouseEvent} ev (mouse up event)
     */
    DetailsHeader.prototype._onSizerMouseUp = function (ev) {
        var _a = this.props, columns = _a.columns, onColumnIsSizingChanged = _a.onColumnIsSizingChanged;
        var columnResizeDetails = this.state.columnResizeDetails;
        this.setState({
            columnResizeDetails: undefined,
            isSizing: false
        });
        if (onColumnIsSizingChanged) {
            onColumnIsSizingChanged(columns[columnResizeDetails.columnIndex], false);
        }
    };
    DetailsHeader.prototype._onSelectionChanged = function () {
        var isAllSelected = this.props.selection.isAllSelected();
        if (this.state.isAllSelected !== isAllSelected) {
            this.setState({
                isAllSelected: isAllSelected
            });
        }
    };
    DetailsHeader.prototype._onColumnClick = function (column, ev) {
        var onColumnClick = this.props.onColumnClick;
        if (column.onColumnClick) {
            column.onColumnClick(ev, column);
        }
        if (onColumnClick) {
            onColumnClick(ev, column);
        }
    };
    DetailsHeader.prototype._onColumnContextMenu = function (column, ev) {
        var onColumnContextMenu = this.props.onColumnContextMenu;
        if (column.onColumnContextMenu) {
            column.onColumnContextMenu(column, ev);
            ev.preventDefault();
        }
        if (onColumnContextMenu) {
            onColumnContextMenu(column, ev);
            ev.preventDefault();
        }
    };
    DetailsHeader.prototype._onToggleCollapseAll = function () {
        var onToggleCollapseAll = this.props.onToggleCollapseAll;
        var newCollapsed = !this.state.isAllCollapsed;
        this.setState({
            isAllCollapsed: newCollapsed
        });
        if (onToggleCollapseAll) {
            onToggleCollapseAll(newCollapsed);
        }
    };
    DetailsHeader.defaultProps = {
        selectAllVisibility: SelectAllVisibility.visible,
        collapseAllVisibility: CollapseAllVisibility.visible
    };
    tslib_1.__decorate([
        autobind
    ], DetailsHeader.prototype, "_onRenderColumnHeaderTooltip", null);
    tslib_1.__decorate([
        autobind
    ], DetailsHeader.prototype, "_onSelectAllClicked", null);
    tslib_1.__decorate([
        autobind
    ], DetailsHeader.prototype, "_onRootMouseDown", null);
    tslib_1.__decorate([
        autobind
    ], DetailsHeader.prototype, "_onRootMouseMove", null);
    tslib_1.__decorate([
        autobind
    ], DetailsHeader.prototype, "_onRootKeyDown", null);
    tslib_1.__decorate([
        autobind
    ], DetailsHeader.prototype, "_onSizerMouseMove", null);
    tslib_1.__decorate([
        autobind
    ], DetailsHeader.prototype, "_onSizerBlur", null);
    tslib_1.__decorate([
        autobind
    ], DetailsHeader.prototype, "_onSizerMouseUp", null);
    return DetailsHeader;
}(BaseComponent));
export { DetailsHeader };
function stopPropagation(ev) {
    ev.stopPropagation();
}
//# sourceMappingURL=DetailsHeader.js.map