import * as React from 'react';
import {isFunction, isUndefined} from 'lodash';

import {AccordionItem} from './AccordionItem';

type AccordionProps = {
    activeItem: string;
    lazy: boolean;
    onToggle: Function;
    testAutomationId: string;
};

export class Accordion extends React.PureComponent<AccordionProps, any> {
    static Item = AccordionItem;

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

    static getDerivedStateFromProps(props, state) {
        if (props.activeItem === state.activeItem) {
            return null;
        }

        if (isUndefined(props.activeItem)) {
            return null;
        }

        let activeItem = state.activeItem;

        if (props.activeItem !== state.prevActiveItem) {
            activeItem = props.activeItem;
        }

        return {
            prevActiveItem: props.activeItem,
            activeItem
        };
    }

    state = {
        prevActiveItem: this.props.activeItem,
        activeItem: this.props.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);
        }
    };

    renderChild = (child: React.ReactElement) => {
        const {lazy} = this.props;
        const {activeItem} = this.state;

        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
        });
    };

    renderChildren() {
        const {children} = this.props;

        return React.Children.map(children, this.renderChild);
    }

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

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