"use strict";
/* @flow */
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
    result["default"] = mod;
    return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const React = __importStar(require("react"));
{
    DropdownProps;
}
from;
'./types';
const withStyles_1 = __importDefault(require("components/hoc/withStyles"));
const prop_types_1 = __importDefault(require("prop-types"));
const get_1 = __importDefault(require("lodash/get"));
const isEqual_1 = __importDefault(require("lodash/isEqual"));
const classnames_1 = __importDefault(require("classnames"));
const Collapse_1 = __importDefault(require("@material-ui/core/Collapse"));
const idx_1 = __importDefault(require("idx"));
const findIndex_1 = __importDefault(require("lodash/findIndex"));
const ErrorBoundary_1 = __importDefault(require("components/hoc/ErrorBoundary"));
const FieldLabel_1 = __importDefault(require("components/bosons/FieldLabel"));
const styles_1 = __importDefault(require("./styles"));
class Dropdown extends React.Component {
    constructor(props) {
        super(props);
        this._selectValueFromProps = () => {
            const { value, items, multiple } = this.props;
            this.selectValue(items, value, multiple);
        };
        this._handleOutSideClick = (e) => {
            if (this.container.contains(e.target)) {
                return;
            }
            // outside click
            this.close();
        };
        this.open = () => {
            if (this.props.disabled) {
                return;
            }
            this.setState({ isOpen: true });
        };
        this.close = () => {
            this.setState({ isOpen: false });
            if (this.props.onClose) {
                this.props.onClose();
            }
        };
        this._toggle = e => {
            if (this.state.isOpen) {
                this.close();
            }
            else {
                this.open();
            }
            if (this.props.onClick) {
                this.props.onClick(e);
            }
        };
        this.selectValue = (items = [], value, multiple) => {
            if (typeof value === 'undefined' || value === null) {
                return;
            }
            // if it is singular selection nextSelectedIndex is number and nextSelectedItem object
            // if it is multiple selection nextSelectedIndex is array of index and nextSelectedItem array of items
            let nextSelectedIndex;
            let nextSelectedItem;
            if (this.props.comparator) {
                let { index, item } = this.props.comparator(items.map(item => item.value), value);
                if (!multiple) {
                    // if single selection, index is number and item is object
                    nextSelectedIndex = index;
                    nextSelectedItem = item;
                }
                else {
                    // if multiple selection, index should be array of number and item should be array of object
                    nextSelectedIndex = [].concat(index);
                    nextSelectedItem = [].concat(item);
                }
            }
            else {
                // if comparator is not given then entire value object will be matched with given items
                if (!multiple) {
                    nextSelectedIndex = findIndex_1.default(items, { value });
                    nextSelectedItem = idx_1.default(items, _ => _[nextSelectedIndex]);
                }
                else {
                    nextSelectedIndex = [];
                    nextSelectedItem = [];
                    items.forEach((item, index) => {
                        if (value.indexOf(item.value) > -1) {
                            nextSelectedIndex.push(index);
                            nextSelectedItem.push(item);
                        }
                    });
                }
            }
            this.setState({ selectedIndex: nextSelectedIndex });
        };
        this.reset = () => {
            this.setState({ selectedIndex: -1 });
        };
        this._handleChange = (item, index) => {
            const { onChange, multiple } = this.props;
            let isSelected = true;
            if (!multiple) {
                this.setState({ selectedIndex: index });
            }
            else {
                const { selectedIndex } = this.state;
                const pos = [].concat(selectedIndex || []).indexOf(index);
                let newSelectedIndex = [];
                if (selectedIndex instanceof Array) {
                    newSelectedIndex = [...selectedIndex];
                }
                if (pos > -1) {
                    // index already exist so remove it from array
                    newSelectedIndex.splice(pos, 1);
                    isSelected = false;
                }
                else {
                    // index doesn't exist so add it
                    newSelectedIndex.push(index);
                }
                this.setState({ selectedIndex: newSelectedIndex });
            }
            if (onChange) {
                // isSelected is mainly used for multiple selection , whether item is checked or unchecked
                onChange(item, index, isSelected);
            }
            if (!multiple) {
                // if only single selection, then close dropdown on select
                this.close();
            }
        };
        this.state = {
            selectedIndex: props.selectedIndex,
            isOpen: false,
        };
    }
    componentDidMount() {
        if (typeof this.props.value !== 'undefined') {
            this._selectValueFromProps();
        }
        document.addEventListener('mousedown', this._handleOutSideClick, false);
    }
    componentWillUnmount() {
        document.removeEventListener('mousedown', this._handleOutSideClick, false);
    }
    componentDidUpdate(prevProps, prevState) {
        if (this.props.selectedIndex !== prevProps.selectedIndex) {
            this.setState({
                selectedIndex: this.props.selectedIndex,
            });
        }
        if (!isEqual_1.default(this.props.value, prevProps.value) ||
            !isEqual_1.default(this.props.items, prevProps.items)) {
            this._selectValueFromProps();
        }
    }
    _renderDropdown() {
        const { classes, label, placeholder, items, disabled, error, multiple, className, } = this.props;
        const { isOpen, selectedIndex } = this.state;
        let selectedLabel;
        if (!multiple) {
            selectedLabel = get_1.default(items, `${String(selectedIndex)}.label`);
        }
        else {
            if (selectedIndex instanceof Array) {
                const labels = []
                    .concat(selectedIndex || [])
                    .map(val => get_1.default(items, val + `.label`));
                selectedLabel = labels.join(', ');
            }
        }
        let selectedIcon;
        if (!multiple) {
            selectedIcon = React.createElement("div", { className: classnames_1.default(classes.circleIcon) });
        }
        else {
            selectedIcon = React.createElement("i", { className: classnames_1.default('fa fa-check', classes.tickIcon) });
        }
        return (React.createElement("div", { className: classnames_1.default(classes.root, { error: Boolean(error) }, className) },
            label && (React.createElement(FieldLabel_1.default, { label: label, classes: { label: classes.label } })),
            React.createElement("div", { className: classnames_1.default(classes.select, {
                    open: isOpen,
                    'is-value-selected': Boolean(selectedLabel),
                    disabled,
                }), onClick: this._toggle },
                Boolean(placeholder) &&
                    !selectedLabel && (React.createElement("div", { className: classnames_1.default(classes.placeholder) }, placeholder)),
                Boolean(selectedLabel) && (React.createElement("div", { className: classnames_1.default(classes.selectValue) }, selectedLabel)),
                React.createElement("div", { className: classnames_1.default(classes.arrowDown, { up: isOpen }) })),
            React.createElement(Collapse_1.default, { in: this.state.isOpen, timeout: "auto", unmountOnExit: true, classes: {
                    container: classnames_1.default(classes.selectMenu, { withoutLabel: !label }),
                } },
                React.createElement("div", { "data-test-id": "select-menu-wrapper" }, items.map((item, index) => {
                    let isItemSelected = false;
                    if (!multiple) {
                        isItemSelected = selectedIndex === index;
                    }
                    else {
                        isItemSelected = [].concat(selectedIndex).indexOf(index) > -1;
                    }
                    return (React.createElement("div", { "data-test-id": `item-${index}`, key: index, className: classnames_1.default(classes.menuItem), onClick: () => {
                            this._handleChange(item, index);
                        } },
                        React.createElement("div", { className: classnames_1.default(classes.menuItemText, {
                                selected: isItemSelected,
                            }) }, item.label),
                        isItemSelected && selectedIcon));
                })))));
    }
    render() {
        const { classes, error, showErrorMessage, id } = this.props;
        return (React.createElement(ErrorBoundary_1.default, null,
            React.createElement("div", { className: classnames_1.default(classes.component), id: id, ref: ref => (this.container = ref) },
                this._renderDropdown(),
                Boolean(error) &&
                    showErrorMessage && React.createElement("div", { className: classes.error }, error))));
    }
}
Dropdown.propTypes = {
    /** id **/
    id: prop_types_1.default.string,
    /** label **/
    label: prop_types_1.default.string,
    /** placeholder **/
    placeholder: prop_types_1.default.string,
    /** called when item selection change **/
    onChange: prop_types_1.default.func,
    /** called when dropdown selection change **/
    onClick: prop_types_1.default.func,
    /** called when dropdown menu close **/
    onClose: prop_types_1.default.func,
    /** disable dropdown **/
    disabled: prop_types_1.default.bool,
    /** selcted index  **/
    selectedIndex: prop_types_1.default.oneOfType([prop_types_1.default.number, prop_types_1.default.array]),
    /** items to display in dropdown  **/
    items: prop_types_1.default.arrayOf(prop_types_1.default.shape({
        label: prop_types_1.default.string.isRequired,
        value: prop_types_1.default.any.isRequired,
    })).isRequired,
    /** error message **/
    error: prop_types_1.default.string,
    /** should show error message (default : true) **/
    showErrorMessage: prop_types_1.default.bool,
    /** value of selected item **/
    value: prop_types_1.default.any,
    /** this is used to find selected value from given item  */
    comparator: prop_types_1.default.func,
    /** multiple: to allow multiple selection, default: false */
    multiple: prop_types_1.default.bool,
    /** classes  **/
    classes: prop_types_1.default.object,
    /** custom css  **/
    className: prop_types_1.default.string,
};
Dropdown.defaultProps = {
    placeholder: 'Select',
    showErrorMessage: true,
    id: '',
    onChange: () => { },
    onClick: () => { },
    onClose: () => { },
};
exports.default = withStyles_1.default(styles_1.default)(Dropdown);
//# sourceMappingURL=index.js.map