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

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

import React, { useState, useRef, useEffect } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Button, Stack, TextField } from "@mui/material"; //Интерфейсные компоненты MUI
import { P8PDialog } from "../../../../components/p8p_dialog"; //Типовой диалог
import { DATA_TYPE_ICON } from "../../common"; //Общие ресурсы и константы редактора запросов
import { ENTITY_SHAPE } from "../entity/entity"; //Описание сущности
import { ARGUMENT_SHAPE } from "../argument/argument"; //Описание аргумента запроса
import { CondOperationButtons } from "./cond_operation_buttons"; //Кнопки операций условия отбора
import { CondComponentSelectButton, COMPONENT_TYPE } from "./cond_component_select_button"; //Кнопка выбора компонента условия

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

//Иконки
const ICONS = { ...DATA_TYPE_ICON, DEFAULT: "category" };

//Стили
const STYLE = {
    BUTTONS_STACK: { width: "550px" }
};

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

//Диалог настройки условий отбора запроса
const QueryCondDialog = ({ cond, entities, args, onOk, onCancel }) => {
    //Собственное состояние - условия отбора
    const [conditions, setConditions] = useState(cond || "");

    //Ссылка на элемент ввода условия
    const coditionInputRef = useRef(null);

    //Перемещение курсора в конец поля ввода условия
    const moveCondCursorToEnd = () => {
        if (coditionInputRef.current) {
            const length = coditionInputRef.current.value.length;
            coditionInputRef.current.setSelectionRange(length, length);
            coditionInputRef.current.focus();
        }
    };

    //Добавление значения в редактор по месту курсора
    const addCondValueToCursor = value => {
        let newValue = conditions + value;
        if (coditionInputRef.current) {
            newValue = coditionInputRef.current.value;
            newValue =
                newValue.substring(0, coditionInputRef.current.selectionStart) + value + newValue.substring(coditionInputRef.current.selectionEnd);
            coditionInputRef.current.value = newValue;
        }
        moveCondCursorToEnd();
        setConditions(newValue);
    };

    //Нажатие на кнопку "ОК"
    const handleOk = () => onOk && onOk(conditions);

    //Нажатие на кнопку "Отмена"
    const handleCancel = () => onCancel && onCancel();

    //При изменении условия через компонент
    const handleChange = e => setConditions(e.target.value);

    //При выборе компонента условия
    const handleComponentSelected = value => addCondValueToCursor(value);

    //При нажатии на кнопку операции
    const handleOperationButtonClick = value => addCondValueToCursor(value);

    //При нажатии на кнопку очистки условий
    const handleClearClick = () => setConditions("");

    //При подмонтировании компонента
    useEffect(() => {
        //Перевод курсора в конец обёрнут в setTimeout по тому, что Input подмонтируется позднее диалога (он внутри children)
        setTimeout(moveCondCursorToEnd, 100);
    }, []);

    //Доступные атрибуты сущностей запроса
    const entsAttributes =
        entities && entities?.length > 0
            ? entities.reduce(
                  (components, e) => [
                      ...components,
                      { type: COMPONENT_TYPE.DIVIDER, title: e.title },
                      ...e.attrs.map(a => ({
                          type: COMPONENT_TYPE.ITEM,
                          title: a.title,
                          name: a.name,
                          value: a.id,
                          icon: ICONS[a.dataType] || ICONS.DEFAULT
                      }))
                  ],
                  []
              )
            : [];
    const entsAttributesExists = entsAttributes.find(a => a.type === COMPONENT_TYPE.ITEM) ? true : false;

    //Доступные аргументы запроса
    const queryArguments =
        args && args?.length > 0
            ? args.reduce(
                  (components, a) => [
                      ...components,
                      {
                          type: COMPONENT_TYPE.ITEM,
                          title: a.title,
                          name: a.name,
                          value: `:${a.name}`,
                          icon: ICONS[a.dataType] || ICONS.DEFAULT
                      }
                  ],
                  []
              )
            : [];
    const queryArgumentsExists = queryArguments.length > 0 ? true : false;

    //Генерация содержимого
    return (
        <P8PDialog title={`Условия отбора запроса`} onOk={handleOk} onCancel={handleCancel}>
            <Stack sx={STYLE.BUTTONS_STACK} direction={"row"} spacing={1} pb={1}>
                {entsAttributesExists && (
                    <CondComponentSelectButton caption={"Атрибут сущности"} components={entsAttributes} onSelect={handleComponentSelected} />
                )}
                {queryArgumentsExists && (
                    <CondComponentSelectButton caption={"Аргумент запроса"} components={queryArguments} onSelect={handleComponentSelected} />
                )}
                <Button onClick={handleClearClick}>Очистить</Button>
            </Stack>
            <Stack sx={STYLE.BUTTONS_STACK} direction={"row"} spacing={1} pb={1}>
                <CondOperationButtons
                    buttons={[
                        { caption: "=", title: "Равно", value: " = " },
                        { caption: "<>", title: "Не равно", value: " <> " },
                        { caption: ">", title: "Больше", value: " > " },
                        { caption: ">=", title: "Больше или равно", value: " >= " },
                        { caption: "<", title: "Меньше", value: " < " },
                        { caption: "<=", title: "Меньше или равно", value: " <= " },
                        { caption: "(", title: "Открывающая скобка", value: "(" },
                        { caption: ")", title: "Закрывающая скобка", value: ")" }
                    ]}
                    onClick={handleOperationButtonClick}
                />
                <CondOperationButtons
                    buttons={[
                        { caption: "И", title: "Логическое умножение (конъюнкция)", value: " and " },
                        { caption: "ИЛИ", title: "Логическое сложение (дизъюнкция)", value: " or " },
                        { caption: "НЕ", title: "Отрицание (инверсия)", value: " not " },
                        { caption: "B", title: "Входит в диапазон", value: " in (0, 1, ...) " }
                    ]}
                    onClick={handleOperationButtonClick}
                />
            </Stack>
            <TextField
                inputRef={coditionInputRef}
                focused={true}
                autoFocus
                value={conditions}
                placeholder={"Настройте условия отбора..."}
                multiline
                minRows={10}
                fullWidth
                onChange={handleChange}
            />
        </P8PDialog>
    );
};

//Контроль свойств - Диалог настройки условий отбора запроса
QueryCondDialog.propTypes = {
    cond: PropTypes.string,
    onOk: PropTypes.func,
    entities: PropTypes.arrayOf(ENTITY_SHAPE),
    args: PropTypes.arrayOf(ARGUMENT_SHAPE),
    onCancel: PropTypes.func
};

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

export { QueryCondDialog };
