'use strict';
var __importDefault =
  (this && this.__importDefault) ||
  function (mod) {
    return mod && mod.__esModule ? mod : { default: mod };
  };
Object.defineProperty(exports, '__esModule', { value: true });
exports.createConfigPageRecursion = void 0;
const saveConfigPage_1 = __importDefault(require('../saveConfigPage/saveConfigPage'));
const createForm_1 = __importDefault(require('./createForm'));
const styleNames_1 = __importDefault(require('../../styleNames'));
const utils_1 = require('../../utils');
const index_1 = require('../../../index');
const helpers_1 = require('./helpers/helpers');
let newFields;
let mainConfig;
const paths = {};
// функция создаёт HTML страницу конфига
const createConfigPageEntry = (props) => {
  newFields = props.newFields;
  mainConfig = props.config;
  paths.local = props.pathToSaveLocalConfig;
  paths.default = props.pathToSaveDefaultConfig;
  const wrapper = (0, utils_1.createElement)('form', {
    className: styleNames_1.default.wrapper,
    onsubmit: (e) => e.preventDefault(),
  });
  wrapper.dataset.isChanged = `${props.isConfigChanged}`;
  const heading = (0, utils_1.createElement)(
    'div',
    { className: styleNames_1.default.heading },
    wrapper,
    (0, utils_1.createElement)('p', { innerHTML: 'Конфиг' }),
  );
  const configEntryLayer = (0, utils_1.createElement)(
    'div',
    {
      className: `${styleNames_1.default.node} ${styleNames_1.default.highestNode}`,
    },
    wrapper,
  );
  (0, helpers_1.createConfigControlButton)({
    type: 'collapseAll',
    parent: heading,
    onClick: () =>
      configEntryLayer
        .querySelectorAll('details[open]')
        .forEach((details) => (details.open = false)),
  });
  (0, helpers_1.createConfigControlButton)({
    type: 'add',
    parent: heading,
    onClick: () =>
      configEntryLayer.appendChild(
        (0, createForm_1.default)({ targetNode: configEntryLayer }),
      ),
  });
  mainConfig.HTML = wrapper;
  createConfigPageRecursion(mainConfig.united, configEntryLayer);
  createBottomButtons(wrapper);
  (0, utils_1.emit)('info', 'страница с конфигом создана');
  return wrapper;
};
// рекурсивное создание HTML-страницы
const createConfigPageRecursion = (config, parentNode) => {
  for (const key in config) {
    const isSection =
      typeof config[key].value === 'object' && !Array.isArray(config[key].value);
    if (isSection) {
      const container = createDetailsField(key, config[key]);
      parentNode.appendChild(container);
      createConfigPageRecursion(config[key].value, container);
    } else {
      createInputField(key, config[key], parentNode);
    }
  }
  // группировка по типу элемента(раздел, инпут) и сортировка по алфавиту
  const children = Array.from(parentNode.children);
  parentNode.innerHTML = '';
  const details = [],
    divs = [];
  // группировка
  children.forEach((child) => {
    if (child.classList.contains(styleNames_1.default.nodeDescription)) {
      parentNode.appendChild(child);
      return;
    }
    if (child.classList.contains(styleNames_1.default.inputNode)) {
      divs.push(child);
    } else {
      details.push(child);
    }
  });
  // сортировка
  divs.sort((a, b) => (0, helpers_1.sortComparator)(a.textContent, b.textContent));
  details.sort((a, b) =>
    (0, helpers_1.sortComparator)(a.children[0].textContent, b.children[0].textContent),
  );
  parentNode.append(...divs);
  parentNode.append(...details);
};
exports.createConfigPageRecursion = createConfigPageRecursion;
// создание раздела
const createDetailsField = (key, config) => {
  const container = (0, utils_1.createElement)('details', {
    className: styleNames_1.default.node,
  });
  const description = (0, utils_1.createElement)(
    'summary',
    {
      className: styleNames_1.default.nodeDescription,
      innerHTML: `<span>${config.name}</span>`,
    },
    container,
  );
  description.dataset.key = key;
  // выделение, если поле новое(index.ts: 29)
  if (newFields.includes(key)) {
    description.classList.add(styleNames_1.default.newNode);
    const removeNew = () => {
      description.classList.remove(styleNames_1.default.newNode);
      description.removeEventListener('click', removeNew);
    };
    description.addEventListener('click', removeNew);
  }
  (0, helpers_1.createConfigControlButton)({
    type: 'add',
    parent: description,
    onClick: () =>
      container.appendChild((0, createForm_1.default)({ targetNode: container })),
  });
  (0, helpers_1.createConfigControlButton)({
    type: 'edit',
    parent: description,
    onClick: () => handleDetailsEditButtonClick(container, { [key]: { ...config } }),
  });
  (0, helpers_1.createConfigControlButton)({
    type: 'delete',
    parent: description,
    onClick: () =>
      (0, helpers_1.createSubmitDeleteModal)(mainConfig.HTML, description.parentElement),
  });
  return container;
};
// обработчик клика на кнопку редактирования раздела
const handleDetailsEditButtonClick = (container, config) => {
  const key = Object.keys(config)[0];
  const form = (0, createForm_1.default)({
    targetNode: container,
    oldValues: {
      key,
      name: config[key].name,
      value: config[key].value,
      type: config[key].type,
      step: config[key].step,
    },
  });
  container.replaceWith(form);
};
// создание инпута
const createInputField = (key, config, parentSection) => {
  const container = (0, utils_1.createElement)(
    'div',
    { className: styleNames_1.default.node },
    parentSection,
  );
  const description = (0, utils_1.createElement)(
    'p',
    { className: styleNames_1.default.nodeDescription },
    container,
  );
  description.dataset.key = key;
  (0, utils_1.createElement)(
    'span',
    { innerHTML: config.name, className: styleNames_1.default.nodeName },
    description,
  );
  // выделение поля
  if (newFields.includes(key)) {
    description.classList.add(styleNames_1.default.newNode);
    const removeNew = () => {
      description.classList.remove(styleNames_1.default.newNode);
      description.removeEventListener('click', removeNew);
    };
    description.addEventListener('click', removeNew);
  }
  let valueInput = createValueInput(config, key, container);
  (0, helpers_1.createConfigControlButton)({
    type: 'edit',
    parent: description,
    onClick: () => handleInputEditButtonClick(valueInput, container, key, config),
  });
  (0, helpers_1.createConfigControlButton)({
    type: 'delete',
    parent: description,
    onClick: () =>
      (0, helpers_1.createSubmitDeleteModal)(mainConfig.HTML, description.parentElement),
  });
  container.classList.add(styleNames_1.default.inputNode);
};
// создание инпута
const createValueInput = (config, key, parentContainer) => {
  let valueInput;
  const description = parentContainer.querySelector(
    `.${styleNames_1.default.nodeDescription}`,
  );
  const parentSection = parentContainer.parentElement;
  switch (typeof config.value) {
    case 'boolean':
      valueInput = (0, utils_1.createElement)(
        'input',
        {
          type: 'checkbox',
          checked: config.value,
          onchange: () => (mainConfig.HTML.dataset.isChanged = 'true'),
        },
        parentContainer,
      );
      description.querySelector(`.${styleNames_1.default.nodeName}`).onclick = () =>
        valueInput.click();
      break;
    case 'number':
      valueInput = (0, utils_1.createElement)(
        'input',
        {
          type: 'number',
          value: config.value.toString(),
          step: config.step,
          onchange: () => (mainConfig.HTML.dataset.isChanged = 'true'),
        },
        parentContainer,
      );
      (0, utils_1.createElement)(
        'span',
        {
          innerHTML: ` (${config.type === 'float' ? 'дробное' : 'целое'}  число)`,
          className: styleNames_1.default.nodeInputType,
        },
        description,
      );
      description.querySelector(`.${styleNames_1.default.nodeName}`).onclick = () =>
        valueInput.focus();
      break;
    // в данном случае это массив, т.к. все поля со значением value типа "объект/не массив" были отсеяны в функции createConfigPageRecursion
    case 'object':
      valueInput = (0, utils_1.createElement)('select', null, parentContainer);
      // для камер нужно ставить уникальный наблюдатель за значением другого инпута камер
      if (key === 'selected_camera') {
        valueInput.dataset.key =
          parentSection === null || parentSection === void 0
            ? void 0
            : parentSection.getElementsByTagName('summary')[0].dataset.key;
        valueInput.onchange = () =>
          handleCameraSelectChange(
            mainConfig.HTML,
            valueInput.value,
            valueInput.dataset.key,
          );
      } else {
        valueInput.onchange = () => (mainConfig.HTML.dataset.isChanged = 'true');
      }
      config.value.forEach((opt) =>
        (0, utils_1.createElement)(
          'option',
          {
            textContent: opt.name,
            value: opt.value,
            selected: opt.chosen,
            disabled: opt === null || opt === void 0 ? void 0 : opt.disabled,
          },
          valueInput,
        ),
      );
      break;
    // default также отвечает за текстовый инпут
    default: {
      valueInput = (0, utils_1.createElement)(
        'input',
        {
          type: 'text',
          value: config.value,
          onchange: () => (mainConfig.HTML.dataset.isChanged = 'true'),
        },
        parentContainer,
      );
      (0, utils_1.createElement)(
        'span',
        { innerHTML: ' (текст)', className: styleNames_1.default.nodeInputType },
        description,
      );
      description.querySelector(`.${styleNames_1.default.nodeName}`).onclick = () =>
        valueInput.focus();
    }
  }
  return valueInput;
};
// проверяет значение другого инпута камер и обнуляет его, если оно совпадает с введённым
const handleCameraSelectChange = (configHTML, currentInputValue, currentInputKey) => {
  const anotherCameraSelect = Array.from(document.getElementsByTagName('select')).find(
    (s) => s.dataset.key && s.dataset.key !== currentInputKey,
  );
  if (
    (anotherCameraSelect === null || anotherCameraSelect === void 0
      ? void 0
      : anotherCameraSelect.value) === currentInputValue &&
    currentInputValue !== 'none'
  ) {
    anotherCameraSelect.value = 'none';
  }
  configHTML.dataset.isChanged = 'true';
};
// обработчик клика на кнопку изменения инпута
const handleInputEditButtonClick = (valueInput, parent, key, config) => {
  let value;
  // находим значение инпута
  if (valueInput.nodeName === 'SELECT') {
    value = Array.from(valueInput.options);
  } else {
    switch (valueInput.type) {
      case 'number': {
        value = +valueInput.value.replace(',', '.');
        break;
      }
      case 'checkbox': {
        value = valueInput.checked;
        break;
      }
      default:
        value = valueInput.value;
    }
  }
  // форма создания/изменения поля
  const form = (0, createForm_1.default)({
    targetNode: parent,
    oldValues: {
      key,
      name: config.name,
      value,
      step: config === null || config === void 0 ? void 0 : config.step,
      type: config === null || config === void 0 ? void 0 : config.type,
    },
  });
  parent.replaceWith(form);
};
// создаёт кнопки "сохранить" и "сбросить изменения" внизу экрана
const createBottomButtons = (parentNode) => {
  const buttonContainer = (0, utils_1.createElement)(
    'div',
    { className: styleNames_1.default.bottomButtonsContainer },
    parentNode,
  );
  (0, utils_1.createElement)(
    'button',
    {
      className: styleNames_1.default.bottomButton,
      textContent: 'Сохранить изменения',
      onclick: () => {
        if (parentNode.checkValidity()) {
          const newConfig = (0, saveConfigPage_1.default)({
            config: mainConfig,
            pathToSaveLocalConfig: paths.local,
            pathToSaveDefaultConfig: paths.default,
          });
          if (newConfig) {
            mainConfig.united = newConfig;
          }
        } else {
          (0, helpers_1.showInvalidInputs)(parentNode);
        }
      },
    },
    buttonContainer,
  );
  (0, utils_1.createElement)(
    'button',
    {
      className: styleNames_1.default.bottomButton,
      textContent: 'Сбросить изменения',
      onclick: index_1.close,
    },
    buttonContainer,
  );
};
exports.default = createConfigPageEntry;
//# sourceMappingURL=createConfigPage.js.map
