/*
    Парус 8 - Панели мониторинга - Редакторы панелей
    Компонент: Редактор действия
*/

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

import React, { useState, useEffect } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { TextField, Select, Menu, MenuItem, FormControl, InputLabel, Stack, Box } from "@mui/material"; //Интерфейсные элементы
import { TITLES } from "../../../../app.text"; //Общие текстовые ресурсы
import { P8PConfigDialog } from "../p8p_config_dialog"; //Диалог настройки
import { deepCopyObject } from "../../../core/utils"; //Вспомогательные функции
import { P8P_CA_DEF_VALUE_TYPES, P8P_CA_TYPE, P8P_CA_SHAPE, P8P_CA_INPUT_PARAM_INITIAL, P8P_CA_OPEN_UNIT_INITIAL, P8P_CA_INITIAL } from "./common"; //Общие ресурсы действий
import { P8PCAUnitOpenOptions } from "./config_unit_open"; //Компонент редактора действия "Открыть раздел"
import { P8PCAPanelOpenOptions } from "./config_panel_open"; //Компонент редактора действия "Открыть панель"
import { P8PCAVarSetOptions } from "./config_var_set"; //Компонент редактора действия "Установить переменную"
import { isActionOkDisabled, getActionTypeParams } from "./util"; //Вспомогательные ресурсы действий

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

//Стили
const STYLES = {
    CONTAINER: { display: "flex", flexDirection: "column", gap: "10px", minWidth: "300px" }
};

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

//Редактор действия
const P8PCAEditor = ({ areas = [], valueTypes = [], action = null, onOk = null, onCancel = null, valueProviders = {} }) => {
    //Собственное состояние - признак инициализиации
    const [init, setInit] = useState(true);

    //Собственное состояние - параметры действия
    const [state, setState] = useState({});

    //Собственное состояние - доступные типы значений компонента
    const [availableValueTypes, setAvailableValueTypes] = useState([]);

    //Собственное состояние - доступные области компонента
    const [availableAreas, setAvailableAreas] = useState([]);

    //Собственное состояние - доступность поля "Элемент"
    const [hasElement, setHasElement] = useState(false);

    //Собственное состояние - элемент привязки меню выбора источника
    const [valueProvidersMenuAnchorEl, setValueProvidersMenuAnchorEl] = useState({
        target: null,
        onChange: null
    });

    //Открытие/сокрытие меню выбора источника
    const toggleValueProvidersMenu = (target, onChange) =>
        setValueProvidersMenuAnchorEl(target instanceof Element ? { target, onChange } : { target: null, onChange: null });

    //При отображении меню связывания значения с поставщиком данных
    const handleValueSourceLinkMenuClick = (e, onChange) => setValueProvidersMenuAnchorEl({ target: e.currentTarget, onChange });

    //При закрытии редактора с сохранением
    const handleOk = () => onOk && onOk({ ...state });

    //При закрытии редактора с отменой
    const handleCancel = () => onCancel && onCancel();

    //При изменении типа действия
    const handleTypeChange = e => {
        //Иницилизируем параметры типа
        let newParams = getActionTypeParams(e.target.value);
        //Изменяем тип действия с изменение структуры параметров
        setState(pv => ({
            ...pv,
            type: e.target.value,
            params: Array.isArray(newParams) ? [...newParams] : { ...newParams }
        }));
    };

    //При ручном изменении общего параметра действия
    const handleChange = e => setState(pv => ({ ...pv, [e.target.name]: e.target.value }));

    //При изменении области действия
    const handleAreaChange = e => {
        //Устанавливаем значение
        setState(pv => ({ ...pv, [e.target.name]: e.target.value, name: "" }));
        //Устанавливаем доступность "Элемент"
        setHasElement(availableAreas.find(item => item.area === e.target.value).hasElement);
    };

    //При изменении полей параметров действия
    const handleParamsChange = params => {
        setState(pv => ({ ...pv, params: { ...pv.params, ...params } }));
    };

    //При изменении переменных параметров действия "Установить переменную"
    const handleVariablesParamsChange = variables => {
        setState(pv => ({ ...pv, params: [...variables] }));
    };

    //Список значений
    const values = Object.keys(valueProviders);

    //Наличие значений
    const isValues = values && values.length > 0 ? true : false;

    //Меню привязки к поставщикам значений
    const valueProvidersMenu = isValues && (
        <Menu anchorEl={valueProvidersMenuAnchorEl.target} open={Boolean(valueProvidersMenuAnchorEl.target)} onClose={toggleValueProvidersMenu}>
            {values.map((value, i) => (
                <MenuItem
                    key={i}
                    onClick={() => {
                        //Выполняем выбор параметра
                        valueProvidersMenuAnchorEl.onChange(value);
                        //Закрываем меню выбора переменной
                        toggleValueProvidersMenu();
                    }}
                >
                    {value}
                </MenuItem>
            ))}
        </Menu>
    );

    //При инициализации действия
    useEffect(() => {
        //Если это иницализация
        if (init) {
            //Если это открытие действия - берем его параметры, иначе - инициализируем изначальными
            const initAction = action
                ? action
                : {
                      ...P8P_CA_INITIAL,
                      area: areas[0].area,
                      params: { ...P8P_CA_OPEN_UNIT_INITIAL, inputParams: [{ ...P8P_CA_INPUT_PARAM_INITIAL }] }
                  };
            //Устанавливаем параметры действия
            setState(deepCopyObject(initAction));
            //Заполняем доступные области
            setAvailableAreas([...areas]);
            //Определяем доступность "Элемент"
            setHasElement(areas.find(item => item.area === initAction.area)?.hasElement || false);
            //Заполняем доступные типы значений
            setAvailableValueTypes([...P8P_CA_DEF_VALUE_TYPES, ...valueTypes]);
            //Сбрасываем признак инициализации
            setInit(false);
        }
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [init]);

    //Формирование представления
    return (
        <>
            {!init ? (
                <P8PConfigDialog
                    title={`${action ? TITLES.UPDATE : TITLES.INSERT} действия`}
                    onOk={handleOk}
                    onCancel={handleCancel}
                    width={"xl"}
                    okDisabled={isActionOkDisabled(state)}
                >
                    <Stack direction={"column"} spacing={1}>
                        {valueProvidersMenu}
                        <Box sx={STYLES.CONTAINER}>
                            {availableAreas.length !== 0 ? (
                                <FormControl variant={"standard"} fullWidth>
                                    <InputLabel id={"areaLabel-label"}>Область</InputLabel>
                                    <Select name={"area"} value={state.area} labelId={"area-label"} label={"Область"} onChange={handleAreaChange}>
                                        {availableAreas.map((item, index) => (
                                            <MenuItem value={item.area} key={index}>
                                                {item.name}
                                            </MenuItem>
                                        ))}
                                    </Select>
                                </FormControl>
                            ) : null}
                            {hasElement && (
                                <TextField
                                    type={"text"}
                                    variant={"standard"}
                                    value={state.element}
                                    label={"Элемент"}
                                    name={"element"}
                                    onChange={handleChange}
                                />
                            )}
                            <FormControl variant={"standard"} fullWidth>
                                <InputLabel id={"type-label"}>Тип</InputLabel>
                                <Select name={"type"} value={state.type} labelId={"type-label"} label={"Тип"} onChange={handleTypeChange}>
                                    {Object.keys(P8P_CA_TYPE).map((item, index) => (
                                        <MenuItem value={P8P_CA_TYPE[item].code} key={index}>
                                            {P8P_CA_TYPE[item].name}
                                        </MenuItem>
                                    ))}
                                </Select>
                            </FormControl>
                        </Box>
                        {state.type === P8P_CA_TYPE.openUnit.code && (
                            <P8PCAUnitOpenOptions
                                unit={state.params}
                                valueTypes={availableValueTypes}
                                isValues={isValues}
                                onStateChange={handleParamsChange}
                                onValueSourceMenuClick={handleValueSourceLinkMenuClick}
                            />
                        )}
                        {state.type === P8P_CA_TYPE.openPanel.code && (
                            <P8PCAPanelOpenOptions
                                panel={state.params}
                                valueTypes={availableValueTypes}
                                isValues={isValues}
                                onStateChange={handleParamsChange}
                                onValueSourceMenuClick={handleValueSourceLinkMenuClick}
                            />
                        )}
                        {state.type === P8P_CA_TYPE.setVariable.code && (
                            <P8PCAVarSetOptions
                                variables={state.params}
                                valueTypes={availableValueTypes}
                                isValues={isValues}
                                onStateChange={handleVariablesParamsChange}
                                onValueSourceMenuClick={handleValueSourceLinkMenuClick}
                            />
                        )}
                    </Stack>
                </P8PConfigDialog>
            ) : null}
        </>
    );
};

//Контроль свойств - Редактор условия
P8PCAEditor.propTypes = {
    areas: PropTypes.array,
    valueTypes: PropTypes.array,
    action: P8P_CA_SHAPE,
    onOk: PropTypes.func.isRequired,
    onCancel: PropTypes.func.isRequired,
    valueProviders: PropTypes.object
};

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

export { P8PCAEditor };
