import React, { useCallback, useEffect, useMemo, useState } from 'react';
import clsx from 'clsx';
import { ChevronDownIcon } from '@fluentui/react-icons';
import { FormControlLabel, FormGroup, makeStyles } from '@material-ui/core';
import { isEmpty } from 'lodash-es';
import { FluentCheckbox } from '../../inputs/checkbox/FluentCheckbox';
import { FluentIconButton } from '../../inputs/buttons/FluentIconButton';
import { getChildrenObjectsWithNoChildren } from '../utilities/MapUtilities';
const useStyles = makeStyles((theme) => ({
    expand: {
        transform: 'rotate(0deg)',
        transition: theme.transitions.create('transform', {
            duration: theme.transitions.duration.shortest
        })
    },
    expandOpen: {
        transform: 'rotate(180deg)'
    },
    iconButtonWrapper: {
        borderRadius: 2,
        margin: 'auto 0px'
    },
    expandedList: {
        marginLeft: theme.spacing(4),
        display: 'flex',
        flexDirection: 'column'
    },
    checkboxGroup: {
        display: 'flex',
        justifyContent: 'space-between'
    }
}));
export const CheckboxGroup = (props) => {
    const { title, options, onChange, defaultExpandedListState = true, values, valueKey } = props;
    const [checkedItems, setCheckedItems] = useState({});
    const [checkedParent, setCheckedParent] = useState(false);
    const [expanded, setExpanded] = useState(defaultExpandedListState);
    const [parentIndeterminate, setParentIndeterminate] = useState(false);
    const classes = useStyles();
    useEffect(() => {
        let preCheckedItems = {};
        options === null || options === void 0 ? void 0 : options.forEach((option) => {
            var _a;
            if (!!!(option === null || option === void 0 ? void 0 : option.options) || ((_a = option === null || option === void 0 ? void 0 : option.options) === null || _a === void 0 ? void 0 : _a.length) === 0) {
                preCheckedItems[option.value] = values === null || values === void 0 ? void 0 : values.includes(option.value);
            }
        });
        setCheckedItems(preCheckedItems);
    }, [options, values]);
    //get a list of child values
    const childrenValues = useMemo(() => {
        return getChildrenObjectsWithNoChildren(options !== null && options !== void 0 ? options : [], 'value');
    }, [options]);
    useEffect(() => {
        var _a, _b;
        var _c;
        const checkedAll = isEmpty(checkedItems)
            ? (_c = ((childrenValues === null || childrenValues === void 0 ? void 0 : childrenValues.length) > 0 &&
                (childrenValues === null || childrenValues === void 0 ? void 0 : childrenValues.every((val) => values.includes(val))))) !== null && _c !== void 0 ? _c : false : (_a = Object.values(checkedItems)) === null || _a === void 0 ? void 0 : _a.every((checked) => checked);
        setCheckedParent(checkedAll);
        setParentIndeterminate(!checkedAll &&
            (isEmpty(checkedItems)
                ? childrenValues === null || childrenValues === void 0 ? void 0 : childrenValues.some((val) => values.includes(val))
                : (_b = Object.values(checkedItems)) === null || _b === void 0 ? void 0 : _b.some((checked) => checked)));
    }, [checkedItems, childrenValues, title, values]);
    const handleOnClickChildCheckboxOnChange = useCallback((event) => {
        var _a, _b;
        setCheckedItems((preVal) => {
            var _a, _b;
            return (Object.assign(Object.assign({}, preVal), { [(_a = event === null || event === void 0 ? void 0 : event.target) === null || _a === void 0 ? void 0 : _a.name]: (_b = event === null || event === void 0 ? void 0 : event.target) === null || _b === void 0 ? void 0 : _b.checked }));
        });
        if (!((_a = event === null || event === void 0 ? void 0 : event.target) === null || _a === void 0 ? void 0 : _a.checked)) {
            onChange(values === null || values === void 0 ? void 0 : values.filter((val) => {
                var _a;
                return val !== ((_a = event === null || event === void 0 ? void 0 : event.target) === null || _a === void 0 ? void 0 : _a.name);
            }));
        }
        else {
            onChange([...values, (_b = event === null || event === void 0 ? void 0 : event.target) === null || _b === void 0 ? void 0 : _b.name]);
        }
    }, [onChange, values]);
    const handleParentCheckboxOnChange = useCallback((event) => {
        var _a, _b;
        setCheckedParent((_a = event === null || event === void 0 ? void 0 : event.target) === null || _a === void 0 ? void 0 : _a.checked);
        if (!((_b = event === null || event === void 0 ? void 0 : event.target) === null || _b === void 0 ? void 0 : _b.checked)) {
            setCheckedItems({});
            onChange(values === null || values === void 0 ? void 0 : values.filter((val) => {
                return !(childrenValues === null || childrenValues === void 0 ? void 0 : childrenValues.includes(val));
            }));
        }
        let newItemToAdd = [];
        childrenValues.forEach((option) => {
            var _a;
            if (((_a = event === null || event === void 0 ? void 0 : event.target) === null || _a === void 0 ? void 0 : _a.checked) && option && !(values === null || values === void 0 ? void 0 : values.includes(option))) {
                newItemToAdd.push(option);
            }
        });
        if (newItemToAdd.length > 0) {
            onChange([...values, ...newItemToAdd]);
        }
        setExpanded(true);
        setParentIndeterminate(false);
    }, [childrenValues, onChange, values]);
    const childrenList = useMemo(() => {
        if ((options === null || options === void 0 ? void 0 : options.length) > 0) {
            return options === null || options === void 0 ? void 0 : options.map((option) => {
                var _a;
                if (((_a = option === null || option === void 0 ? void 0 : option.options) === null || _a === void 0 ? void 0 : _a.length) > 0) {
                    return (React.createElement(CheckboxGroup, { key: option === null || option === void 0 ? void 0 : option.value, title: option === null || option === void 0 ? void 0 : option.title, options: option === null || option === void 0 ? void 0 : option.options, values: values, valueKey: option === null || option === void 0 ? void 0 : option.value, onChange: onChange }));
                }
                return (React.createElement(FormControlLabel, { label: option === null || option === void 0 ? void 0 : option.title, control: React.createElement(FluentCheckbox, { checked: checkedItems[option === null || option === void 0 ? void 0 : option.value] || false, onChange: handleOnClickChildCheckboxOnChange }), name: option === null || option === void 0 ? void 0 : option.value }));
            });
        }
        return [];
    }, [
        checkedItems,
        handleOnClickChildCheckboxOnChange,
        onChange,
        options,
        values
    ]);
    return (React.createElement(FormGroup, null, (options === null || options === void 0 ? void 0 : options.length) > 0 ? (React.createElement("div", { className: classes.checkboxGroup }, React.createElement(FormControlLabel, { label: title, control: React.createElement(FluentCheckbox, { checked: checkedParent, indeterminate: parentIndeterminate, onChange: handleParentCheckboxOnChange }) }), React.createElement(FluentIconButton, { className: clsx(classes.expand, {
            [classes.expandOpen]: expanded
        }, classes.iconButtonWrapper), onClick: () => setExpanded(!expanded), icon: ChevronDownIcon }))) : (React.createElement("div", null, React.createElement(FormControlLabel, { label: title, control: React.createElement(FluentCheckbox, { checked: checkedItems[valueKey] || false, onChange: handleOnClickChildCheckboxOnChange, name: valueKey }) }))), expanded && (options === null || options === void 0 ? void 0 : options.length) > 0 && (React.createElement("div", { className: classes.expandedList }, childrenList))));
};
//# sourceMappingURL=CheckboxGroup.js.map