import _ from 'lodash';
import PropTypes from 'prop-types';
import React from 'react';
import classSet from 'classnames';
import { Checkbox } from 'lego-on-react';
import Popup from 'react-bem-components/lib/Popup';
import AuthStore from 'stores/Auth';

import Unit from 'ui/Unit';
import Link from 'ui/Link';
import UserHoverCard from 'components/User/HoverCard';
import Counter from './Counter';

import './index.css';
import './types.css';

const ITEM_TYPES_WITH_COUNTER = ['department'];

const hoverPopupIndex = {};

const SectionListItem = React.createClass({

    getInitialState() {
        return {};
    },

    componentDidMount() {
        this._anchorPopup();
        this._key = _.uniqueId();
    },

    componentDidUpdate() {
        this._anchorPopup();
        if (this.refs.hoverPopup) {
            this.refs.hoverPopup.block.domElem.css('animation', 'none');
        }
    },

    _anchorPopup() {
        const { hoverPopup, listItem } = this.refs;

        if (hoverPopup && listItem) {
            hoverPopup.setAnchor(_.get(listItem, 'refs.item'));
        }
    },

    _handleClick(event) {
        const { editable, checked, item, onClick, onChange } = this.props;

        event.preventDefault();

        if (editable && onChange) {
            onChange(item, !checked);
        } else if (onClick) {
            onClick(item);
        }
    },

    _handleMouseEnter() {
        this._closeOtherOpenHoverCards();
        this._holdOpenHoverCard() || this._openHoverCard();
    },

    _handleMouseLeave() {
        this._closeHoverCard();
    },

    _handleHoverCardMouseEnter() {
        this._holdOpenHoverCard();
    },

    _handleHoverCardMouseLeave() {
        this._closeHoverCard();
    },

    _holdOpenHoverCard() {
        if (hoverPopupIndex[this._key]) {
            clearTimeout(hoverPopupIndex[this._key].timeout);
            delete hoverPopupIndex[this._key];

            return true;
        }

        return false;
    },

    _openHoverCard() {
        if (this.refs.hoverPopup) {
            this.refs.hoverPopup.block.setMod('visible', true);
            this.setState({ hovered: true });
        }
    },

    _closeHoverCard() {
        if (this.refs.hoverPopup) {
            const closePopup = () => {
                this.refs.hoverPopup.block.setMod('visible', false);
                delete hoverPopupIndex[this._key];
                this.setState({ hovered: false });
            };

            hoverPopupIndex[this._key] = {
                timeout: setTimeout(closePopup, 200),
                close: closePopup,
            };
        }
    },

    _closeOtherOpenHoverCards() {
        const ownKey = this._key;

        _.forEach(hoverPopupIndex, (popup, key) => {
            if (key !== ownKey) {
                clearTimeout(popup.timeout);
                popup.close();
                delete hoverPopupIndex[key];
            }
        });
    },

    _getHoverCardPopup(hoverCard) {
        if (!hoverCard) {
            return null;
        }

        return (
            <Popup
                ref="hoverPopup"
                closable
                directions={[
                    'right-center', 'right-top', 'right-bottom',
                    'left-center', 'left-top', 'left-bottom',
                    'top-right',
                ]}
                target="anchor"
            >
                <div
                    className="section-list-item__hover-card"
                    onMouseEnter={this._handleHoverCardMouseEnter}
                    onMouseLeave={this._handleHoverCardMouseLeave}
                >
                    {hoverCard}
                </div>
            </Popup>
        );
    },

    render() {
        let { avatar, description } = this.props;
        const { item, badge, hoverCard } = this.props;
        const component = { badge, hoverCard };

        if (avatar === undefined && item.getAvatar) {
            avatar = item.getAvatar();
        }

        if (description === undefined && item.getDescription) {
            description = item.getDescription();
        }

        const className = classSet({
            'section-list-item': true,
            'section-list-item_editable': this.props.editable,
            'section-list-item_selected': this.props.selected,
            'section-list-item_hovered': this.state.hovered,
        });

        if (this.props.editable) {
            component.control = (
                <div className="section-list-item__control">
                    <Checkbox size="s" theme="normal" checked={this.props.checked} />
                </div>
            );
        }

        const type = item.getType();
        const name = item.getAlphabeticalName ? item.getAlphabeticalName() : item.getName();

        if (!component.badge && ITEM_TYPES_WITH_COUNTER.indexOf(type) !== -1) {
            component.badge = <Counter item={item} />;
        }

        if (!component.hoverCard && type === 'user' && AuthStore.getViewMode() === 'staff') {
            component.hoverCard = <UserHoverCard user={item} />;
        }

        if (component.hoverCard) {
            component.hoverPopup = this._getHoverCardPopup(component.hoverCard);
        }

        return (
            <Link
                ref="listItem"
                role="link"
                tabIndex="0"
                className={className}
                onClick={this._handleClick}
                onMouseEnter={this._handleMouseEnter}
                onMouseLeave={this._handleMouseLeave}
                data-id={item.getId()}
                data-type={type}
            >
                {component.control}
                <Unit
                    avatar={avatar}
                    title={name}
                    description={description}
                    role={item.getRole ? item.getRole() : null}
                    type={type}
                />
                {component.badge}
                {component.hoverPopup}
            </Link>
        );
    },

});

SectionListItem.propTypes = {
    item: PropTypes.object.isRequired,
    avatar: PropTypes.string,
    description: PropTypes.string,
    badge: PropTypes.object,
    selected: PropTypes.bool,
    editable: PropTypes.bool,
    checked: PropTypes.bool,
    onClick: PropTypes.func,
    onChange: PropTypes.func,
};

SectionListItem.defaultProps = {
    selected: false,
    editable: false,
    checked: false,
};

export default SectionListItem;
