import React, {PureComponent} from 'react';
import {isFunction} from 'lodash';
import PropTypes from 'prop-types';

import {AccordionItem} from './AccordionItem';

export class Accordion extends PureComponent {
    static Item = AccordionItem;

    static propTypes = {
        activeItem: PropTypes.string,
        lazy: PropTypes.bool,
        children: PropTypes.node.isRequired,
        onToggle: PropTypes.func,
        testAutomationId: PropTypes.string
    };

    static defaultProps = {
        activeItem: null,
        lazy: false,
        onToggle: null,
        testAutomationId: 'accordion'
    };

    state = {
        activeItem: this.props.activeItem
    };

    // TODO: redo with getDerivedStateFromProps
    componentWillReceiveProps(nextProps) {
        const {activeItem} = this.props;

        if (activeItem !== nextProps.activeItem) {
            this.setState({activeItem: nextProps.activeItem});
        }
    }

    createClickHandler = childOnToggle => activeItem => {
        const {onToggle} = this.props;

        if (isFunction(onToggle)) {
            onToggle(activeItem);
        } else {
            this.setState(state => ({
                activeItem: state.activeItem !== activeItem ? activeItem : null
            }));
        }

        if (isFunction(childOnToggle)) {
            childOnToggle(activeItem);
        }
    };

    prepareChildren() {
        const {children, lazy} = this.props;
        const {activeItem} = this.state;

        return React.Children.map(children, child => {
            if (!child) {
                return child;
            }

            if (child.type !== AccordionItem) {
                throw new Error('Accordion only supports children of type AccordionItem');
            }

            const {name, onToggle, testAutomationId} = child.props;

            if (!name) {
                throw new Error('AccordionItem in Accordion requires unique `name` prop');
            }

            return React.cloneElement(child, {
                lazy,
                isExpanded: name === activeItem,
                onToggle: this.createClickHandler(onToggle),
                testAutomationId:
                    testAutomationId === AccordionItem.defaultProps.testAutomationId
                        ? `${AccordionItem.defaultProps.testAutomationId}${name}`
                        : testAutomationId
            });
        });
    }

    render() {
        const {testAutomationId} = this.props;

        return <div data-test-automation-id={testAutomationId}>{this.prepareChildren()}</div>;
    }
}
