/*
    Парус 8 - Панели мониторинга
    Компонент: Диалог
*/

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

import React, { useEffect, useState } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Dialog, DialogTitle, DialogContent, DialogActions, Button } from "@mui/material"; //Интерфейсные компоненты
import { BUTTONS } from "../../app.text"; //Общие текстовые ресурсы
import { P8P_INPUT, P8PInput } from "./p8p_input"; //Поле ввода
import { APP_STYLES } from "../../app.styles"; //Типовые стили

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

//Типовая ширина диалога
const P8P_DIALOG_WIDTH = {
    XS: "xs",
    SM: "sm",
    MD: "md",
    LG: "lg",
    XL: "xl"
};

//Стили
const STYLES = {
    SCROLL: display =>
        display === true ? { overflow: "auto", ...APP_STYLES.SCROLL } : { overflow: "hidden", display: "flex", flexDirection: "column" }
};

//-----------------------
//Вспомогательные функции
//-----------------------

//Формирование объекта вида {ключ: значение} из текущего состояния элементов ввода формы
const buildFormValues = inputsState =>
    inputsState.reduce((res, input) => ({ ...res, [input.name]: input.value == undefined ? null : input.value }), {});

//-----------
//Тело модуля
//-----------

//Диалог
const P8PDialog = ({
    title,
    width,
    fullWidth,
    inputs,
    children,
    okDisabled = false,
    scrollContent = true,
    onOk,
    onCancel,
    onClose,
    onInputChange
}) => {
    //Состояние элементов ввода диалога
    const [inputsState, setInputsState] = useState([]);

    //При изменении элемента ввода
    const handleInputChange = (name, value) => {
        //Если есть функция пересчета формы - вызовем её
        const doNotChangeInputsState = onInputChange ? onInputChange(name, value, inputsState) : false;
        //И ориентируясь на то, пересчитала ли она элементы ввода обновим собственное состояние.
        //Если функция пересчета вернула "true", значит она пересчитала что-то, тогда новые настройки элементов придут через свойство inputs и будут обработаны в useEffect ниже.
        //Следовательно, и нам здесь не надо состояние выставлять, т.к. всё будет перезаписано useEffectом.
        if (!doNotChangeInputsState)
            setInputsState(pv => pv.reduce((accum, cur) => [...accum, { ...cur, value: cur.name === name ? value : cur.value }], []));
    };

    //При нажатии на "ОК" диалога
    const handleOk = () => onOk && onOk(buildFormValues(inputsState));

    //При нажатии на "Отмена" диалога
    const handleCancel = () => onCancel && onCancel();

    //При нажатии на "Закрыть" диалога
    const handleClose = () => (onClose ? onClose() : onCancel ? onCancel() : null);

    //При изменении полей для ввода
    useEffect(() => {
        if (inputs && Array.isArray(inputs) && inputs.length > 0) setInputsState(inputs.map(input => ({ ...input })));
    }, [inputs]);

    //Расчет объектного представления текущих значений формы
    const formValues = buildFormValues(inputsState);

    //Формирование представления
    return (
        <Dialog onClose={handleClose} open {...{ ...(width ? { maxWidth: width } : {}), ...(fullWidth === true ? { fullWidth: true } : {}) }}>
            <DialogTitle>{title}</DialogTitle>
            <DialogContent sx={STYLES.SCROLL(scrollContent)}>
                {inputsState.map((input, i) => (
                    <P8PInput key={i} {...input} formValues={formValues} onChange={handleInputChange} />
                ))}

                {children}
            </DialogContent>
            <DialogActions>
                {onOk && (
                    <Button disabled={okDisabled} onClick={handleOk}>
                        {BUTTONS.OK}
                    </Button>
                )}
                {onCancel && <Button onClick={handleCancel}>{BUTTONS.CANCEL}</Button>}
                {onClose && <Button onClick={handleClose}>{BUTTONS.CLOSE}</Button>}
            </DialogActions>
        </Dialog>
    );
};

//Контроль свойств - Диалог
P8PDialog.propTypes = {
    title: PropTypes.string.isRequired,
    width: PropTypes.oneOf(Object.values(P8P_DIALOG_WIDTH)),
    fullWidth: PropTypes.bool,
    inputs: PropTypes.arrayOf(PropTypes.shape(P8P_INPUT)),
    children: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)]),
    okDisabled: PropTypes.bool,
    scrollContent: PropTypes.bool,
    onOk: PropTypes.func,
    onCancel: PropTypes.func,
    onClose: PropTypes.func,
    onInputChange: PropTypes.func
};

//----------------
//Интерфейс модуля
//----------------

export { P8PDialog, P8P_DIALOG_WIDTH };
