import classNames from "classnames";
import React, { useCallback, useEffect, useRef } from "react";

import classes from "./classes.module.scss";
import DropdownOption, { IOption } from "./DropdownOption";

type IProps = {
	options: IOption[];
	selectedOptions: IOption[];
	children: React.ReactNode;
	openable: {
		isOpen: boolean;
		open: () => void;
		close: () => void;
		toggle: () => void;
	};
	onSelect?: (newOption: IOption, options: IOption[]) => void;
};
export default function DropdownMenu(props: IProps) {
	const { children, options, onSelect, openable, selectedOptions } = props;
	const ref = useRef<HTMLDivElement>(null);

	const handleSelect = useCallback(
		(option: IOption) => {
			const newOptions = selectedOptions.some((selectedOption) => selectedOption.id === option.id)
				? selectedOptions
				: [...selectedOptions, option];

			onSelect?.(option, newOptions);
			openable.close();
		},
		[onSelect, openable, selectedOptions],
	);

	const handleClickOutside = useCallback(
		(event: MouseEvent) => {
			if (ref.current && !ref.current.contains(event.target as Node)) {
				openable.close();
			}
		},
		[openable],
	);

	useEffect(() => {
		document.addEventListener("mousedown", handleClickOutside);
		return () => document.removeEventListener("mousedown", handleClickOutside);
	}, [handleClickOutside]);

	return (
		<div className={classNames([classes["root"], openable.isOpen && classes["open"]])} ref={ref}>
			{children}
			<div className={classes["content"]}>
				{options.map((option) => {
					return <DropdownOption key={option.id} option={option} onClick={handleSelect} isActive={isActive(option)} />;
				})}
			</div>
		</div>
	);

	function isActive(option: IOption): boolean {
		return selectedOptions.some((selectedOption) => selectedOption.id === option.id);
	}
}
