/*!
 * Copyright © 2016-2018 European Support Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */
import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import Collapse from 'react-bootstrap/lib/Collapse.js';

class NavigationSideBar extends React.Component {
    static propTypes = {
        activeItemId: PropTypes.string.isRequired,
        onSelect: PropTypes.func,
        onToggle: PropTypes.func,
        groups: PropTypes.array,
        disabled: PropTypes.bool
    };

    constructor(props) {
        super(props);
        this.state = {
            activeItemId: null
        };
        this.handleItemClicked = this.handleItemClicked.bind(this);
    }

    render() {
        let { groups, activeItemId, disabled = false } = this.props;

        return (
            <div
                className={`navigation-side-content ${
                    disabled ? 'disabled' : ''
                }`}>
                {groups.map(group => (
                    <NavigationMenu
                        menu={group}
                        activeItemId={activeItemId}
                        onNavigationItemClick={this.handleItemClicked}
                        key={'menu_' + group.id}
                    />
                ))}
            </div>
        );
    }

    handleItemClicked(event, item) {
        event.stopPropagation();
        if (this.props.onToggle) {
            this.props.onToggle(this.props.groups, item.id);
        }
        if (item.onSelect) {
            item.onSelect();
        }
        if (this.props.onSelect) {
            this.props.onSelect(item);
        }
    }
}

class NavigationMenu extends React.Component {
    static propTypes = {
        activeItemId: PropTypes.string.isRequired,
        onNavigationItemClick: PropTypes.func,
        menu: PropTypes.object
    };

    render() {
        const { menu, activeItemId, onNavigationItemClick } = this.props;
        return (
            <div className="navigation-group" key={menu.id}>
                <NavigationMenuHeader title={menu.name} />
                <NavigationMenuItems
                    items={menu.items}
                    activeItemId={activeItemId}
                    onNavigationItemClick={onNavigationItemClick}
                />
            </div>
        );
    }
}

function NavigationMenuHeader(props) {
    return (
        <div className="group-name" data-test-id="navbar-group-name">
            {props.title}
        </div>
    );
}

function getItemDataTestId(itemId) {
    return itemId.split('|')[0];
}
function NavigationMenuItems(props) {
    const { items, activeItemId, onNavigationItemClick } = props;
    return (
        <div className="navigation-group-items">
            {items &&
                items.map(item => (
                    <NavigationMenuItem
                        key={'menuItem_' + item.id}
                        item={item}
                        activeItemId={activeItemId}
                        onNavigationItemClick={onNavigationItemClick}
                    />
                ))}
        </div>
    );
}

function NavigationMenuItem(props) {
    const { onNavigationItemClick, item, activeItemId } = props;
    const isGroup = item.items && item.items.length > 0;
    return (
        <div
            className={classnames('navigation-group-item', {
                'selected-item': item.id === activeItemId
            })}
            key={'item_' + item.id}>
            <NavigationLink
                item={item}
                activeItemId={activeItemId}
                onClick={onNavigationItemClick}
            />
            {isGroup && (
                <Collapse
                    in={item.expanded}
                    data-test-id={
                        'navigation-group-' + getItemDataTestId(item.id)
                    }>
                    <div>
                        {item.items.map(subItem => (
                            <NavigationMenuItem
                                key={'menuItem_' + subItem.id}
                                item={subItem}
                                onNavigationItemClick={onNavigationItemClick}
                                activeItemId={activeItemId}
                            />
                        ))}
                    </div>
                </Collapse>
            )}
        </div>
    );
}

function NavigationLink(props) {
    const { item, activeItemId, onClick } = props;
    // todo should this be button
    return (
        <div
            key={'navAction_' + item.id}
            className={classnames('navigation-group-item-name', {
                selected: item.id === activeItemId,
                disabled: item.disabled,
                'bold-name': item.expanded,
                hidden: item.hidden
            })}
            onClick={event => onClick(event, item)}
            data-test-id={'navbar-group-item-' + getItemDataTestId(item.id)}>
            {item.name}
        </div>
    );
}

export default NavigationSideBar;
