/*
    Парус 8 - Панели мониторинга - УДП - Доски задач
    Дополнительная разметка и вёрстка клиентских элементов
*/

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

//Перечисление "Состояние события"
export const EVENT_STATES = Object.freeze({ 0: "Все", 1: "Не аннулированные", 2: "Аннулированные" });

//Допустимые значение поля сортировки
export const sortAttrs = [
    { id: "SEVNSTAT_CODE", descr: "Мнемокод статуса" },
    { id: "SEVNSTAT_NAME", descr: "Наименование статуса" },
    { id: "SEVPOINT_DESCR", descr: "Описание точки маршрута" }
];

//Допустимые значения направления сортировки
export const sortDest = [];
sortDest[-1] = "desc";
sortDest[1] = "asc";

//Цвета статусов
export const COLORS = [
    "mediumSlateBlue",
    "lightSalmon",
    "fireBrick",
    "orange",
    "gold",
    "limeGreen",
    "yellowGreen",
    "mediumAquaMarine",
    "paleTurquoise",
    "steelBlue",
    "skyBlue",
    "tan"
];

//Перечисление "Цвет задачи"
export const TASK_COLORS = Object.freeze({ EXPIRED: "#ff0000", EXPIRES_SOON: "#ffdf00", LINKED: "#1e90ff" });

//Перечисление Доп. свойства "Значение по умолчанию"
export const DP_DEFAULT_VALUE = Object.freeze({ 0: "SDEFAULT_STR", 1: "NDEFAULT_NUM", 2: "DDEFAULT_DATE", 3: "NDEFAULT_NUM" });
//Перечисление Доп. свойства "Префикс формата данных"
export const DP_TYPE_PREFIX = Object.freeze({ 0: "S", 1: "N", 2: "D", 3: "N" });
//Перечисление Доп. свойства "Входящее значение дополнительного словаря"
export const DP_IN_VALUE = Object.freeze({ 0: "pos_str_value", 1: "pos_num_value", 2: "pos_date_value", 3: "pos_num_value" });
//Перечисление Доп. свойства "Исходящее значение дополнительного словаря"
export const DP_RETURN_VALUE = Object.freeze({ 0: "str_value", 1: "num_value", 2: "date_value", 3: "num_value" });

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

//Формирование массива из 0, 1 и более элементов
export const makeArray = arr => {
    return arr ? (arr.length ? arr : [arr]) : [];
};

//Конвертация формата HEX в формат RGB
const convertHexToRGB = hex => {
    let r = parseInt(hex.slice(1, 3), 16);
    let g = parseInt(hex.slice(3, 5), 16);
    let b = parseInt(hex.slice(5, 7), 16);
    let a = 0.5;
    r = Math.round((a * (r / 255) + a * (255 / 255)) * 255);
    g = Math.round((a * (g / 255) + a * (255 / 255)) * 255);
    b = Math.round((a * (b / 255) + a * (255 / 255)) * 255);
    return "rgb(" + r + ", " + g + ", " + b + ")";
};

//Считывание заливки события по условию
export const getTaskBgColorByRule = (task, colorRule) => {
    //Исходя из типа определяем наименование и возвращаем цвет заливки
    switch (colorRule.STYPE) {
        case "number":
            return (!colorRule.fromValue || Number(task.docProps[`N${colorRule.SFIELD}`]) >= Number(colorRule.fromValue)) &&
                (!colorRule.toValue || Number(task.docProps[`N${colorRule.SFIELD}`]) <= Number(colorRule.toValue))
                ? convertHexToRGB(colorRule.SCOLOR)
                : null;
        default:
            return task.docProps[`S${colorRule.SFIELD}`] == colorRule.fromValue ? convertHexToRGB(colorRule.SCOLOR) : null;
    }
};

//Индикация истечения срока отработки события
export const getTaskExpiredColor = task => {
    //Определяем текущую дату
    let sysDate = new Date();
    //Определяем дату истечения срока события
    let expireDate = task.dExpireDate ? new Date(task.dExpireDate) : null;
    //Если дата истечения срока определена
    if (expireDate) {
        //Определяем разницу между датами
        let daysDiff = ((expireDate.getTime() - sysDate.getTime()) / (1000 * 60 * 60 * 24)).toFixed(2);
        //Если разница меньше 0 - срок истечен
        if (daysDiff < 0) return TASK_COLORS.EXPIRED;
        //Если разница меньше 4 - скоро истечет
        if (daysDiff < 4) return TASK_COLORS.EXPIRES_SOON;
    }
    return null;
};

//Цвет из hsl формата в rgba формат
const convertHslToRgba = (h, s, l) => {
    s /= 100;
    l /= 100;
    const k = n => (n + h / 30) % 12;
    const a = s * Math.min(l, 1 - l);
    const f = n => l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
    return `rgba(${Math.floor(255 * f(0))},${Math.floor(255 * f(8))},${Math.floor(255 * f(4))},0.3)`;
};

//Формирование случайного цвета
export const getRandomColor = index => {
    const hue = index * 137.508;
    return convertHslToRgba(hue, 50, 70);
};

//Формат дополнительного свойства типа число (длина, точность)
const formatRegExpNum = (width, precision) =>
    new RegExp("^(\\d{1," + (width - precision) + "}" + (precision > 0 ? "((\\.|,)\\d{1," + precision + "})?" : "") + ")?$");

//Формат дополнительного свойства типа строка (длина)
const formatRegExpStr = length => new RegExp("^.{0," + length + "}$");

//Проверка валидности числа
const isValidNum = (width, precision, value) => {
    return formatRegExpNum(width, precision).test(value);
};

//Проверка валидности строки
const isValidStr = (length, value) => {
    return formatRegExpStr(length).test(value);
};

//Признак ошибки валидации
export const validationError = (value = "", format, numWidth, numPrecision, strLength) => {
    //Исходим от формата
    switch (format) {
        //Проверка строки
        case 0:
            return isValidStr(strLength, value);
        //Проверка числа
        case 1:
            return isValidNum(numWidth, numPrecision, value);
        //Остальное не проверяем
        default:
            return true;
    }
};

//Конвертация времени в привычный формат
export const formatSqlDate = timeStamp => {
    //Если есть разделитель
    if (timeStamp.indexOf(".") !== -1) {
        //Определяем секунды
        let seconds = 24 * 60 * 60 * timeStamp;
        //Определяем часы
        const hours = Math.trunc(seconds / (60 * 60));
        //Переопределяем секунды
        seconds = seconds % (60 * 60);
        //Определяем минуты
        const minutes = Math.trunc(seconds / 60);
        //Определяем остаток секунд
        seconds = Math.round(seconds % 60);
        //Форматируем
        const formattedTime = ("0" + hours).slice(-2) + ":" + ("0" + minutes).slice(-2) + ":" + ("0" + seconds).slice(-2);
        //Возвращаем результат
        return formattedTime;
    }
    return timeStamp;
};

//Считывание значений из локального хранилища
export const getLocalStorageValue = (sName, defaultValue = null) => localStorage.getItem(sName) || defaultValue;

//Форматирование фильтра в массив для отбора
export const convertFilterValuesToArray = filterValues => {
    //Инициализируем значение "с" состояния ("Все", "Не аннулированные" - 0, "Аннулированые" - 1)
    let nClosedFrom = filterValues.sState ? ([EVENT_STATES[0], EVENT_STATES[1]].includes(filterValues.sState) ? 0 : 1) : 0;
    //Инициализируем значение "по" состояния ("Все", "Аннулированные" - 1, "Не аннулированные" - 0)
    let nClosedTo = filterValues.sState ? ([EVENT_STATES[0], EVENT_STATES[2]].includes(filterValues.sState) ? 1 : 0) : 0;
    //Формируем массив значений фильтра
    let filterValuesArray = [
        { name: "NCLOSED", from: nClosedFrom, to: nClosedTo },
        { name: "SEVTYPE_CODE", from: filterValues.sType, to: null },
        { name: "NCRN", from: filterValues.sCrnRnList, to: null },
        { name: "SSEND_PERSON", from: filterValues.sSendPerson, to: null },
        { name: "SSEND_DIVISION", from: filterValues.sSendDivision, to: null },
        { name: "SSEND_USRGRP", from: filterValues.sSendUsrGrp, to: null },
        { name: "NLINKED_RN", from: filterValues.sDocLink, to: null }
    ];
    return filterValuesArray;
};

//Формирование массива действий карточки события
export const makeCardActionsArray = (onEdit, onEditClient, onDelete, onStateChange, onReturn, onSend, onNotesOpen, onFileLinksOpen, onMove) => {
    //Формируем список действий карточки
    return [
        {
            method: "EDIT",
            name: "Исправить",
            icon: "edit",
            visible: false,
            delimiter: false,
            tasksReload: false,
            needAccountsReload: false,
            disableClosed: false,
            func: onEdit
        },
        {
            method: "EDIT_CLIENT",
            name: "Исправить в разделе",
            icon: "edit_note",
            visible: true,
            delimiter: false,
            tasksReload: false,
            needAccountsReload: false,
            disableClosed: false,
            func: onEditClient
        },
        {
            method: "MOVE",
            name: "Переместить",
            icon: "drive_file_move",
            visible: true,
            delimiter: false,
            tasksReload: true,
            needAccountsReload: false,
            disableClosed: false,
            func: onMove
        },
        {
            method: "DELETE",
            name: "Удалить",
            icon: "delete",
            visible: true,
            delimiter: true,
            tasksReload: true,
            needAccountsReload: false,
            disableClosed: false,
            func: onDelete
        },
        {
            method: "TASK_STATE_CHANGE",
            name: "Перейти",
            icon: "turn_right",
            visible: true,
            delimiter: false,
            tasksReload: true,
            needAccountsReload: true,
            disableClosed: true,
            func: onStateChange
        },
        {
            method: "TASK_RETURN",
            name: "Выполнить возврат",
            icon: "turn_left",
            visible: true,
            delimiter: false,
            tasksReload: true,
            needAccountsReload: true,
            disableClosed: true,
            func: onReturn
        },
        {
            method: "TASK_SEND",
            name: "Направить",
            icon: "send",
            visible: true,
            delimiter: true,
            tasksReload: true,
            needAccountsReload: true,
            disableClosed: true,
            func: onSend
        },
        {
            method: "NOTES",
            name: "Примечания",
            icon: "event_note",
            visible: true,
            delimiter: true,
            tasksReload: false,
            needAccountsReload: false,
            disableClosed: false,
            func: onNotesOpen
        },
        {
            method: "FILE_LINKS",
            name: "Присоединенные документы",
            icon: "attach_file",
            visible: true,
            delimiter: false,
            tasksReload: false,
            needAccountsReload: false,
            disableClosed: false,
            func: onFileLinksOpen
        }
    ];
};
