/*
    Парус 8 - Панели мониторинга - ПУП - Выдача сменного задания
    Компонент панели: Таблица информации о строках сменного задания
*/

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

import React, { useState } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import {
    Typography,
    Box,
    Checkbox,
    Grid,
    Icon,
    Button,
    Dialog,
    DialogContent,
    TextField,
    DialogActions,
    Tooltip,
    Stack,
    DialogTitle
} from "@mui/material"; //Интерфейсные элементы
import { BUTTONS } from "../../../app.text"; //Текстовые ресурсы
import { APP_BAR_HEIGHT } from "../../components/p8p_app_workspace"; //Заголовок страницы
import { P8PDataGrid, P8P_DATA_GRID_SIZE, P8P_DATA_GRID_MORE_HEIGHT } from "../../components/p8p_data_grid"; //Таблица данных
import { APP_STYLES } from "../../../app.styles"; //Типовые стили
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { useCostJobsSpecs, useEquipConfiguration } from "./hooks"; //Собственные хуки таблиц
import { MAIN_HEADER_HEIGHT, SUB_HEADER_HEIGHT } from "./mech_rec_cost_jobs_manage"; //Заглавный компонент панели

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

//Мнемокод раздела операций
const UNIT_COST_JOBS_SPECS = "CostJobsSpecs";

//Мнемокод раздела рабочих центров
const UNIT_COST_EQUIPMENT = "CostEquipment";

//Высота заголовка таблицы
const TABLE_HEADER_HEIGHT = "35px";

//Высота панели кнопок таблицы
const TABLE_BUTTONS_HEIGHT = "35px";

//Отступ таблицы
const TABLE_PADDING_TOP = "15px";

//Стили
const STYLES = {
    CONTAINER: { textAlign: "center" },
    DATA_GRID_CONTAINER: morePages => ({
        height: `calc(100vh - ${APP_BAR_HEIGHT} - ${MAIN_HEADER_HEIGHT} - ${SUB_HEADER_HEIGHT} - ${TABLE_HEADER_HEIGHT} - ${TABLE_BUTTONS_HEIGHT} - ${TABLE_PADDING_TOP} - 32px - ${
            morePages ? P8P_DATA_GRID_MORE_HEIGHT : "0px"
        })`,
        ...APP_STYLES.SCROLL
    }),
    TABLE: { paddingTop: TABLE_PADDING_TOP },
    TABLE_HEADER: { height: TABLE_HEADER_HEIGHT, overflow: "hidden" },
    TABLE_BUTTONS: { display: "flex", justifyContent: "flex-end", height: TABLE_BUTTONS_HEIGHT, overflow: "hidden" },
    CHECK_BOX: { textAlign: "center" },
    JOBS_INFO: { textAlign: "center" },
    EQUIPMENT_INFO: { textAlign: "center" }
};

//Цвета
const colors = {
    LINKED: "#bce0de",
    UNAVAILABLE: "#949494",
    WITH_EQCONFIG: "#82df83"
};

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

//Форматирование значения ячейки
const dataCellRender = ({ row, columnDef, handleSelectChange, sUnit, selectedRow, selectedJobSpec }) => {
    //Стиль
    let cellStyle = {};
    //Если это рабочие центры
    if (sUnit === UNIT_COST_EQUIPMENT) {
        //Признак недоступности
        let disabled = true;
        //Если в выбранной строке смены указано рабочее место
        if (selectedJobSpec.NEQCONFIG) {
            //Если это текущее рабочее место
            if (row["NRN"] === selectedJobSpec.NEQCONFIG) {
                //Подсвечиваем строку рабочего места
                cellStyle = { backgroundColor: colors.LINKED };
            }
        } else {
            //Если выбрана строка смены
            if (selectedJobSpec.NRN) {
                //Если на текущее рабочее место возможно добавить задание
                if (row["NLOADING"] < 100 && row["NEQUIPMENT"] === selectedJobSpec.NEQUIP_PLAN) {
                    //Подсвечиваем строку рабочего места
                    cellStyle = { backgroundColor: colors.LINKED };
                    disabled = false;
                }
            }
        }
        //Если рабочий центр загружен
        if (row["NLOADING"] >= 100) {
            //Если поле не поле выбора
            if (columnDef.name !== "NSELECT") {
                //Указываем, что рабочее место недоступно
                cellStyle = { ...cellStyle, color: colors.UNAVAILABLE };
            }
        }
        //Для колонки выбора
        if (columnDef.name === "NSELECT") {
            return {
                cellStyle,
                data: (
                    <Box sx={STYLES.CHECK_BOX}>
                        <Checkbox
                            disabled={disabled}
                            checked={row["NRN"] === selectedRow}
                            onChange={() => handleSelectChange({ NRN: row["NRN"], SUNIT: sUnit, BFULL_LOADED: row["NLOADING"] >= 100 })}
                        />
                    </Box>
                )
            };
        }
        //Отформатированная колонка
        return {
            cellStyle,
            data: row[columnDef.name]
        };
    }
    //Если это сменное задание
    if (sUnit === UNIT_COST_JOBS_SPECS) {
        //Если указан станок
        if (row["SEQCONFIG"]) {
            //Подсвечиваем сменное задание зеленым
            cellStyle = { ...cellStyle, backgroundColor: colors.WITH_EQCONFIG };
        }
        //Для колонки выбора
        if (columnDef.name === "NSELECT") {
            return {
                cellStyle,
                data: (
                    <Box sx={STYLES.CHECK_BOX}>
                        <Checkbox
                            disabled={row["DBEG_FACT"] ? true : false}
                            checked={row["NRN"] === selectedRow}
                            onChange={() =>
                                handleSelectChange({
                                    NRN: row["NRN"],
                                    SUNIT: sUnit,
                                    NEQCONFIG: row["NEQCONFIG"],
                                    NEQUIP_PLAN: row["NEQUIP_PLAN"],
                                    NQUANT_PLAN: row["NQUANT_PLAN"]
                                })
                            }
                        />
                    </Box>
                )
            };
        }
        //Отформатированная колонка
        return {
            cellStyle,
            data: row[columnDef.name]
        };
    }
    //Необрабатываемый раздел
    return {
        data: row[columnDef.name]
    };
};

//Генерация представления ячейки заголовка группы
export const headCellRender = ({ columnDef }) => {
    if (columnDef.name === "NSELECT") {
        return {
            stackStyle: { padding: "2px", justifyContent: "space-around" },
            data: <Icon>done</Icon>
        };
    } else {
        return {
            stackStyle: { padding: "2px" },
            data: columnDef.caption
        };
    }
};

//Диалог включения станка в сменное задание
const CostJobsSpecsInclude = ({ includeEquipment, setIncludeEquipment, setCostJobsSpecs, setEquipConfiguration, includeEquipConfiguration }) => {
    //Собственное состояние - Значение приоритета
    const [state, setState] = useState(includeEquipment.NVALUE);

    //При закрытии включения станка
    const handlePriorEditClose = () => {
        setIncludeEquipment({
            NFCJOBSSP: null,
            NEQCONFIG: null,
            NVALUE: 0
        });
    };

    //При включении станка в строку сменного задания
    const costJobsSpecIncludeCostEquipment = () => {
        //Делаем асинхронно, чтобы при ошибке ничего не обновлять
        const includeAsync = async () => {
            //Включаем станок в строку сменного задания
            try {
                await includeEquipConfiguration({
                    NEQCONFIG: includeEquipment.NEQCONFIG,
                    NFCJOBSSP: includeEquipment.NFCJOBSSP,
                    NQUANT_PLAN: state
                });
                //Необходимо обновить все данные
                setCostJobsSpecs(pv => ({ ...pv, selectedRow: {}, pageNumber: 1, reload: true }));
                setEquipConfiguration(pv => ({ ...pv, selectedRow: {}, pageNumber: 1, reload: true }));
                handlePriorEditClose();
            } catch (e) {
                throw new Error(e.message);
            }
        };
        //Включаем станок асинхронно
        includeAsync();
    };

    return (
        <Dialog open onClose={() => handlePriorEditClose()}>
            <DialogTitle>Включить в задание</DialogTitle>
            <DialogContent>
                <Box>
                    <TextField
                        name="editInculdeValue"
                        label="Количество"
                        variant="standard"
                        fullWidth
                        InputProps={{
                            type: "number",
                            inputProps: {
                                max: includeEquipment.NVALUE,
                                min: 0
                            }
                        }}
                        value={state}
                        onChange={event => {
                            var value = parseInt(event.target.value, 10);
                            if (value > includeEquipment.NVALUE) {
                                value = includeEquipment.NVALUE;
                            }
                            if (value < 0) {
                                value = 0;
                            }
                            setState(value);
                        }}
                    />
                    <Box></Box>
                </Box>
            </DialogContent>
            <DialogActions>
                <Button onClick={costJobsSpecIncludeCostEquipment}>{BUTTONS.OK}</Button>
                <Button onClick={() => handlePriorEditClose(null)}>{BUTTONS.CANCEL}</Button>
            </DialogActions>
        </Dialog>
    );
};

//Контроль свойств - Диалог включения станка в сменное задание
CostJobsSpecsInclude.propTypes = {
    includeEquipment: PropTypes.object.isRequired,
    setIncludeEquipment: PropTypes.func.isRequired,
    setCostJobsSpecs: PropTypes.func.isRequired,
    setEquipConfiguration: PropTypes.func.isRequired,
    includeEquipConfiguration: PropTypes.func.isRequired
};

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

//Таблица информации о строках сменного задания
const CostJobsSpecsDataGrid = ({ task, haveNote, fromAction }) => {
    //Собственное состояние - Включение в задание
    const [includeEquipment, setIncludeEquipment] = useState({ NFCJOBSSP: null, NEQCONFIG: null, NVALUE: 0 });

    //Собственное состояние - таблица данных сменных заданий
    const [costJobsSpecs, setCostJobsSpecs, issueCostJobsSpecs] = useCostJobsSpecs(task);

    //Собственное состояние - таблица рабочих центров
    const [equipConfiguration, setEquipConfiguration, includeEquipConfiguration, excludeEquipConfiguration] = useEquipConfiguration(task, fromAction);

    //При изменении состояния сортировки операций
    const costJobsSpecOrderChanged = ({ orders }) => setCostJobsSpecs(pv => ({ ...pv, orders: [...orders], pageNumber: 1, reload: true }));

    //При изменении количества отображаемых страниц операций
    const costJobsSpecPagesCountChanged = () => setCostJobsSpecs(pv => ({ ...pv, pageNumber: pv.pageNumber + 1, reload: true }));

    //При изменении состояния сортировки рабочих центров
    const costEquipmentOrderChanged = ({ orders }) => setEquipConfiguration(pv => ({ ...pv, orders: [...orders], pageNumber: 1, reload: true }));

    //При изменении количества отображаемых страниц рабочих центров
    const costEquipmentPagesCountChanged = () => setEquipConfiguration(pv => ({ ...pv, pageNumber: pv.pageNumber + 1, reload: true }));

    //При исключении станка из строки сменного задания
    const costJobsSpecExcludeCostEquipment = () => {
        //Делаем асинхронно, чтобы при ошибке ничего не обновлять
        const excludeAsync = async () => {
            //Исключаем станок из строки сменного задания
            try {
                await excludeEquipConfiguration({
                    NFCJOBSSP: costJobsSpecs.selectedRow.NRN
                });
                //Необходимо обновить данные
                setCostJobsSpecs(pv => ({ ...pv, selectedRow: {}, pageNumber: 1, reload: true }));
                setEquipConfiguration(pv => ({ ...pv, selectedRow: {}, pageNumber: 1, reload: true }));
            } catch (e) {
                throw new Error(e.message);
            }
        };
        //Исключаем станок асинхронно
        excludeAsync();
    };

    //Выдача задания операции
    const costJobsSpecIssue = () => {
        //Делаем асинхронно, чтобы при ошибке ничего не обновлять
        const issueAsync = async () => {
            //Включаем оборудование в операции
            try {
                await issueCostJobsSpecs({ NFCJOBS: task });
                //Необходимо обновить данные
                setCostJobsSpecs(pv => ({ ...pv, selectedRow: {}, pageNumber: 1, reload: true }));
                setEquipConfiguration(pv => ({ ...pv, selectedRow: {}, pageNumber: 1, reload: true }));
            } catch (e) {
                throw new Error(e.message);
            }
        };
        //Выдаем задание асинхронно
        issueAsync();
    };

    //При изменение состояния выбора
    const handleSelectChange = prms => {
        //Выбранный элемент
        let selectedRow = null;
        //Исходим от раздела
        switch (prms.SUNIT) {
            //Сменное задание
            case UNIT_COST_JOBS_SPECS:
                //Определяем это новое отмеченное сменное задание или сброс старого
                selectedRow = costJobsSpecs.selectedRow.NRN ? (costJobsSpecs.selectedRow.NRN === prms.NRN ? null : prms.NRN) : prms.NRN;
                //Актуализируем строки
                setCostJobsSpecs(pv => ({
                    ...pv,
                    selectedRow: selectedRow
                        ? { NRN: selectedRow, NEQCONFIG: prms.NEQCONFIG, NEQUIP_PLAN: prms.NEQUIP_PLAN, NQUANT_PLAN: prms.NQUANT_PLAN }
                        : { NRN: null, NEQCONFIG: null, NEQUIP_PLAN: null, NQUANT_PLAN: null }
                }));
                //Выходим
                break;
            //Рабочие центры
            case UNIT_COST_EQUIPMENT:
                //Определяем это новое отмеченное сменное задание или сброс старого
                selectedRow = equipConfiguration.selectedRow.NRN ? (equipConfiguration.selectedRow.NRN === prms.NRN ? null : prms.NRN) : prms.NRN;
                //Актуализируем строки
                setEquipConfiguration(pv => ({
                    ...pv,
                    selectedRow: selectedRow ? { NRN: selectedRow, BFULL_LOADED: prms.BFULL_LOADED } : { NRN: null, BFULL_LOADED: null }
                }));
                //Выходим
                break;
            default:
                return;
        }
    };

    //При открытии окна включения в задание
    const handleIncludeEquipmentOpen = () => {
        //Актуализируем строки
        setIncludeEquipment({
            NFCJOBSSP: costJobsSpecs.selectedRow.NRN,
            NEQCONFIG: equipConfiguration.selectedRow.NRN,
            NVALUE: costJobsSpecs.selectedRow.NQUANT_PLAN
        });
    };

    //Генерация содержимого
    return (
        <div style={STYLES.CONTAINER}>
            <Grid container spacing={2}>
                <Grid item sx={STYLES.JOBS_INFO} xs={6}>
                    <Typography sx={STYLES.TABLE_HEADER} variant={"h6"} color={"text.secondary"}>
                        Сменное задание
                    </Typography>
                    {costJobsSpecs.dataLoaded ? (
                        <>
                            <Box sx={STYLES.TABLE_BUTTONS}>
                                <Tooltip title={haveNote ? "Сменное задание имеет строку с примечанием" : null}>
                                    <Button variant="contained" size="small" disabled={haveNote} onClick={costJobsSpecIssue}>
                                        Выдать задания
                                    </Button>
                                </Tooltip>
                            </Box>
                            <Box sx={STYLES.TABLE}>
                                <P8PDataGrid
                                    {...P8P_DATA_GRID_CONFIG_PROPS}
                                    containerComponentProps={{ sx: STYLES.DATA_GRID_CONTAINER(costJobsSpecs.morePages), elevation: 1 }}
                                    columnsDef={costJobsSpecs.columnsDef}
                                    rows={costJobsSpecs.rows}
                                    size={P8P_DATA_GRID_SIZE.SMALL}
                                    morePages={costJobsSpecs.morePages}
                                    reloading={costJobsSpecs.reload}
                                    onOrderChanged={costJobsSpecOrderChanged}
                                    onPagesCountChanged={costJobsSpecPagesCountChanged}
                                    dataCellRender={prms =>
                                        dataCellRender({
                                            ...prms,
                                            handleSelectChange,
                                            sUnit: UNIT_COST_JOBS_SPECS,
                                            selectedRow: costJobsSpecs.selectedRow.NRN,
                                            selectedJobSpec: costJobsSpecs.selectedRow
                                        })
                                    }
                                    headCellRender={prms => headCellRender({ ...prms })}
                                    fixedHeader={true}
                                />
                            </Box>
                        </>
                    ) : null}
                </Grid>
                <Grid item sx={STYLES.EQUIPMENT_INFO} xs={6}>
                    <Typography sx={STYLES.TABLE_HEADER} variant={"h6"} color={"text.secondary"}>
                        Рабочие центры
                    </Typography>
                    {equipConfiguration.dataLoaded ? (
                        <>
                            <Box sx={STYLES.TABLE_BUTTONS}>
                                <Stack direction={"row"} spacing={1}>
                                    <Button
                                        variant="contained"
                                        size="small"
                                        disabled={
                                            !equipConfiguration.selectedRow.NRN ||
                                            !costJobsSpecs.selectedRow.NRN ||
                                            (equipConfiguration.selectedRow.NRN && equipConfiguration.selectedRow.BFULL_LOADED)
                                        }
                                        onClick={handleIncludeEquipmentOpen}
                                    >
                                        Включить в задание
                                    </Button>
                                    <Button
                                        variant="contained"
                                        size="small"
                                        disabled={!costJobsSpecs.selectedRow.NRN || !costJobsSpecs.selectedRow.NEQCONFIG}
                                        onClick={costJobsSpecExcludeCostEquipment}
                                    >
                                        Исключить из задания
                                    </Button>
                                </Stack>
                            </Box>
                            <Box sx={STYLES.TABLE}>
                                <P8PDataGrid
                                    {...P8P_DATA_GRID_CONFIG_PROPS}
                                    containerComponentProps={{ sx: STYLES.DATA_GRID_CONTAINER(equipConfiguration.morePages), elevation: 1 }}
                                    columnsDef={equipConfiguration.columnsDef}
                                    rows={equipConfiguration.rows}
                                    size={P8P_DATA_GRID_SIZE.SMALL}
                                    morePages={equipConfiguration.morePages}
                                    reloading={equipConfiguration.reload}
                                    onOrderChanged={costEquipmentOrderChanged}
                                    onPagesCountChanged={costEquipmentPagesCountChanged}
                                    dataCellRender={prms =>
                                        dataCellRender({
                                            ...prms,
                                            handleSelectChange,
                                            sUnit: UNIT_COST_EQUIPMENT,
                                            selectedRow: equipConfiguration.selectedRow.NRN,
                                            selectedJobSpec: costJobsSpecs.selectedRow
                                        })
                                    }
                                    headCellRender={prms => headCellRender({ ...prms })}
                                    fixedHeader={true}
                                />
                            </Box>
                        </>
                    ) : null}
                </Grid>
            </Grid>
            {includeEquipment.NFCJOBSSP && includeEquipment.NFCJOBSSP ? (
                <CostJobsSpecsInclude
                    includeEquipment={includeEquipment}
                    setIncludeEquipment={setIncludeEquipment}
                    setCostJobsSpecs={setCostJobsSpecs}
                    setEquipConfiguration={setEquipConfiguration}
                    includeEquipConfiguration={includeEquipConfiguration}
                />
            ) : null}
        </div>
    );
};

//Контроль свойств - Таблица информации о строках сменного задания
CostJobsSpecsDataGrid.propTypes = {
    task: PropTypes.number.isRequired,
    haveNote: PropTypes.bool.isRequired,
    fromAction: PropTypes.bool.isRequired
};

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

export { CostJobsSpecsDataGrid };
