/*
    Парус 8 - Панели мониторинга - ТОиР - Выполнение работ
    Панель мониторинга: Корневая панель выполнения работ
*/

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

import React, { useState, useContext, useCallback, useEffect } from "react"; //Классы React
import { Box } from "@mui/material"; //Интерфейсные компоненты
import { P8PDataGrid, P8P_DATA_GRID_SIZE } from "../../components/p8p_data_grid"; //Таблица данных
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
import { MessagingCtx } from "../../context/messaging"; //Контекст сообщений
import { headCellRender, dataCellRender, groupCellRender, DIGITS_REG_EXP, MONTH_NAME_REG_EXP, DAY_NAME_REG_EXP } from "./layouts"; //Дополнительная разметка и вёрстка клиентских элементов
import { TEXTS } from "../../../app.text"; //Тектовые ресурсы и константы
import { Filter } from "./filter"; //Компонент фильтра
import { FilterDialog } from "./filter_dialog"; //Компонент диалогового окна фильтра отбора
import { useWindowResize } from "./hooks"; //Пользовательские хуки

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

//Высота меню Парус (пиксели)
const pxOuterMenuH = 53;
//Высота заголовка панели (пиксели)
const pxPanelHeaderH = 64;
//Минимальная ширина таблицы (пиксели)
const minGridW = 800;
//Минимальная высота таблицы (пиксели)
const minGridH = 200;

//Стили
const STYLES = {
    BOX_ROW: { display: "flex", justifyContent: "center", alignItems: "center" },
    GRID_PADDING: { paddingTop: 1, paddingBottom: 1 },
    GRID_SIZES: (width, height) => ({
        padding: "0px",
        minWidth: minGridW,
        maxWidth: width * 0.975 > minGridW ? width * 0.975 : minGridW,
        minHeight: minGridH,
        maxHeight: (height - pxOuterMenuH - pxPanelHeaderH) * 0.975 > minGridH ? (height - pxOuterMenuH - pxPanelHeaderH) * 0.975 : minGridH
    })
};

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

//Корневая панель выполнения работ
const EqsPrfrm = () => {
    //Собственное состояние - таблица данных
    const [dataGrid, setDataGrid] = useState({
        dataLoaded: false,
        columnsDef: [],
        groups: [],
        rows: [],
        fixedHeader: false,
        fixedColumns: 0,
        reload: false
    });

    //Состояние фильтра
    const [filter, setFilter] = useState({
        isOpen: false,
        isDefault: false,
        isSetByUser: false,
        needSave: false,
        values: {
            belong: "",
            prodObj: "",
            techServ: "",
            respDep: "",
            fromMonth: 1,
            fromYear: 1990,
            toMonth: 1,
            toYear: 1990
        }
    });

    //Состояние ячейки заголовка даты (по раскрытию/скрытию)
    const [activeRef, setActiveRef] = useState();

    //Состояние актуальности ссылки на ячейку
    const [refIsDeprecated, setRidFlag] = useState(true);

    //Подключение к контексту приложения
    const { pOnlineShowUnit } = useContext(ApplicationCtx);

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

    //Подключение к контексту сообщений
    const { showMsgErr } = useContext(MessagingCtx);

    //Загрузка данных таблицы с сервера
    const loadData = useCallback(async () => {
        if (dataGrid.reload) {
            const data = await executeStored({
                stored: "PKG_P8PANELS_EQUIPSRV.EQUIPSRV_GRID",
                args: {
                    SBELONG: filter.values.belong,
                    SPRODOBJ: filter.values.prodObj,
                    STECHSERV: filter.values.techServ,
                    SRESPDEP: filter.values.respDep,
                    NFROMMONTH: filter.values.fromMonth,
                    NFROMYEAR: filter.values.fromYear,
                    NTOMONTH: filter.values.toMonth,
                    NTOYEAR: filter.values.toYear
                },
                respArg: "COUT",
                attributeValueProcessor: (name, val) => (["caption", "name", "parent"].includes(name) ? undefined : val)
            });
            let cP = 0;
            let sP = 0;
            let cF = 0;
            let sF = 0;
            let properties = [];
            if (data.XDATA_GRID.rows != null) {
                data.XDATA_GRID.rows.map(row => {
                    properties = [];
                    Object.entries(row).forEach(([key, value]) => properties.push({ name: key, data: value }));
                    let info2 = properties.find(element => {
                        return element.name === "SINFO2";
                    });
                    if (info2 != undefined) {
                        if (info2.data == "План") {
                            properties.map(p => {
                                if (DAY_NAME_REG_EXP.test(p.name)) cP = cP + 1;
                            });
                        } else if (info2.data == "Факт") {
                            properties.map(p => {
                                if (DAY_NAME_REG_EXP.test(p.name)) cF = cF + 1;
                            });
                        }
                    } else {
                        properties.map(p => {
                            if (MONTH_NAME_REG_EXP.test(p.name)) {
                                let str = p.data;
                                let m = [];
                                let i = 0;
                                while ((m = DIGITS_REG_EXP.exec(str)) != null) {
                                    if (i == 0) sP = sP + Number(m[0].replace(",", "."));
                                    else {
                                        sF = sF + Number(m[0].replace(",", "."));
                                    }
                                    i++;
                                }
                            }
                        });
                    }
                });
            }
            setDataGrid(pv => ({
                ...pv,
                ...data.XDATA_GRID,
                columnsDef: data.XDATA_GRID.columnsDef ? [...data.XDATA_GRID.columnsDef] : pv.columnsDef,
                rows: [...(data.XDATA_GRID.rows || [])],
                groups: [...(data.XDATA_GRID.groups || [])],
                dataLoaded: true,
                reload: false
            }));
        }
    }, [dataGrid.reload, filter, executeStored]);

    //Загрузка значений фильтра по умолчанию
    const loadDefaultFilter = useCallback(async () => {
        const data = await executeStored({
            stored: "PKG_P8PANELS_EQUIPSRV.GET_DEFAULT_FP",
            respArg: "COUT"
        });
        setFilter(pv => ({
            ...pv,
            values: { ...pv.values, belong: data.JURPERS, fromMonth: 1, fromYear: data.YEAR, toMonth: 12, toYear: data.YEAR },
            isDefault: true
        }));
    }, [executeStored]);

    //Загрузка значений фильтра из локального хранилища браузера
    const loadLocalFilter = useCallback(async () => {
        let vs = filter.values;
        Object.keys(vs).map(function (k) {
            vs[k] =
                k == "fromMonth" || k == "fromYear" || k == "toMonth" || k == "toYear" ? Number(localStorage.getItem(k)) : localStorage.getItem(k);
        });
        setFilter(pv => ({ ...pv, isDefault: true, values: { ...vs } }));
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

    //Отбор документа (ТОиР или Ремонтных ведомостей) по ячейке даты
    const showEquipSrv = async ({ date, workType, info }) => {
        const [techName, servKind] = info.split("_");
        let type;
        if (workType == "План") type = 0;
        else type = 1;
        let [year, month, day] = date.substring(1).split("_");
        const data = await executeStored({
            stored: "PKG_P8PANELS_EQUIPSRV.SELECT_EQUIPSRV",
            args: {
                SBELONG: filter.values.belong,
                SPRODOBJ: filter.values.prodObj,
                STECHSERV: filter.values.techServ ? filter.values.techServ : null,
                SRESPDEP: filter.values.respDep ? filter.values.respDep : null,
                STECHNAME: techName,
                SSRVKIND: servKind,
                NYEAR: Number(year),
                NMONTH: Number(month),
                NDAY: day ? Number(day) : null,
                NWORKTYPE: type
            }
        });
        if (data.NIDENT) {
            if (type == 0) pOnlineShowUnit({ unitCode: "EquipTechServices", inputParameters: [{ name: "in_Ident", value: data.NIDENT }] });
            else pOnlineShowUnit({ unitCode: "EquipRepairSheets", inputParameters: [{ name: "in_Ident", value: data.NIDENT }] });
        } else showMsgErr(TEXTS.NO_DATA_FOUND);
    };

    //Показать/скрыть фильтр
    const setFilterOpen = isOpen => setFilter(pv => ({ ...pv, isOpen }));

    //Установить значение фильтра
    const setFilterValues = values => setFilter(pv => ({ ...pv, isSetByUser: true, needSave: true, values: { ...values } }));

    //Отработка события скрытия/раскрытия ячейки даты
    const handleClick = (e, ref) => {
        const curCell = ref.current;
        if (e.target.type == "button" || e.target.offsetParent.type == "button") {
            setActiveRef(curCell);
            setRidFlag(false);
        }
    };

    //При необходимости обновить данные таблицы
    useEffect(() => {
        loadData();
    }, [loadData, dataGrid.reload]);

    //При изменении фильтра
    useEffect(() => {
        if (filter.isSetByUser) setDataGrid({ reload: true });
    }, [
        filter.isSetByUser,
        filter.values.belong,
        filter.values.prodObj,
        filter.values.techServ,
        filter.values.respDep,
        filter.values.fromMonth,
        filter.values.fromYear,
        filter.values.toMonth,
        filter.values.toYear
    ]);

    //При нажатии скрытии/раскрытии ячейки даты, фокус на неё
    useEffect(() => {
        if (!refIsDeprecated) {
            if (activeRef) {
                var cellRect = activeRef.getBoundingClientRect();
                window.scrollTo(window.scrollX + cellRect.left + activeRef.clientWidth / 2 - window.innerWidth / 2, 0);
                setRidFlag(true);
            }
        }
        //eslint-disable-next-line react-hooks/exhaustive-deps
    }, [refIsDeprecated]);

    //При закрытии панели
    useEffect(() => {
        filter.needSave
            ? window.addEventListener("beforeunload", function () {
                  Object.keys(filter.values).map(function (k) {
                      localStorage.setItem(k, filter.values[k]);
                  });
              })
            : null;
    }, [filter.needSave, filter.values]);

    //При загрузке фильтра по умолчанию
    useEffect(() => {
        if (filter.isDefault) setFilterOpen(true);
    }, [filter.isDefault]);

    //При подключении к странице
    useEffect(() => {
        localStorage.getItem("belong") ? loadLocalFilter() : loadDefaultFilter();
    }, [loadDefaultFilter, loadLocalFilter]);

    //При открытии диалога фильтра
    const handleFilterClick = () => setFilterOpen(true);

    //При изменении фильтра в диалоге
    const handleFilterOk = filter => {
        setFilterValues(filter);
        setFilterOpen(false);
    };

    //При закрытии диалога фильтра
    const handleFilterCancel = () => setFilterOpen(false);

    //Состояние ширины и высоты рабочей области окна
    const [width, height] = useWindowResize();

    //Генерация содержимого
    return (
        <div>
            {filter.isOpen ? <FilterDialog initial={filter.values} onOk={handleFilterOk} onCancel={handleFilterCancel} /> : null}
            <Filter filter={filter.values} onClick={handleFilterClick} />
            {dataGrid.dataLoaded ? (
                <Box sx={{ ...STYLES.GRID_PADDING, ...STYLES.BOX_ROW }}>
                    <P8PDataGrid
                        {...P8P_DATA_GRID_CONFIG_PROPS}
                        containerComponentProps={{
                            elevation: 6,
                            style: {
                                ...STYLES.GRID_SIZES(width, height)
                            }
                        }}
                        columnsDef={dataGrid.columnsDef}
                        groups={dataGrid.groups}
                        rows={dataGrid.rows}
                        fixedHeader={dataGrid.fixedHeader}
                        fixedColumns={dataGrid.fixedColumns}
                        size={P8P_DATA_GRID_SIZE.LARGE}
                        reloading={dataGrid.reload}
                        headCellRender={prms => headCellRender({ ...prms }, handleClick)}
                        dataCellRender={prms => dataCellRender({ ...prms }, width * 0.2, showEquipSrv)}
                        groupCellRender={prms => groupCellRender({ ...prms })}
                        showCellRightBorder={true}
                    />
                </Box>
            ) : null}
        </div>
    );
};

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

export { EqsPrfrm };
