'use strict';
var __importDefault =
  (this && this.__importDefault) ||
  function (mod) {
    return mod && mod.__esModule ? mod : { default: mod };
  };
Object.defineProperty(exports, '__esModule', { value: true });
const styleNames_1 = __importDefault(require('../../styleNames'));
const utils_1 = require('../../utils');
const createConfigPage_1 = require('./createConfigPage');
const helpers_1 = require('./helpers/helpers');
const optionValues = [
  { name: 'текст', value: 'text', selected: true },
  { name: 'целое число', value: 'integer' },
  { name: 'дробное число', value: 'float' },
  { name: 'логическое значение', value: 'checkbox' },
  { name: 'список вариантов', value: 'select' },
  { name: 'раздел', value: 'details' },
];
let isCreatedSection = false;
let newSection; // хранит в себе самую первую созданную секцию
let oldValues;
let targetNode;
// функция создаёт форму создания/изменения поля
const createForm = (props) => {
  oldValues = props.oldValues;
  targetNode = props.targetNode;
  // по наличию oldValues определяется, создание
  if (!oldValues) {
    targetNode.open = true;
  }
  const form = (0, utils_1.createElement)('form', {
    className: styleNames_1.default.form,
  });
  window.setTimeout(() => document.addEventListener('click', removeForm));
  const nameInput = createInput(
    'Имя поля',
    (oldValues === null || oldValues === void 0 ? void 0 : oldValues.name) || '',
    styleNames_1.default.formNameInput,
    form,
  );
  window.setTimeout(() => nameInput.focus());
  const keyInput = createInput(
    'Ключ поля',
    (oldValues === null || oldValues === void 0 ? void 0 : oldValues.key) || '',
    styleNames_1.default.formKeyInput,
    form,
  );
  keyInput.pattern = '[0-9a-zA-Z-_]*';
  const valueTypeInputWrapper = (0, utils_1.createElement)('div', null, form);
  (0, utils_1.createElement)(
    'span',
    { innerHTML: 'Тип значения:' },
    valueTypeInputWrapper,
  );
  const options = optionValues.map((opt) =>
    (0, utils_1.createElement)('option', {
      innerHTML: opt.name,
      id: `c_opt_${opt.value}`,
      value: opt.value,
      selected: opt.selected,
    }),
  );
  const valueInputTypeSelect = (0, utils_1.createElement)(
    'select',
    { className: styleNames_1.default.formValueTypeInput },
    valueTypeInputWrapper,
    options,
  );
  let valueInput = createInput(
    'Значение поля',
    '',
    styleNames_1.default.formValueInput,
    form,
  );
  valueInputTypeSelect.onchange = (e) => {
    valueInput = handleValueInputTypeSelectChange(e, form, valueInput);
  };
  if (oldValues) {
    fillForm(oldValues, form, valueInputTypeSelect, valueInput);
  }
  (0, utils_1.createElement)(
    'button',
    {
      className: styleNames_1.default.formSubmitButton,
      textContent: 'Сохранить',
      type: 'button',
      onclick: () => handleSaveButtonClick(form, oldValues),
    },
    form,
  );
  return form;
};
// заполняет форму значениями из oldValues
const fillForm = (oldValues, form, valueInputTypeSelect, valueInput) => {
  let valueInputType;
  switch (typeof oldValues.value) {
    case 'object':
      if (Array.isArray(oldValues.value)) {
        valueInputType = 'select';
        const newValueInput = createOptionsForm(oldValues.value);
        valueInput.replaceWith(newValueInput);
        valueInput = newValueInput;
      } else {
        valueInputType = 'details';
        valueInput.disabled = true;
        valueInput.value = 'объект';
        valueInput.type = 'text';
      }
      break;
    case 'boolean':
    case 'number':
    case 'string':
      const input = targetNode.querySelector('input');
      valueInput.type = input.type;
      valueInput.value = `${oldValues.value}`;
      valueInputType = input.type;
      if (input.type === 'number') {
        valueInputType = oldValues.type;
        valueInput.step = input.step;
        const stepInput = createInput(
          'Шаг для значения',
          input.step,
          styleNames_1.default.formStepInput,
        );
        stepInput.onchange = () => (valueInput.step = stepInput.value.replace(',', '.'));
        stepInput.pattern =
          valueInputType === 'float' ? '([0]*[,.]{0,1}[0]*)?1([0]*)?' : '1([0]*)?';
        form.insertBefore(stepInput.parentElement, valueInput.parentElement);
      } else if (input.type === 'checkbox') {
        valueInput.checked = !!oldValues.value;
      }
      break;
  }
  const selectedOption = valueInputTypeSelect.options.namedItem(
    `c_opt_${valueInputType}`,
  );
  if (selectedOption) {
    valueInputTypeSelect.options[0].selected = false;
    selectedOption.selected = true;
  }
};
// обработчик изменения селекта
const handleValueInputTypeSelectChange = (e, form, valueInput) => {
  var _a, _b;
  const valueInputTypeSelect = e.currentTarget;
  const valueInputType = valueInputTypeSelect.value;
  (_b =
    (_a = form.querySelector(`.${styleNames_1.default.formStepInput}`)) === null ||
    _a === void 0
      ? void 0
      : _a.parentElement) === null || _b === void 0
    ? void 0
    : _b.remove();
  if (!newSection) {
    isCreatedSection = valueInputType === 'details';
  } else if (valueInputType !== 'details') {
    newSection = null;
    isCreatedSection = false;
  }
  // создаём новый инпут
  let newValueInput;
  switch (valueInputType) {
    case 'select':
      newValueInput = createOptionsForm();
      break;
    case 'details':
      newValueInput = (0, utils_1.createElement)('div', {
        innerHTML:
          'Вы перейдёте к созданию дочернего поля,<br /> как только завершите создание текущего.',
      });
      break;
    case 'float':
    case 'integer':
      newValueInput = (0, utils_1.createElement)('input', {
        type: 'number',
        className: styleNames_1.default.formValueInput,
        required: true,
        step: valueInputType === 'float' ? '0.1' : '1',
      });
      if (valueInput.nodeName === 'INPUT' && valueInput.type === 'number') {
        const oldInputValue = valueInput.value;
        newValueInput.value =
          valueInputType === 'integer'
            ? Math.round(+oldInputValue).toString()
            : oldInputValue;
      }
      const stepInput = createInput(
        'Шаг для значения',
        valueInputType === 'float' ? '0.1' : '1',
        styleNames_1.default.formStepInput,
      );
      stepInput.onchange = () => (newValueInput.step = stepInput.value.replace(',', '.'));
      stepInput.pattern =
        valueInputType === 'float' ? '([0]*[,.]{0,1}[0]*)?1([0]*)?' : '1([0]*)?';
      form.insertBefore(stepInput.parentElement, valueInput.parentElement);
      break;
    case 'text':
      newValueInput = (0, utils_1.createElement)('input', {
        type: 'text',
        className: styleNames_1.default.formValueInput,
        required: true,
      });
      if (valueInput.nodeName === 'INPUT' && valueInput.type === 'number') {
        newValueInput.value = valueInput.value;
      }
      break;
    case 'checkbox':
      newValueInput = (0, utils_1.createElement)('input', {
        type: 'checkbox',
        className: styleNames_1.default.formValueInput,
      });
      break;
  }
  valueInput.replaceWith(newValueInput);
  window.setTimeout(() => newValueInput.focus());
  return newValueInput;
};
// обработчик клика на кнопку сохранения формы
const handleSaveButtonClick = (form, oldValues) => {
  var _a;
  const keyInput = form.querySelector(`.${styleNames_1.default.formKeyInput}`);
  const nameInput = form.querySelector(`.${styleNames_1.default.formNameInput}`);
  const valueInput = form.querySelector(`.${styleNames_1.default.formValueInput}`);
  const valueInputTypeSelect = form.querySelector(
    `.${styleNames_1.default.formValueTypeInput}`,
  );
  if (!form.checkValidity()) {
    form.reportValidity();
    return;
  }
  const key = keyInput.value.replace(/[ ]+/g, '_'),
    name = nameInput.value,
    target = oldValues && form.parentElement ? form.parentElement : targetNode,
    isKeyUsed = Array.from(target.children).find((node) => {
      return node.nodeName !== 'SUMMARY' && node.querySelector(`[data-key="${key}"]`);
    });
  if (isKeyUsed) {
    setError('в этом разделе уже есть поле с таким ключём');
    return;
  }
  let value,
    step = '';
  const valueInputType = valueInputTypeSelect.value;
  switch (valueInputType) {
    case 'select': {
      let options = Array.from(
        form.getElementsByClassName(styleNames_1.default.optionsFormOptionInputs),
      ).map((div) => ({
        value: div.querySelector(`.${styleNames_1.default.formValueInput}`).value,
        name: div.querySelector(`.${styleNames_1.default.formNameInput}`).value,
        chosen: div.querySelector('[type=radio]').checked,
      }));
      let isValuesUnique = true;
      for (let i = 0; i < options.length - 1 && isValuesUnique; i++) {
        isValuesUnique = options
          .slice(i + 1)
          .some(
            (option) =>
              options[i].value !== option.value && options[i].name !== option.name,
          );
      }
      if (!isValuesUnique) {
        setError('Ключи и названия опций должны быть уникальными');
        return;
      }
      value = options;
      break;
    }
    case 'text': {
      value = valueInput.value;
      break;
    }
    case 'float':
    case 'integer': {
      value = Number(valueInput.value.replace(',', '.'));
      step = valueInput.step;
      break;
    }
    case 'checkbox': {
      value = valueInput.checked;
      break;
    }
    case 'details': {
      let isOldValuesValueObject =
        typeof (oldValues === null || oldValues === void 0 ? void 0 : oldValues.value) ===
          'object' && !Array.isArray(oldValues.value);
      value = isOldValuesValueObject
        ? oldValues === null || oldValues === void 0
          ? void 0
          : oldValues.value
        : {};
      break;
    }
  }
  document.querySelector(`.${styleNames_1.default.wrapper}`).dataset.isChanged = 'true';
  (0, createConfigPage_1.createConfigPageRecursion)(
    {
      [key]: { name, value, type: valueInputType, step },
    },
    target,
  );
  form.remove();
  // определяем, что нужно изменить в дефолтном конфиге
  let saveInDefault = '';
  if (!oldValues) {
    saveInDefault = 'key name value';
  } else {
    saveInDefault =
      ((_a = targetNode.querySelector(`[data-key="${oldValues.key}"]`)) === null ||
      _a === void 0
        ? void 0
        : _a.dataset.saveInDefault) || '';
    saveInDefault +=
      key !== oldValues.key && !saveInDefault.includes('key') ? ' key' : '';
    saveInDefault +=
      name !== oldValues.name && !saveInDefault.includes('name') ? ' name' : '';
    if (
      (JSON.stringify(value) !== JSON.stringify(oldValues.value) &&
        !saveInDefault.includes('value')) ||
      (oldValues.type && oldValues.type !== valueInputType)
    ) {
      saveInDefault += ' value';
    }
    saveInDefault = saveInDefault.trimStart();
  }
  // создаём вложенную форму, если был создан раздел
  if (valueInputType === 'details') {
    const newTarget = Array.from(target.children).find((node) =>
      node.querySelector(`[data-key="${key}"]`),
    );
    if (!newSection) {
      newSection = newTarget;
    }
    newTarget === null || newTarget === void 0
      ? void 0
      : newTarget.appendChild(createForm({ targetNode: newTarget }));
  }
  target.querySelector(`[data-key="${key}"]`).dataset.saveInDefault = saveInDefault;
  document.removeEventListener('click', removeForm);
};
const createInput = (descriptionText, value, style, parent) => {
  const wrapper = (0, utils_1.createElement)(
    'div',
    null,
    parent,
    (0, utils_1.createElement)('span', { innerHTML: `${descriptionText}:` }),
  );
  return (0, utils_1.createElement)(
    'input',
    { type: 'text', required: true, className: style, value: value },
    wrapper,
  );
};
// удаляет форму по клику на любое место на экране, кроме самой формы
const removeForm = (e) => {
  const form = document.querySelector(`.${styleNames_1.default.form}`);
  if (form && !e.composedPath().includes(form)) {
    if (oldValues) {
      form.replaceWith(targetNode);
    } else {
      form.remove();
      if (
        isCreatedSection &&
        !Array.from(
          (newSection === null || newSection === void 0 ? void 0 : newSection.children) ||
            [],
        ).some((elem) => elem.nodeName !== 'SUMMARY')
      ) {
        newSection === null || newSection === void 0 ? void 0 : newSection.remove();
      }
      isCreatedSection = false;
      newSection = null;
    }
    document.removeEventListener('click', removeForm);
  }
};
// добавляет текст ошибки валидации в форме
const setError = (text) => {
  const form = document.querySelector(`.${styleNames_1.default.form}`);
  if (!form) {
    return;
  }
  const errorMessage = (0, utils_1.createElement)(
    'p',
    {
      className: styleNames_1.default.formValidationError,
      innerHTML: text,
    },
    form,
  );
  const removeError = () => {
    errorMessage.remove();
    form === null || form === void 0
      ? void 0
      : form.removeEventListener('click', removeError);
  };
  setTimeout(() =>
    form === null || form === void 0
      ? void 0
      : form.addEventListener('click', removeError),
  );
};
// форма ввода опций для селекта
const createOptionsForm = (oldValues = []) => {
  const form = (0, utils_1.createElement)('div', {
    className: styleNames_1.default.optionsForm,
  });
  (0, utils_1.createElement)('h3', { innerHTML: 'Создайте опции' }, form);
  (0, utils_1.createElement)(
    'div',
    { className: styleNames_1.default.optionsFormTableHead },
    form,
    [
      (0, utils_1.createElement)('p', { innerHTML: 'Имя' }),
      (0, utils_1.createElement)('p', { innerHTML: 'Значение' }),
    ],
  );
  (0, utils_1.createElement)(
    'button',
    {
      textContent: 'Добавить опцию',
      className: styleNames_1.default.optionsFormAddOptionButton,
      type: 'button',
      onclick: () => createOptionInputs(form),
    },
    form,
  );
  // если это форма редактирования, то добавляем уже существующие опции, если нет, то добавляем дефолтную
  if (oldValues.length > 0) {
    oldValues.forEach((option) => createOptionInputs(form, option));
  } else {
    createOptionInputs(
      form,
      (0, utils_1.createElement)('option', {
        value: 'none',
        innerHTML: 'не выбрано',
        selected: true,
      }),
    );
    createOptionInputs(form);
  }
  return form;
};
// инпуты для опций
const createOptionInputs = (parent, option) => {
  const addNewOptionButton = parent.querySelector(
    `.${styleNames_1.default.optionsFormAddOptionButton}`,
  );
  const optionNameInput = (0, utils_1.createElement)('input', {
    type: 'text',
    className: styleNames_1.default.formNameInput,
    required: true,
    value: (option === null || option === void 0 ? void 0 : option.textContent) || '',
  });
  const optionValueInput = (0, utils_1.createElement)('input', {
    type: 'text',
    className: styleNames_1.default.formValueInput,
    required: true,
    value: (option === null || option === void 0 ? void 0 : option.value) || '',
  });
  const optionSelectedInput = (0, utils_1.createElement)('input', {
    type: 'radio',
    checked: option === null || option === void 0 ? void 0 : option.selected,
    name: 'chosen',
  });
  const optionInputsContainer = (0, utils_1.createElement)(
    'div',
    { className: styleNames_1.default.optionsFormOptionInputs },
    null,
    [optionNameInput, optionValueInput, optionSelectedInput],
  );
  (0, helpers_1.createConfigControlButton)({
    type: 'delete',
    parent: optionInputsContainer,
    onClick: () => {
      optionInputsContainer.remove();
      if (
        parent.querySelectorAll(`.${styleNames_1.default.optionsFormOptionInputs}`)
          .length === 0
      ) {
        createOptionInputs(parent);
      }
    },
  });
  parent.insertBefore(optionInputsContainer, addNewOptionButton);
  window.setTimeout(() => optionNameInput.focus());
};
exports.default = createForm;
//# sourceMappingURL=createForm.js.map
