/*
    Парус 8 - Панели мониторинга - ПУП - Работы проектов
    Панель мониторинга: Корневая панель работ проектов
*/
//---------------------
//Подключение библиотек
//---------------------
import React, { useContext, useState, useCallback, useEffect } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import {
    Drawer,
    Fab,
    Box,
    Grid,
    List,
    ListItemButton,
    ListItemText,
    ListItemIcon,
    Icon,
    Typography,
    Divider,
    ListItem,
    Button,
    Dialog,
    DialogContent,
    DialogActions,
    TextField,
    DialogTitle
} from "@mui/material"; //Интерфейсные элементы
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { formatDateJSONDateOnly } from "../../core/utils"; //Вспомогательные функции
import { P8P_GANTT_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { P8PGantt } from "../../components/p8p_gantt"; //Диаграмма Ганта
import { formatDateRF } from "../../core/utils"; //Вспомогательные функции
import { BUTTONS } from "../../../app.text"; //Текстовые ресурсы и константы
import { ResMon } from "./res_mon"; //Монитор ресурсов
import { taskAttributeRenderer } from "./layouts"; //Дополнительная разметка и вёрстка клиентских элементов
//---------
//Константы
//---------
//Высота диаграммы Ганта
const GANTT_HEIGHT = "75vh";
//Ширина диаграммы Ганта
const GANTT_WIDTH = "98vw";
//Стили
const STYLES = {
    PROJECTS_LIST_ITEM_NOJOBS: { backgroundColor: "#ff000045" },
    PROJECTS_LIST_ITEM_PRIMARY: { wordWrap: "break-word" },
    PROJECTS_LIST_ITEM_SECONDARY: { wordWrap: "break-word", fontSize: "0.5rem", textTransform: "uppercase" },
    PROJECTS_LIST_ITEM_SECONDARY_NOJOBS: { color: "red" },
    PROJECTS_LIST_ITEM_SECONDARY_NOEDIT: { color: "gray" },
    PROJECTS_LIST_ITEM_SECONDARY_CHANGED: { color: "green" },
    PROJECTS_BUTTON: { position: "absolute" },
    PROJECTS_DRAWER: { width: "250px", flexShrink: 0, [`& .MuiDrawer-paper`]: { width: "250px", boxSizing: "border-box" } },
    GANTT_CONTAINER: { height: GANTT_HEIGHT, width: GANTT_WIDTH },
    GANTT_TITLE: { paddingLeft: "100px", paddingRight: "120px" },
    PERIODS_BUTTON: { position: "absolute", right: "20px" },
    PERIODS_DRAWER: { width: "1200px", flexShrink: 0, [`& .MuiDrawer-paper`]: { width: "1200px", boxSizing: "border-box" } }
};
//Единицы измерения длительности
const DURATION_MEAS = {
    0: "День",
    1: "Неделя",
    2: "Декада",
    3: "Месяц",
    4: "Квартал",
    5: "Год"
};
//------------------------------------
//Вспомогательные функции и компоненты
//------------------------------------
//Диалог параметров инициализации панели
const InitDialog = ({ dateBegin, dateFact, onOk, onCancel }) => {
    //Собственное состояние - значения с-по
    const [values, setValues] = useState({ dateBegin: formatDateJSONDateOnly(dateBegin), dateFact: formatDateJSONDateOnly(dateFact) });
    //Отработка воода значения в фильтр
    const handleValueTextFieldChanged = e => setValues(prev => ({ ...prev, [e.target.name]: e.target.value }));
    //Генерация содержимого
    return (
        
    );
};
//Контроль свойств - Диалог параметров инициализации панели
InitDialog.propTypes = {
    dateBegin: PropTypes.instanceOf(Date).isRequired,
    dateFact: PropTypes.instanceOf(Date).isRequired,
    onOk: PropTypes.func,
    onCancel: PropTypes.func
};
//Список проектов
const ProjectsList = ({ projects = [], selectedProject, onClick } = {}) => {
    //Подключение к контексту сообщений
    const { InlineMsgErr } = useContext(MessagingСtx);
    //Генерация содержимого
    return projects.length > 0 ? (
        
            {projects.map(p => (
                 (onClick ? onClick(p) : null)}
                >
                    
                        
                            {p.NEDITABLE == 1 ? "edit" : "edit_off"}
                        
                    
                    {p.SNAME}}
                        secondary={
                            
                                {p.NJOBS == 1
                                    ? p.NEDITABLE == 1
                                        ? p.NCHANGED == 1
                                            ? "Изменён"
                                            : "Не изменён"
                                        : "Редактирование недоступно"
                                    : "Работы не определены"}
                            
                        }
                    />
                
            ))}
        
) : (
        
    );
};
//Контроль свойств - Список проектов
ProjectsList.propTypes = {
    projects: PropTypes.array,
    selectedProject: PropTypes.number,
    onClick: PropTypes.func
};
//-----------
//Тело модуля
//-----------
//Корневая панель работ проектов
const PrjJobs = () => {
    //Собственное состояние
    let [state, setState] = useState({
        needSave: false,
        showProjectsList: false,
        showPeriodsList: false,
        init: false,
        dateBegin: null,
        dateFact: null,
        durationMeas: null,
        labMeas: null,
        resourceStatus: null,
        ident: null,
        projects: [],
        projectsLoaded: false,
        selectedProjectJobsLoaded: false,
        selectedProject: null,
        selectedProjectDocRn: null,
        selectedProjectGanttDef: {},
        selectedProjectTasks: [],
        showInitDialog: false
    });
    //Подключение к контексту приложения
    const { pOnlineShowDocument } = useContext(ApplicationСtx);
    //Подключение к контексту сообщений
    const { InlineMsgInfo } = useContext(MessagingСtx);
    //Подключение к контексту взаимодействия с сервером
    const { executeStored } = useContext(BackEndСtx);
    //Загрузка списка проектов
    const loadProjects = useCallback(
        async (force = false) => {
            if (!state.projectsLoaded || force) {
                const data = await executeStored({
                    stored: "PKG_P8PANELS_PROJECTS.JB_PRJCTS_LIST",
                    args: { NIDENT: state.ident },
                    respArg: "COUT",
                    isArray: name => name === "XPROJECTS"
                });
                setState(pv => ({ ...pv, projectsLoaded: true, projects: [...(data?.XPROJECTS || [])] }));
            }
        },
        [executeStored, state.ident, state.projectsLoaded]
    );
    //Загрузка списка работ проекта
    const loadProjectJobs = useCallback(
        async (tasksOnly = false) => {
            const data = await executeStored({
                stored: "PKG_P8PANELS_PROJECTS.JB_JOBS_LIST",
                args: { NIDENT: state.ident, NPRN: state.selectedProject, NINCLUDE_DEF: tasksOnly === false ? 1 : 0 },
                attributeValueProcessor: (name, val) =>
                    name == "numb" ? undefined : ["start", "end"].includes(name) ? formatDateJSONDateOnly(val) : val,
                respArg: "COUT"
            });
            setState(pv => ({
                ...pv,
                selectedProjectJobsLoaded: true,
                selectedProjectGanttDef: tasksOnly === true ? { ...pv.selectedProjectGanttDef } : data.XGANTT_DEF ? { ...data.XGANTT_DEF } : {},
                selectedProjectTasks: [...data.XGANTT_TASKS]
            }));
        },
        [executeStored, state.ident, state.selectedProject]
    );
    //Изменение работы в графике
    const modifyJob = useCallback(
        async (job, dateFrom, dateTo, dateBegin, dateFact, durationMeas) => {
            let data = null;
            try {
                data = await executeStored({
                    stored: "PKG_P8PANELS_PROJECTS.JB_JOBS_MODIFY_PERIOD",
                    args: { NJB_JOBS: job, DDATE_FROM: dateFrom, DDATE_TO: dateTo, DBEGIN: dateBegin, DFACT: dateFact, NDURATION_MEAS: durationMeas }
                });
                if (data?.NRESOURCE_STATUS != -1) {
                    setState(pv => ({ ...pv, resourceStatus: data.NRESOURCE_STATUS, needSave: true }));
                    loadProjects(true);
                }
            } finally {
                loadProjectJobs(true);
            }
        },
        [executeStored, loadProjectJobs, loadProjects]
    );
    //Сохранение буфера балансировки в проекты
    const saveProjects = useCallback(async () => {
        const data = await executeStored({
            stored: "PKG_P8PANELS_PROJECTS.JB_SAVE",
            args: { NIDENT: state.ident },
            respArg: "COUT"
        });
        setState(pv => ({ ...pv, needSave: false, projects: [...(data?.XPROJECTS || [])] }));
    }, [executeStored, state.ident]);
    //Инициализация данных балансировки
    const initJobs = useCallback(async () => {
        if (!state.init) {
            const data = await executeStored({
                stored: "PKG_P8PANELS_PROJECTS.JB_INIT",
                args: {
                    DBEGIN: state.dateBegin ? state.dateBegin : null,
                    DFACT: state.dateFact ? state.dateFact : null,
                    NDURATION_MEAS: state.durationMeas,
                    SLAB_MEAS: state.labMeas,
                    NIDENT: state.ident
                }
            });
            setState(pv => ({
                ...pv,
                init: true,
                reInit: false,
                dateBegin: new Date(data.DBEGIN),
                dateFact: new Date(data.DFACT),
                durationMeas: data.NDURATION_MEAS,
                labMeas: data.SLAB_MEAS,
                resourceStatus: data.NRESOURCE_STATUS,
                ident: data.NIDENT
            }));
        }
    }, [state.init, state.dateBegin, state.dateFact, state.durationMeas, state.labMeas, state.ident, executeStored]);
    //Грузим список проектов при смене идентификатора процесса
    useEffect(() => {
        if (state.ident) loadProjects();
    }, [state.ident, loadProjects]);
    //При смене выбранного проекта
    useEffect(() => {
        if (state.selectedProject) loadProjectJobs(false);
    }, [state.selectedProject, loadProjectJobs]);
    //При изменении флага инициализации
    useEffect(() => {
        initJobs();
    }, [state.init, initJobs]);
    //Выбор проекта
    const selectPoject = (project, projectDocRn) => {
        setState(pv => ({
            ...pv,
            selectedProject: project,
            selectedProjectDocRn: projectDocRn,
            selectedProjectJobsLoaded: false,
            selectedProjectTasks: [],
            selectedProjectGanttDef: {},
            showProjectsList: false
        }));
    };
    //Сброс выбора проекта
    const unselectProject = () =>
        setState(pv => ({
            ...pv,
            selectedProjectJobsLoaded: false,
            selectedProject: null,
            selectedProjectDocRn: null,
            selectedProjectTasks: [],
            selectedProjectGanttDef: {},
            showProjectsList: false
        }));
    //Обработка нажатия на элемент в списке проектов
    const handleProjectClick = project => {
        if (state.selectedProject != project.NRN) selectPoject(project.NRN, project.NPROJECT);
        else unselectProject();
    };
    //Отработка нажатия на заголовок плана-графика
    const handleTitleClick = () =>
        state.selectedProjectDocRn ? pOnlineShowDocument({ unitCode: "Projects", document: state.selectedProjectDocRn }) : null;
    //Обработка измненения сроков задачи в диаграмме Гантта
    const handleTaskDatesChange = ({ task, start, end, isMain }) => {
        if (isMain) modifyJob(task.rn, new Date(start), new Date(end), new Date(state.dateBegin), new Date(state.dateFact), state.durationMeas);
    };
    //Отработка нажатия на отображения диалога параметров инициализации панели
    const handleShowInitDialogClick = () => setState(pv => ({ ...pv, showInitDialog: true }));
    //Отработка нажатия на "ОК" в диалоге параметров инициализации панели
    const handleOKInitDialogClick = values =>
        setState(pv => ({ ...pv, dateBegin: values.dateBegin, dateFact: values.dateFact, showInitDialog: false, init: false }));
    //Отработка нажатия на "Отмена" в диалоге параметров инициализации панели
    const handleCancelInitDialogClick = () => setState(pv => ({ ...pv, showInitDialog: false }));
    //Обработка нажатия на сохранение данных в проект
    const handleSaveToProjectsClick = () => saveProjects();
    //Обработка нажатия на проект в таблице детализации трудоёмкости по плану-графику монитора ресурсов
    const handlePlanJobsDtlProjectClick = ({ sender }) => {
        setState(pv => ({ ...pv, showPeriodsList: false }));
        if (state.selectedProject != sender.NJB_PRJCTS) selectPoject(sender.NJB_PRJCTS, sender.NPROJECT);
    };
    //Генерация содержимого
    return (
        
            {state.showInitDialog ? (
                
            ) : null}
             setState(pv => ({ ...pv, showProjectsList: !pv.showProjectsList }))}>
                Проекты
                {state.needSave ? (
                    <>
                          
                        save
                    >
                ) : null}
            
             setState(pv => ({ ...pv, showProjectsList: false }))}
                sx={STYLES.PROJECTS_DRAWER}
            >
                {state.projectsLoaded ? (
                    <>
                            
                                
                                            Начало: 
                                            {formatDateRF(state.dateBegin)}
                                            
                                            Факт на: 
                                            {formatDateRF(state.dateFact)}
                                            
                                            Длительность: 
                                            {DURATION_MEAS[state.durationMeas]}
                                            
                                            Трудоёмкость: 
                                            {state.labMeas}
                                        >
                                    }
                                />
                            
                            
                                
                            
                        
{state.needSave ? (
                            <>
                                    
                                        
                                    
                                
>
                        ) : null}
                        
                    >
                ) : null}
            
             setState(pv => ({ ...pv, showPeriodsList: !pv.showPeriodsList }))}>
                Ресурсы
                {[0, 1].includes(state.resourceStatus) ? (
                    <>
                          
                        {state.resourceStatus === 0 ? "done" : "error"}
                    >
                ) : null}
            
             setState(pv => ({ ...pv, showPeriodsList: false }))}
                sx={STYLES.PERIODS_DRAWER}
            >
                {state.ident ?  : null}
            
            {state.init == true ? (
                
                    
                        {state.selectedProjectJobsLoaded ? (
                            
                                
                            
                        ) : !state.selectedProject ? (
                            
                        ) : null}
                    
                
            ) : null}
        
    );
};
//----------------
//Интерфейс модуля
//----------------
export { PrjJobs };