import classNames from "classnames";
import React from "react";
import ReactSelect, { ActionMeta, MultiValue, Options, PropsValue } from "react-select";

import { IOption } from "../Select";
import Typography, { ITypo } from "../Typography";
import classes from "./classes.module.scss";
import { styles } from "./styles";

type IProps = {
	options: IOption[];
	label?: string | JSX.Element;
	placeholder?: string;
	onChange?: (newValue: MultiValue<IOption>, actionMeta: ActionMeta<IOption>) => void;
	defaultValue?: PropsValue<IOption>;
	value?: PropsValue<IOption>;
	isMulti?: boolean;
	shouldCloseMenuOnSelect: boolean;
	isOptionDisabled?: (option: IOption, selectValue: Options<IOption>) => boolean;
};
type IState = {
	isFocused: boolean;
	selectedOptions: MultiValue<IOption>;
};

export default class MultiSelect extends React.Component<IProps, IState> {
	public static defaultProps: Partial<IProps> = {
		placeholder: "Sélectionner une option...",
		shouldCloseMenuOnSelect: false,
	};

	constructor(props: IProps) {
		super(props);
		this.state = {
			isFocused: false,
			selectedOptions: [],
		};
		this.onChange = this.onChange.bind(this);
		this.onEmptyResearch = this.onEmptyResearch.bind(this);
		this.onFocus = this.onFocus.bind(this);
		this.onBlur = this.onBlur.bind(this);
	}
	public override render(): JSX.Element {
		return (
			<div className={classes["root"]}>
				<div className={classNames(classes["label-container"], this.state.selectedOptions.length >= 1 && classes["active"])}>
					{this.props.label && <div className={classes["label"]}>{this.props.label}</div>}
					{this.props.placeholder && (
						<div
							className={classes["placeholder"]}
							data-selected={(this.state.isFocused || this.state.selectedOptions.length >= 1).toString()}>
							<Typography typo={ITypo.NAV_INPUT_16}>{this.props.placeholder}</Typography>
						</div>
					)}
					<div className={classes["input-container"]}>
						<ReactSelect
							placeholder={""}
							options={this.props.options}
							styles={styles}
							onChange={this.onChange}
							value={this.props.value}
							defaultValue={this.props.defaultValue}
							closeMenuOnSelect={this.props.shouldCloseMenuOnSelect}
							isMulti
							isOptionDisabled={this.props.isOptionDisabled}
							noOptionsMessage={this.onEmptyResearch}
							onFocus={this.onFocus}
							onBlur={this.onBlur}
							classNamePrefix="react-select"
						/>
					</div>
				</div>
			</div>
		);
	}

	public override componentDidMount(): void {
		if (this.props.defaultValue) {
			// If default value contains multiple IOptions
			if (Array.isArray(this.props.defaultValue)) {
				this.setState({ selectedOptions: this.props.defaultValue });
			}

			// If default value is a single IOption
			if ("label" in this.props.defaultValue) {
				this.setState({ selectedOptions: [this.props.defaultValue] });
			}
		}
	}

	private onFocus() {
		this.setState({ isFocused: true });
	}

	private onBlur() {
		this.setState({ isFocused: false });
	}

	private onChange(newValue: MultiValue<IOption>, actionMeta: ActionMeta<IOption>) {
		this.props.onChange && this.props.onChange(newValue, actionMeta);
		this.setState({
			selectedOptions: newValue,
		});
	}

	private onEmptyResearch() {
		if (this.state.selectedOptions.length === this.props.options.length) {
			return null;
		}
		return "Aucune option trouvée";
	}
}
