/*!
 * 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.array
    };

    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;
