var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
import PropTypes from 'prop-types';
import { playMessage } from '../core/utils/playMessage';
import { KeyCodes } from '../utils/constants';
import React, { Component } from 'react';
import lang from '../lang/common/index-en_US';
export var keyboardSortableDesc = {
    get onFocusDesc() {
        return lang.DRAG_ITEM_ON_FOCUS_DESC;
    },
    get onGrabDescA() {
        return lang.DRAG_ITEM_ON_GRAB_DESC_A;
    },
    get onGrabDescB() {
        return lang.DRAG_ITEM_ON_GRAB_DESC_B;
    },
    get onDragDesc() {
        return lang.DRAG_ITEM_ON_DRAG_DESC;
    },
    get onDropDesc() {
        return lang.DRAG_ITEM_ON_DROP_DESC;
    },
    get onCancelDesc() {
        return lang.DRAG_ITEM_ON_CANCEL_DESC;
    }
};
export var keyboardSortableListItemDefaultProps = {
    onMove: null,
    onHover: null,
    get dragItemName() {
        return lang.DRAGGABLE_ITEM;
    }
};
export function keyboardSortableListItem(DecoratedComponent) {
    var _a;
    return _a = /** @class */ (function (_super) {
            __extends(KeyboardSortableListItem, _super);
            function KeyboardSortableListItem(props, context) {
                var _this = _super.call(this, props, context) || this;
                _this.onHandlerKeyUp = function (event) {
                    if (_this.state.isExistingFromReorderingMode) {
                        event.stopPropagation();
                    }
                };
                _this.state = {
                    originalIndexBeforeOrdering: -1,
                    isReorderingMode: false,
                    isExistingFromReorderingMode: false
                };
                _this.reorderActionHandler = _this.reorderActionHandler.bind(_this);
                _this.dragHandler = null;
                _this.prevDragHandler = null;
                return _this;
            }
            KeyboardSortableListItem.prototype.componentDidMount = function () {
                if (this.dragHandler) {
                    this.register();
                }
                document.addEventListener('click', this.handleOutsideClick.bind(this));
            };
            KeyboardSortableListItem.prototype.componentDidUpdate = function () {
                if (this.dragHandler) {
                    this.register();
                    if (this.state.isReorderingMode) {
                        this.dragHandler.focus();
                    }
                }
                else if (!this.dragHandler && !this.prevDragHandler) {
                    this.unregister();
                }
            };
            KeyboardSortableListItem.prototype.componentWillUnmount = function () {
                if (this.dragHandler) {
                    this.unregister();
                }
                document.removeEventListener('click', this.handleOutsideClick.bind(this));
            };
            KeyboardSortableListItem.prototype.register = function () {
                var _a = this.props, index = _a.index, dndId = _a.dndId;
                this.context.register(index, dndId);
                var currentKeyDownListener = this.dragHandler._keydownListener;
                if (currentKeyDownListener) {
                    this.dragHandler.removeEventListener('keydown', currentKeyDownListener);
                    this.dragHandler.removeEventListener('keyup', this.onHandlerKeyUp);
                }
                this.dragHandler.addEventListener('keydown', this.reorderActionHandler);
                this.dragHandler.addEventListener('keyup', this.onHandlerKeyUp);
                this.dragHandler._keydownListener = this.reorderActionHandler;
                this.dragHandler.setAttribute('role', 'option');
                this.dragHandler.setAttribute('aria-label', this.props.dragItemName + ", " + KeyboardSortableListItem.keyboardSortableDesc.onFocusDesc);
            };
            KeyboardSortableListItem.prototype.unregister = function () {
                var _a = this.props, index = _a.index, dndId = _a.dndId;
                this.context.unregister(index, dndId);
                if (this.prevDragHandler) {
                    this.prevDragHandler.removeEventListener('keydown', this.reorderActionHandler);
                    this.prevDragHandler._keydownListener = null;
                    this.prevDragHandler.removeAttribute('aria-label');
                }
            };
            KeyboardSortableListItem.prototype.createDragHandlerRef = function (node) {
                this.prevDragHandler = this.dragHandler;
                this.dragHandler = node;
            };
            KeyboardSortableListItem.prototype.cancelReorder = function () {
                var originalIndexBeforeOrdering = this.state.originalIndexBeforeOrdering;
                var _a = this.props, index = _a.index, onMove = _a.onMove, onHover = _a.onHover, dndId = _a.dndId;
                var isMovedDown = index > originalIndexBeforeOrdering;
                if (isMovedDown) {
                    var getPrevDropTarget = this.context.getPrevDropTarget;
                    while (index > originalIndexBeforeOrdering) {
                        var dropDndId = getPrevDropTarget(index).dndId;
                        if (dropDndId) {
                            reorder(dropDndId, index, isMovedDown);
                        }
                        index--;
                    }
                }
                else {
                    var getNextDropTarget = this.context.getNextDropTarget;
                    while (index < originalIndexBeforeOrdering) {
                        var dropDndId = getNextDropTarget(index).dndId;
                        if (dropDndId) {
                            reorder(dropDndId, index, isMovedDown);
                        }
                        index++;
                    }
                }
                this.announceCancelReorderItem();
                function reorder(dropDndId, index, isMovingDown) {
                    if (onMove) {
                        onMove(dropDndId, dndId);
                    }
                    else {
                        (function (index) {
                            setTimeout(function (_) {
                                onHover({ index: index }, { index: index + (isMovingDown ? -1 : 1) }, true);
                            });
                        })(index);
                    }
                }
            };
            KeyboardSortableListItem.prototype.reorderActionHandler = function (e) {
                var index = this.props.index;
                var _a = this.state, originalIndexBeforeOrdering = _a.originalIndexBeforeOrdering, isReorderingMode = _a.isReorderingMode;
                switch (e.keyCode) {
                    case KeyCodes.TAB:
                    case KeyCodes.ESC:
                        if (isReorderingMode) {
                            e.stopPropagation();
                            this.exitReorderingMode();
                        }
                        break;
                    case KeyCodes.SPACE:
                    case KeyCodes.ENTER:
                        e.preventDefault();
                        if (isReorderingMode) {
                            this.announceDropItem();
                        }
                        else {
                            this.announceGrabItem();
                        }
                        this.setState({
                            originalIndexBeforeOrdering: originalIndexBeforeOrdering < 0 ? index : -1,
                            isReorderingMode: !isReorderingMode,
                            isExistingFromReorderingMode: isReorderingMode
                        });
                        break;
                    case KeyCodes.ARROW_LEFT:
                    case KeyCodes.ARROW_UP:
                        if (isReorderingMode) {
                            e.preventDefault();
                            var _b = this.context.getPrevDropTarget(index), dndId = _b.dndId, targetIndex = _b.index;
                            if (dndId || dndId === 0) {
                                this.announceMovingItem(targetIndex);
                                this.reorder(dndId, false);
                            }
                        }
                        break;
                    case KeyCodes.ARROW_RIGHT:
                    case KeyCodes.ARROW_DOWN:
                        if (isReorderingMode) {
                            e.preventDefault();
                            var _c = this.context.getNextDropTarget(index), dndId = _c.dndId, targetIndex = _c.index;
                            if (dndId || dndId === 0) {
                                this.announceMovingItem(targetIndex);
                                this.reorder(dndId, true);
                            }
                        }
                }
            };
            /**
             * @param targetId moving destination. drop target's id
             * @param movingDown moving direction. direction moving up or moving down
             */
            KeyboardSortableListItem.prototype.reorder = function (targetId, movingDown) {
                var _a = this.props, index = _a.index, dndId = _a.dndId, onMove = _a.onMove, onHover = _a.onHover;
                if (onMove) {
                    onMove(dndId, targetId);
                }
                else {
                    onHover({ index: index }, { index: index + (movingDown ? 1 : -1) }, true);
                }
            };
            KeyboardSortableListItem.prototype.exitReorderingMode = function () {
                var index = this.props.index;
                if (this.state.isReorderingMode && index !== this.state.originalIndexBeforeOrdering) {
                    this.cancelReorder();
                }
                this.setState({
                    isReorderingMode: false,
                    originalIndexBeforeOrdering: -1,
                    isExistingFromReorderingMode: this.state.isReorderingMode
                });
            };
            KeyboardSortableListItem.prototype.handleOutsideClick = function () {
                if (document.activeElement !== this.dragHandler && this.state.isReorderingMode) {
                    this.exitReorderingMode();
                }
            };
            KeyboardSortableListItem.prototype.announceGrabItem = function () {
                var index = this.props.index;
                var dragItemName = this.props.dragItemName;
                var _a = KeyboardSortableListItem.keyboardSortableDesc, onGrabDescA = _a.onGrabDescA, onGrabDescB = _a.onGrabDescB;
                playMessage(dragItemName + ", " + onGrabDescA + ": " + (index + 1) + ". " + onGrabDescB);
            };
            KeyboardSortableListItem.prototype.announceMovingItem = function (currentIndex) {
                var dragItemName = this.props.dragItemName;
                var onDragDesc = KeyboardSortableListItem.keyboardSortableDesc.onDragDesc;
                playMessage(dragItemName + ", " + onDragDesc + ": " + (currentIndex + 1));
            };
            KeyboardSortableListItem.prototype.announceDropItem = function () {
                var index = this.props.index;
                var dragItemName = this.props.dragItemName;
                var onDropDesc = KeyboardSortableListItem.keyboardSortableDesc.onDropDesc;
                playMessage(dragItemName + ", " + onDropDesc + ": " + (index + 1));
            };
            KeyboardSortableListItem.prototype.announceCancelReorderItem = function () {
                var dragItemName = this.props.dragItemName;
                var onCancelDesc = KeyboardSortableListItem.keyboardSortableDesc.onCancelDesc;
                playMessage(dragItemName + ", " + onCancelDesc);
            };
            KeyboardSortableListItem.prototype.render = function () {
                return (React.createElement(DecoratedComponent, __assign({ isKeyboardDragging: this.state.isReorderingMode, connectDragHandler: this.createDragHandlerRef.bind(this) }, this.props)));
            };
            return KeyboardSortableListItem;
        }(Component)),
        _a.keyboardSortableDesc = keyboardSortableDesc,
        _a.contextTypes = {
            register: PropTypes.func.isRequired,
            unregister: PropTypes.func.isRequired,
            getPrevDropTarget: PropTypes.func.isRequired,
            getNextDropTarget: PropTypes.func.isRequired
        },
        _a.propTypes = {
            index: PropTypes.number.isRequired,
            dndId: PropTypes.any.isRequired,
            onMove: checkReorderCallbackProp,
            onHover: checkReorderCallbackProp,
            dragItemName: PropTypes.string.isRequired
        },
        _a.defaultProps = keyboardSortableListItemDefaultProps,
        _a;
}
function checkReorderCallbackProp(props, propName, componentName) {
    var rest = [];
    for (var _i = 3; _i < arguments.length; _i++) {
        rest[_i - 3] = arguments[_i];
    }
    if (!props.onMove && !props.onHover) {
        return new Error("One of props 'onHide' or 'onHover' need to be specified in " + componentName);
    }
    if (props[propName]) {
        return PropTypes.func(props, propName, componentName, rest[0], rest[1]);
    }
    return null;
}
//# sourceMappingURL=keyboardSortableListItem.js.map