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

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

import React, { useState, useContext, useEffect, useCallback } from "react"; //Классы React
import { BackEndCtx } from "../../../context/backend"; //Контекст взаимодействия с сервером
import PropTypes from "prop-types"; //Контроль свойств компонента
import {
    Dialog,
    DialogTitle,
    IconButton,
    Icon,
    DialogContent,
    DialogActions,
    Button,
    Box,
    Stack,
    Checkbox,
    FormControlLabel,
    Radio,
    RadioGroup
} from "@mui/material"; //Интерфейсные компоненты
import { CustomInputField } from "./custom_input_field"; //Кастомное поле ввода
import { hasValue } from "../../../core/utils"; //Вспомогательные функции
import { EVENT_STATES } from "../layouts"; //Перечисление состояний события
import { COMMON_STYLES } from "../styles"; //Общие стили
import { useDictionary } from "../hooks/dict_hooks"; //Состояние открытия разделов

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

//Стили
const STYLES = {
    SELECT: { width: "450px" }
};

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

//Диалог фильтра отбора
const FilterDialog = ({ initial, onFilterChange, onFilterClose, onDocLinksLoad }) => {
    //Собственное состояние
    const [filter, setFilter] = useState(initial.filter);

    //Состояние текущих учётных документов
    const [curDocLinks, setCurDocLinks] = useState({ loaded: true, docLinks: initial.docLinks });

    //Вспомогательные функции открытия раздела
    const { handleCatalogTreeOpen, handleEventTypesOpen, handleAgnlistOpen, handleInsDepartmentOpen, handleCostStaffGroupsOpen } = useDictionary();

    //Подключение к контексту взаимодействия с сервером
    const { executeStored } = useContext(BackEndCtx);

    //При изменении типа события фильтра
    const handleTypeChange = callBack =>
        handleEventTypesOpen({
            sCode: filter.sType,
            callBack: res => {
                callBack(res.outParameters.eventtypecode);
            }
        });

    //При изменении каталога фильтра
    const handleCrnChange = callBack =>
        handleCatalogTreeOpen({
            sUnitName: "ClientEvents",
            sName: filter.sCrnName,
            callBack: res => {
                callBack(res.outParameters.out_NAME);
            }
        });

    //При изменении исполнителя фильтра
    const handleSendPersonChange = callBack =>
        handleAgnlistOpen({
            sMnemo: filter.sSendPerson,
            callBack: res => {
                callBack(res.outParameters.agnmnemo);
            }
        });

    //При изменении подразделения фильтра
    const handleSendDivisionChange = callBack =>
        handleInsDepartmentOpen({
            sCode: filter.sSendDivision,
            callBack: res => {
                callBack(res.outParameters.out_CODE);
            }
        });

    //При изменении группы пользователей фильтра
    const handleSendUsrGrpChange = callBack =>
        handleCostStaffGroupsOpen({
            sCode: filter.sSendUsrGrp,
            callBack: res => {
                callBack(res.outParameters.out_CODE);
            }
        });

    //Считывание подкаталогов
    const getSubCatalogs = useCallback(async () => {
        //Считываем каталоги
        const data = await executeStored({
            stored: "PKG_P8PANELS_CLNTTSKBRD.CLNEVENTS_SUBCATALOGS_GET",
            args: {
                SCRN_NAME: filter.sCrnName,
                NSUBCAT: filter.bSubcatalogs ? 1 : 0
            }
        });
        //Возвращаем список каталогов
        return data.SRESULT;
    }, [executeStored, filter.sCrnName, filter.bSubcatalogs]);

    //При закрытии диалога с изменением фильтра
    const handleDialogOk = async () => {
        //Если указано имя каталога, но не загружен список рег. номеров
        if (filter.sCrnName && !filter.sCrnRnList) {
            //Загружаем список рег. номеров каталогов
            const crns = await getSubCatalogs();
            //Устанавливаем новый фильтр
            onFilterChange({ ...filter, ...(crns ? { sCrnRnList: crns } : {}) });
            //Закрываем диалог фильтра
            onFilterClose();
        } else {
            //Устанавливаем новый фильтр
            onFilterChange(filter);
            //Закрываем диалог фильтра
            onFilterClose();
        }
    };

    //При очистке фильтра
    const handleFilterClear = () => {
        setFilter({
            sState: EVENT_STATES[1],
            sType: "",
            sCrnName: "",
            sCrnRnList: "",
            bSubcatalogs: false,
            sSendPerson: "",
            sSendDivision: "",
            sSendUsrGrp: "",
            sDocLink: ""
        });
    };

    //При изменении значения элемента
    const handleFilterItemChange = (item, value) => {
        //Если это изменение типа
        if (item === "sType") {
            //Указываем тип с очисткой информации об учетных документах
            setFilter(pv => ({ ...pv, [item]: value, sDocLink: "" }));
            setCurDocLinks(pv => ({ ...pv, loaded: false, docLinks: [] }));
        } else {
            //Обновляем значение поля
            setFilter(pv => ({ ...pv, [item]: value }));
        }
    };

    //При очистке учётного документа
    const handleDocLinkClear = () => setFilter(pv => ({ ...pv, sDocLink: "" }));

    //Обработка изменений с каталогами
    useEffect(() => {
        //Если каталог не указан, но галка подкаталогов установлена - снимаем её
        if (!filter.sCrnName && filter.bSubcatalogs) setFilter(pv => ({ ...pv, bSubcatalogs: false }));
        //Если изменился каталог и остался список рег. номеров каталогов - очищаем его
        if (filter.sCrnName !== initial.sCrnName && filter.sCrnRnList) setFilter(pv => ({ ...pv, sCrnRnList: "" }));
        //Если каталог равен изначальному
        if (filter.sCrnName === initial.sCrnName) {
            //Если признак подкаталогов равен изначальному, но список рег. номеров каталогов не соответствует - загружаем изначальный
            if (filter.bSubcatalogs === initial.bSubcatalogs && filter.sCrnRnList !== initial.sCrnRnList) {
                setFilter(pv => ({ ...pv, sCrnRnList: initial.sCrnRnList }));
            }
            //Если признак подкаталогов не равен изначальному
            if (filter.bSubcatalogs !== initial.bSubcatalogs) {
                //Если не установлен - считываем первый из списка рег. номеров изначальных каталогов
                if (!filter.bSubcatalogs) {
                    setFilter(pv => ({
                        ...pv,
                        sCrnRnList: initial.sCrnRnList.split(";")[0]
                    }));
                } else {
                    //Если установлен - очищаем список рег. номеров каталогов для последующей загрузки
                    setFilter(pv => ({ ...pv, sCrnRnList: "" }));
                }
            }
        }
    }, [filter.sCrnName, filter.sCrnRnList, filter.bSubcatalogs, initial.sCrnName, initial.sCrnRnList, initial.bSubcatalogs]);

    //Генерация содержимого
    return (
        <div>
            <Dialog open onClose={onFilterClose} fullWidth maxWidth="sm">
                <DialogTitle>Фильтр отбора</DialogTitle>
                <IconButton aria-label="close" onClick={onFilterClose} sx={COMMON_STYLES.DIALOG_CLOSE_BUTTON}>
                    <Icon>close</Icon>
                </IconButton>
                <DialogContent sx={COMMON_STYLES.SCROLL}>
                    <Box sx={COMMON_STYLES.BOX_WITH_LEGEND} component="fieldset">
                        <legend style={COMMON_STYLES.LEGEND}>Состояние</legend>
                        <RadioGroup
                            row
                            aria-labelledby="sState-label"
                            id="sState"
                            name="sState"
                            value={filter.sState}
                            onChange={e => handleFilterItemChange(e.target.name, e.target.value)}
                        >
                            {Object.keys(EVENT_STATES).map(function (k) {
                                return <FormControlLabel key={k} value={EVENT_STATES[k]} control={<Radio />} label={EVENT_STATES[k]} />;
                            })}
                        </RadioGroup>
                    </Box>
                    <Box component="section" p={1}>
                        <CustomInputField
                            elementCode="sType"
                            elementValue={filter.sType}
                            labelText="Тип"
                            dictionary={callBack => handleTypeChange(callBack)}
                            onChange={handleFilterItemChange}
                        />
                    </Box>
                    <Box component="section" p={1}>
                        <CustomInputField
                            elementCode="sCrnName"
                            elementValue={filter.sCrnName}
                            labelText="Каталог"
                            dictionary={callBack => handleCrnChange(callBack)}
                            onChange={handleFilterItemChange}
                        />
                        <FormControlLabel
                            control={
                                <Checkbox
                                    id="bSubcatalogs"
                                    name="bSubcatalogs"
                                    checked={filter.bSubcatalogs}
                                    disabled={filter.sCrnName ? false : true}
                                    onChange={e => handleFilterItemChange(e.target.name, e.target.checked)}
                                />
                            }
                            label="Включая подкаталоги"
                        />
                    </Box>
                    <Box component="section" p={1}>
                        <CustomInputField
                            elementCode="sSendPerson"
                            elementValue={filter.sSendPerson}
                            labelText="Исполнитель"
                            dictionary={callBack => handleSendPersonChange(callBack)}
                            onChange={handleFilterItemChange}
                        />
                    </Box>
                    <Box component="section" p={1}>
                        <CustomInputField
                            elementCode="sSendDivision"
                            elementValue={filter.sSendDivision}
                            labelText="Подразделение"
                            dictionary={callBack => handleSendDivisionChange(callBack)}
                            onChange={handleFilterItemChange}
                        />
                    </Box>
                    <Box component="section" p={1}>
                        <CustomInputField
                            elementCode="sSendUsrGrp"
                            elementValue={filter.sSendUsrGrp}
                            labelText="Группа пользователей"
                            dictionary={callBack => handleSendUsrGrpChange(callBack)}
                            onChange={handleFilterItemChange}
                        />
                    </Box>
                    <Box component="section" p={1}>
                        <Stack direction="row" sx={COMMON_STYLES.STACK_DOCLINKS}>
                            <CustomInputField
                                elementCode="sDocLink"
                                elementValue={filter.sDocLink}
                                labelText="Учётный документ"
                                items={[...(curDocLinks.docLinks || [])].reduce((prev, cur) => [...prev, { id: cur.NRN, caption: cur.SDESCR }], [])}
                                disabled={!curDocLinks.docLinks.length ? true : false}
                                onChange={handleFilterItemChange}
                                sx={STYLES.SELECT}
                            />
                            <IconButton title="Очистить" disabled={!filter.sDocLink} onClick={handleDocLinkClear}>
                                <Icon>clear</Icon>
                            </IconButton>
                            <IconButton
                                title="Обновить"
                                disabled={curDocLinks.loaded}
                                onClick={() => {
                                    //Очищаем учетный документ
                                    handleDocLinkClear();
                                    //Загружаем учетные документы типа
                                    onDocLinksLoad(filter.sType).then(dl => setCurDocLinks(pv => ({ ...pv, loaded: true, docLinks: dl })));
                                }}
                            >
                                <Icon>refresh</Icon>
                            </IconButton>
                        </Stack>
                    </Box>
                </DialogContent>
                <DialogActions sx={COMMON_STYLES.DIALOG_ACTIONS}>
                    <Button disabled={!hasValue(filter.sType)} variant="text" onClick={handleDialogOk}>
                        ОК
                    </Button>
                    <Button variant="text" onClick={handleFilterClear}>
                        Очистить
                    </Button>
                    <Button variant="text" onClick={onFilterClose}>
                        Отмена
                    </Button>
                </DialogActions>
            </Dialog>
        </div>
    );
};

//Контроль свойств компонента - Диалог фильтра отбора
FilterDialog.propTypes = {
    initial: PropTypes.object.isRequired,
    onFilterChange: PropTypes.func.isRequired,
    onFilterClose: PropTypes.func.isRequired,
    onDocLinksLoad: PropTypes.func
};

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

export { FilterDialog };
