/*
    Парус 8 - Панели мониторинга - УДП - Доски задач
    Компонент: Кастомное поле ввода
*/

//---------------------
//Подключение библиотек
//---------------------

import React, { useEffect, useState } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { FormControl, InputLabel, Input, InputAdornment, IconButton, Icon, FormHelperText, Select, MenuItem, Typography } from "@mui/material"; //Интерфейсные компоненты
import { COMMON_STYLES } from "../styles"; //Общие стили

//---------
//Константы
//---------

//Стили
const STYLES = {
    HELPER_TEXT: { color: "red" },
    SELECT_MENU: width => {
        return { ...COMMON_STYLES.SCROLL, width: width ? width + 24 : null };
    }
};

//---------------
//Тело компонента
//---------------

//Кастомное поле ввода
const CustomInputField = ({
    elementCode,
    elementValue,
    labelText,
    onChange,
    required = false,
    items = null,
    emptyItem = null,
    dictionary,
    menuItemRender,
    ...other
}) => {
    //Значение элемента
    const [value, setValue] = useState(elementValue);

    //Состояние элемента HTML (для оптимизации ширины MenuItems)
    const [anchorEl, setAnchorEl] = useState();

    //При открытии меню заливки событий
    const handleMenuOpen = e => {
        //Устанавливаем элемент меню
        setAnchorEl(e.target);
    };

    //При получении нового значения из вне
    useEffect(() => {
        setValue(elementValue);
    }, [elementValue]);

    //Изменение значения элемента
    const handleChange = e => {
        setValue(e.target.value);
        if (onChange) onChange(e.target.name, e.target.value);
    };

    //Выбор значения из словаря
    const handleDictionaryClick = () => {
        dictionary ? dictionary(res => (res ? handleChange({ target: { name: elementCode, value: res } }) : null)) : null;
    };

    //Генерация поля с выбором из словаря Парус
    const renderInput = validationError => {
        //Генерация содержимого
        return (
            <Input
                error={validationError}
                id={elementCode}
                name={elementCode}
                value={value}
                endAdornment={
                    dictionary ? (
                        <InputAdornment position="end">
                            <IconButton aria-label={`${elementCode} select`} onClick={handleDictionaryClick} edge="end">
                                <Icon>list</Icon>
                            </IconButton>
                        </InputAdornment>
                    ) : null
                }
                aria-describedby={`${elementCode}-helper-text`}
                label={labelText}
                onChange={handleChange}
                {...other}
            />
        );
    };

    //Генерация поля с выпадающим списком
    const renderSelect = (items, anchorEl, handleMenuOpen, validationError) => {
        //Формируем общий список элементов меню
        const menuItems = emptyItem ? [emptyItem, ...items] : [...items];
        //Генерация содержимого
        return (
            <Select
                error={validationError}
                id={elementCode}
                name={elementCode}
                //!!!Пересмотреть момент. При изменении типа происходит ререндер со старым значением учетного документа:
                //1. Изменяется тип
                //2. Очищается items (список учетных документов)
                //3. Рисуется компонент со старым value и пустым items, из-за чего ошибка "You have provided an out-of-range value"
                //4. Вызывается useEffect, меняется значение value на новое (пустое значение)
                value={value}
                aria-describedby={`${elementCode}-helper-text`}
                label={labelText}
                MenuProps={{ slotProps: { paper: { sx: STYLES.SELECT_MENU(anchorEl?.offsetWidth) } } }}
                onChange={handleChange}
                onOpen={handleMenuOpen}
                {...other}
            >
                {menuItems
                    ? menuItems.map((item, index) => {
                          let customRender = null;
                          if (menuItemRender) customRender = menuItemRender({ item: item, key: item?.key ?? index }) || null;
                          return customRender ? (
                              customRender
                          ) : (
                              <MenuItem key={item?.key ?? index} value={item.id}>
                                  <Typography variant="inherit" noWrap title={item.caption} component="div">
                                      {item.caption}
                                  </Typography>
                              </MenuItem>
                          );
                      })
                    : null}
            </Select>
        );
    };

    //Признак ошибки валидации
    const validationError = !value && required ? true : false;

    //Генерация содержимого
    return (
        <FormControl fullWidth variant="standard">
            <InputLabel htmlFor={elementCode}>{labelText}</InputLabel>
            {items ? renderSelect(items, anchorEl, handleMenuOpen, validationError) : renderInput(validationError)}
            {validationError ? (
                <FormHelperText id={`${elementCode}-helper-text`} sx={STYLES.HELPER_TEXT}>
                    *Обязательное поле
                </FormHelperText>
            ) : null}
        </FormControl>
    );
};

//Контроль свойств - Кастомное поле ввода
CustomInputField.propTypes = {
    elementCode: PropTypes.string.isRequired,
    elementValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
    labelText: PropTypes.string.isRequired,
    required: PropTypes.bool,
    items: PropTypes.arrayOf(PropTypes.object),
    emptyItem: PropTypes.object,
    dictionary: PropTypes.func,
    onChange: PropTypes.func,
    menuItemRender: PropTypes.func
};

//--------------------
//Интерфейс компонента
//--------------------

export { CustomInputField };
