перепиши мой код  , я написал визуальный конструктор . нужно переписать и создаь синтаксис пайтона и добавь туда эелменты пайтона и напиши код на Javascript 
<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="UTF-8">
  <title>Визуальный Конструктор Скриптов</title>
  <style>
    /* Стили CSS */

    /* Общие стили */
    body {
      margin: 0;
      display: flex;
      flex-direction: column;
      height: 100vh;
      font-family: Arial, sans-serif;
    }

    /* Верхнее меню */
    #menu {
      background: #f1f1f1;
      padding: 10px;
      display: flex;
      border-bottom: 1px solid #ccc;
    }

    #menu button {
      margin-right: 10px;
      padding: 8px 15px;
      background-color: #337ab7;
      color: #fff;
      border: none;
      border-radius: 4px;
      cursor: pointer;
      transition: background 0.3s;
    }

    #menu button:hover {
      background-color: #286090;
    }

    /* Основная часть */
    #content {
      display: flex;
      flex-grow: 1;
    }

    /* Левая панель (элементы) */
    #sidebar {
      width: 200px;
      background: #f7f7f7;
      padding: 10px;
      overflow-y: auto;
      border-right: 1px solid #ccc;
      box-sizing: border-box;
    }

    #sidebar h3,
    #sidebar h4 {
      margin-top: 0;
    }

    #custom-elements {
      margin-top: 20px;
    }

    /* Правая панель (свойства) */
    #properties {
      width: 250px;
      background: #f7f7f7;
      padding: 10px;
      overflow-y: auto;
      border-left: 1px solid #ccc;
      box-sizing: border-box;
    }

    #properties h3 {
      margin-top: 0;
    }

    #properties-content {
      margin-top: 10px;
    }

    .element-properties {
      margin-bottom: 20px;
      border-bottom: 1px solid #ccc;
      padding-bottom: 10px;
    }

    .element-properties h4 {
      margin: 0 0 10px 0;
    }

    /* Центральная часть */
    #main-content {
      flex-grow: 1;
      display: flex;
    }

    /* Рабочая область */
    #workspace-container {
      flex-grow: 1;
      display: flex;
      flex-direction: column;
    }

    #workspace {
      position: relative;
      background: #fff;
      overflow: auto;
      flex-grow: 1;
    }

    /* Прямоугольник выделения */
    #selection-rectangle {
      position: absolute;
      border: 1px dashed #5bc0de;
      background: rgba(91, 192, 222, 0.1);
      display: none;
      pointer-events: none;
    }

    /* Консоль (снизу) */
    #console {
      background: #232323;
      color: #eaeaea;
      font-family: monospace;
      padding: 10px;
      overflow-y: auto;
      box-sizing: border-box;
      height: 150px;
    }

    #console h3 {
      margin-top: 0;
    }

    #console pre {
      white-space: pre-wrap;
    }

    /* Элементы */
    .element {
      background: #d9edf7;
      margin: 5px 0;
      padding: 8px;
      border: 1px solid #bce8f1;
      border-radius: 4px;
      cursor: grab;
      user-select: none;
      transition: background 0.3s, transform 0.3s;
    }

    .element:hover {
      background: #c4e3f3;
      transform: scale(1.05);
    }

    .workspace-element {
      position: absolute;
      background: #fefefe;
      padding: 10px;
      border: 1px solid #ddd;
      border-radius: 4px;
      cursor: move;
      user-select: none;
      min-width: 100px;
      text-align: center;
      transition: box-shadow 0.2s, transform 0.3s;
      animation: fadeIn 0.5s;
    }

    .workspace-element:hover {
      box-shadow: 0 0 5px rgba(0,0,0,0.3);
      transform: scale(1.05);
    }

    .workspace-element.selected {
      border-color: #5cb85c;
      box-shadow: 0 0 10px rgba(92, 184, 92, 0.5);
    }

    /* Анимация появления элемента */
    @keyframes fadeIn {
      from { opacity: 0; transform: scale(0.8); }
      to { opacity: 1; transform: scale(1); }
    }

    /* Точки соединения */
    .connector {
      width: 10px;
      height: 10px;
      background: #5bc0de;
      border: 1px solid #46b8da;
      border-radius: 50%;
      position: absolute;
      cursor: pointer;
      transition: background 0.2s;
    }

    .connector:hover {
      background: #31b0d5;
    }

    .connector.connecting {
      background: #d9534f;
    }

    .connector.active {
      background: #5cb85c;
    }

    /* Левая точка (Вход) */
    .connector.input {
      left: -5px;
      top: 50%;
      transform: translateY(-50%);
    }

    /* Правая точка (Выход) */
    .connector.output {
      right: -5px;
      top: 50%;
      transform: translateY(-50%);
    }

    /* Подсказки */
    .connector::after {
      content: attr(data-tooltip);
      position: absolute;
      left: 50%;
      bottom: 120%;
      transform: translateX(-50%);
      background: #333;
      color: #fff;
      padding: 2px 5px;
      border-radius: 3px;
      opacity: 0;
      white-space: nowrap;
      pointer-events: none;
      transition: opacity 0.2s;
      font-size: 12px;
      z-index: 10;
    }

    .connector:hover::after {
      opacity: 1;
    }

    /* Соединения */
    #connections {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      pointer-events: none;
    }

    .line {
      stroke: #337ab7;
      stroke-width: 2;
      transition: stroke 0.2s;
    }

    .line:hover {
      stroke: #d9534f;
    }

    .line.active {
      stroke: #5cb85c;
    }

    /* Временная линия при соединении */
    #temp-line {
      stroke: #5bc0de;
      stroke-width: 2;
      stroke-dasharray: 5,5;
    }

    /* Стрелки на линиях */
    .marker {
      stroke: none;
      fill: #337ab7;
    }

    /* Форма в окне свойств */
    #properties-content form {
      display: flex;
      flex-direction: column;
    }

    #properties-content label {
      margin-bottom: 10px;
    }

    #properties-content input[type="text"],
    #properties-content textarea {
      width: 100%;
      padding: 5px;
      box-sizing: border-box;
    }

    #properties-content textarea {
      height: 80px;
    }

    #properties-content select {
      width: 100%;
      padding: 5px;
      box-sizing: border-box;
    }

    #properties-content button {
      padding: 8px 15px;
      background-color: #5cb85c;
      color: #fff;
      border: none;
      border-radius: 4px;
      cursor: pointer;
      margin-top: 10px;
      transition: background 0.3s;
    }

    #properties-content button:hover {
      background-color: #4cae4c;
    }

    .element-properties {
      margin-bottom: 20px;
      border-bottom: 1px solid #ccc;
      padding-bottom: 10px;
    }

    .element-properties h4 {
      margin: 0 0 10px 0;
    }

    /* Модальное окно */
    #modal-overlay,
    #manage-elements-modal-overlay {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background: rgba(0, 0, 0, 0.5);
      z-index: 100;
      display: none;
    }

    #modal,
    #manage-elements-modal {
      position: fixed;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      background: #fff;
      padding: 20px;
      border-radius: 4px;
      z-index: 101;
      width: 400px;
      max-width: 90%;
    }

    #modal h3,
    #manage-elements-modal h3 {
      margin-top: 0;
    }

    #modal form,
    #manage-elements-modal form {
      display: flex;
      flex-direction: column;
    }

    #modal label,
    #manage-elements-modal label {
      margin-bottom: 10px;
    }

    #modal input[type="text"],
    #modal textarea,
    #modal select,
    #manage-elements-modal input[type="text"],
    #manage-elements-modal textarea,
    #manage-elements-modal select {
      width: 100%;
      padding: 5px;
      box-sizing: border-box;
    }

    #modal textarea,
    #manage-elements-modal textarea {
      height: 80px;
    }

    #modal button,
    #manage-elements-modal button {
      padding: 8px 15px;
      background-color: #337ab7;
      color: #fff;
      border: none;
      border-radius: 4px;
      cursor: pointer;
      margin-top: 10px;
      transition: background 0.3s;
    }

    #modal button:hover,
    #manage-elements-modal button:hover {
      background-color: #286090;
    }

    #close-modal,
    #close-manage-modal {
      background-color: #d9534f;
    }

    #close-modal:hover,
    #close-manage-modal:hover {
      background-color: #c9302c;
    }

    /* Стили для списка пользовательских элементов в модальном окне */
    #custom-elements-list {
      list-style: none;
      padding: 0;
      margin: 0;
      max-height: 300px;
      overflow-y: auto;
    }

    #custom-elements-list li {
      padding: 10px;
      border-bottom: 1px solid #ccc;
      position: relative;
    }

    #custom-elements-list li:hover {
      background-color: #f1f1f1;
    }

    .edit-button,
    .delete-button {
      position: absolute;
      top: 10px;
      right: 70px;
      padding: 5px 10px;
      background-color: #5bc0de;
      color: #fff;
      border: none;
      border-radius: 4px;
      cursor: pointer;
      margin-right: 5px;
    }

    .delete-button {
      right: 10px;
      background-color: #d9534f;
    }

    .edit-button:hover {
      background-color: #31b0d5;
    }

    .delete-button:hover {
      background-color: #c9302c;
    }
  </style>
</head>
<body>
  <!-- Верхнее меню -->
  <div id="menu">
    <button id="save-project">Сохранить проект</button>
    <button id="load-project">Загрузить проект</button>
    <button id="create-element">Создать элемент</button>
    <button id="manage-elements">Управлять элементами</button>
  </div>

  <!-- Основная часть -->
  <div id="content">
    <!-- Левая панель с элементами -->
    <div id="sidebar">
      <h3>Элементы</h3>
      <div class="element" data-type="variable" draggable="true">Переменная</div>
      <div class="element" data-type="condition" draggable="true">Условие</div>
      <div class="element" data-type="action" draggable="true">Действие</div>
      <div class="element" data-type="input" draggable="true">Логический Вход</div>
      <div class="element" data-type="output" draggable="true">Логический Выход</div>
      <div class="element" data-type="timer" draggable="true">Таймер</div>
      <!-- Пользовательские элементы будут добавляться сюда -->
      <div id="custom-elements">
        <h4>Пользовательские элементы</h4>
        <!-- Список пользовательских элементов -->
      </div>
    </div>

    <!-- Центральная часть -->
    <div id="main-content">
      <!-- Рабочая область и консоль -->
      <div id="workspace-container">
        <!-- Рабочая область -->
        <div id="workspace">
          <svg id="connections"></svg>
          <!-- Прямоугольник выделения -->
          <div id="selection-rectangle"></div>
        </div>

        <!-- Результат кода -->
        <div id="console">
          <h3>Результат Кода</h3>
          <pre id="console-output"></pre>
        </div>
      </div>

      <!-- Правая панель со свойствами -->
      <div id="properties">
        <h3>Свойства</h3>
        <div id="properties-content">
          <p>Выберите элемент, чтобы изменить его свойства.</p>
        </div>
      </div>
    </div>
  </div>

  <!-- Модальное окно для создания элемента -->
  <div id="modal-overlay">
    <div id="modal">
      <h3 id="modal-title">Создать новый элемент</h3>
      <form id="create-element-form">
        <label>
          Имя элемента:
          <input type="text" id="custom-element-name" required>
        </label>
        <label>
          Параметры элемента (в формате JSON):
          <textarea id="custom-element-params" placeholder='{"param1": "value1", "param2": "value2"}' required></textarea>
        </label>
        <label>
          Шаблон кода:
          <textarea id="custom-element-code-template" placeholder='код шаблона с параметрами типа {param1}, {param2}' required></textarea>
        </label>
        <label>
          Точки соединения:
          <select id="custom-element-connectors">
            <option value="input-output">Вход и Выход</option>
            <option value="input">Только Вход</option>
            <option value="output">Только Выход</option>
            <option value="none">Без точек</option>
          </select>
        </label>
        <button type="submit" id="create-element-button">Создать</button>
        <button type="button" id="close-modal">Отмена</button>
      </form>
    </div>
  </div>

  <!-- Модальное окно для управления элементами -->
  <div id="manage-elements-modal-overlay">
    <div id="manage-elements-modal">
      <h3>Управление элементами</h3>
      <ul id="custom-elements-list">
        <!-- Список пользовательских элементов для управления -->
      </ul>
      <button type="button" id="close-manage-modal">Закрыть</button>
    </div>
  </div>

  <!-- Скрипты JavaScript -->
  <script>
    // Получаем ссылки на DOM-элементы
    const menu = document.getElementById('menu');
    const saveProjectBtn = document.getElementById('save-project');
    const loadProjectBtn = document.getElementById('load-project');
    const createElementBtn = document.getElementById('create-element');
    const manageElementsBtn = document.getElementById('manage-elements');

    const sidebar = document.getElementById('sidebar');
    const workspace = document.getElementById('workspace');
    const consoleOutput = document.getElementById('console-output');
    const connectionsSvg = document.getElementById('connections');
    const propertiesPanel = document.getElementById('properties-content');
    const selectionRectangle = document.getElementById('selection-rectangle');
    const customElementsContainer = document.getElementById('custom-elements');

    const modalOverlay = document.getElementById('modal-overlay');
    const modal = document.getElementById('modal');
    const modalTitle = document.getElementById('modal-title');
    const createElementForm = document.getElementById('create-element-form');
    const createElementButton = document.getElementById('create-element-button');
    const closeModalBtn = document.getElementById('close-modal');

    const manageElementsModalOverlay = document.getElementById('manage-elements-modal-overlay');
    const manageElementsModal = document.getElementById('manage-elements-modal');
    const customElementsList = document.getElementById('custom-elements-list');
    const closeManageModalBtn = document.getElementById('close-manage-modal');

    // Массивы для хранения элементов и соединений
    let elements = [];
    let connections = [];

    // Выбранные элементы
    let selectedElements = [];

    // Массив пользовательских элементов
    let customElements = [];

    // Переменная для хранения индекса редактируемого элемента
    let editingElementIndex = null;

    // Создаем временную линию для соединения
    const tempLine = document.createElementNS('http://www.w3.org/2000/svg', 'line');
    tempLine.setAttribute('id', 'temp-line');
    connectionsSvg.appendChild(tempLine);

    // Добавим маркер стрелки для обозначения направления потока
    const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
    const marker = document.createElementNS('http://www.w3.org/2000/svg', 'marker');
    marker.setAttribute('id', 'arrowhead');
    marker.setAttribute('markerWidth', '10');
    marker.setAttribute('markerHeight', '7');
    marker.setAttribute('refX', '0');
    marker.setAttribute('refY', '3.5');
    marker.setAttribute('orient', 'auto');

    const arrowPath = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
    arrowPath.setAttribute('points', '0 0, 10 3.5, 0 7');
    arrowPath.setAttribute('class', 'marker');

    marker.appendChild(arrowPath);
    defs.appendChild(marker);
    connectionsSvg.appendChild(defs);

    // Обработчики для кнопок меню
    saveProjectBtn.addEventListener('click', saveProject);
    loadProjectBtn.addEventListener('click', loadProject);
    createElementBtn.addEventListener('click', openCreateElementModal);
    manageElementsBtn.addEventListener('click', openManageElementsModal);

    // Функции сохранения и загрузки проекта
    function saveProject() {
      const projectData = {
        elements: elements.map(el => ({
          id: el.id,
          type: el.type,
          x: el.x,
          y: el.y,
          properties: el.properties,
          custom: el.custom || false,
        })),
        connections,
        customElements,
      };
      localStorage.setItem('visualScriptProject', JSON.stringify(projectData));
      alert('Проект сохранен!');
    }

    function loadProject() {
      const projectData = JSON.parse(localStorage.getItem('visualScriptProject'));
      if (projectData) {
        // Очищаем текущую рабочую область
        clearWorkspace();

        // Восстанавливаем пользовательские элементы
        customElements = projectData.customElements || [];
        saveCustomElementsToLocalStorage();
        customElementsContainer.innerHTML = '<h4>Пользовательские элементы</h4>';
        customElements.forEach(customEl => addCustomElementToSidebar(customEl));

        // Восстанавливаем элементы
        elements = projectData.elements.map(elData => {
          const elem = createWorkspaceElement(elData.type, elData.x, elData.y, elData.id, elData.custom);
          elem.properties = elData.properties;
          updateElementContent(elem.domElement, elem);
          return elem;
        });

        // Восстанавливаем соединения
        connections = projectData.connections;
        drawConnections();

        alert('Проект загружен!');
      } else {
        alert('Нет сохраненного проекта.');
      }
    }

    function clearWorkspace() {
      // Очищаем элементы
      elements.forEach(el => {
        el.domElement.remove();
      });
      elements = [];

      // Очищаем соединения
      connections = [];
      drawConnections();
    }

    // Функция открытия модального окна создания элемента
    function openCreateElementModal() {
      // Сбрасываем переменную редактирования
      editingElementIndex = null;
      modalTitle.textContent = 'Создать новый элемент';
      createElementButton.textContent = 'Создать';
      modalOverlay.style.display = 'block';
      createElementForm.reset();
    }

    // Обработчик закрытия модального окна
    closeModalBtn.addEventListener('click', () => {
      modalOverlay.style.display = 'none';
      createElementForm.reset();
    });

    // Добавляем сохранение пользовательских элементов в localStorage
    function saveCustomElementsToLocalStorage() {
      localStorage.setItem('customElements', JSON.stringify(customElements));
    }

    // Загружаем пользовательские элементы из localStorage при загрузке страницы
    function loadCustomElementsFromLocalStorage() {
      const storedElements = JSON.parse(localStorage.getItem('customElements'));
      if (storedElements) {
        customElements = storedElements;
        customElementsContainer.innerHTML = '<h4>Пользовательские элементы</h4>';
        customElements.forEach(customEl => addCustomElementToSidebar(customEl));
      }
    }

    // Функция добавления пользовательского элемента в боковую панель
    function addCustomElementToSidebar(customElement) {
      const customElementDiv = document.createElement('div');
      customElementDiv.classList.add('element');
      customElementDiv.textContent = customElement.name;
      customElementDiv.dataset.type = customElement.name;
      customElementDiv.dataset.custom = 'true';
      customElementDiv.draggable = true;
      customElementsContainer.appendChild(customElementDiv);

      customElementDiv.addEventListener('dragstart', (e) => {
        e.dataTransfer.setData('custom-element', JSON.stringify(customElement));
      });
    }

    // Обработчик начала перетаскивания элемента из сайдбара
    sidebar.addEventListener('dragstart', (e) => {
      if (e.target.classList.contains('element')) {
        if (e.target.dataset.custom === 'true') {
          e.dataTransfer.setData('custom-element', JSON.stringify(customElements.find(el => el.name === e.target.dataset.type)));
        } else {
          e.dataTransfer.setData('text/plain', e.target.dataset.type);
        }
      }
    });

    // Разрешаем сброс элемента на рабочую область
    workspace.addEventListener('dragover', (e) => {
      e.preventDefault();
    });

    // Обработчик сброса элемента на рабочую область
    workspace.addEventListener('drop', (e) => {
      e.preventDefault();
      const rect = workspace.getBoundingClientRect();
      const x = e.clientX - rect.left + workspace.scrollLeft;
      const y = e.clientY - rect.top + workspace.scrollTop;

      // Проверяем, является ли это пользовательским элементом
      const customElementData = e.dataTransfer.getData('custom-element');
      if (customElementData) {
        const customElement = JSON.parse(customElementData);
        createWorkspaceElement(customElement.name, x, y, null, true);
      } else {
        const elementType = e.dataTransfer.getData('text/plain');
        createWorkspaceElement(elementType, x, y);
      }
    });

    // Функция создания элемента на рабочей области
    function createWorkspaceElement(type, x, y, id = null, isCustom = false) {
      const elem = document.createElement('div');
      elem.classList.add('workspace-element');
      elem.dataset.type = type;
      elem.dataset.custom = isCustom;
      elem.style.left = x + 'px';
      elem.style.top = y + 'px';

      // Устанавливаем содержимое элемента
      const content = document.createElement('div');
      content.textContent = type;
      elem.appendChild(content);

      // Добавляем точки соединения
      const connectorsType = isCustom ? (customElements.find(el => el.name === type).connectors || 'input-output') : 'input-output';
      addConnectors(elem, connectorsType);

      // Уникальный ID для элемента
      const elementId = id || 'elem-' + Date.now() + '-' + Math.floor(Math.random() * 1000);
      elem.dataset.id = elementId;

      // Сохраняем данные элемента
      const elementData = {
        id: elementId,
        type: type,
        x: x,
        y: y,
        properties: {},
        domElement: elem, // Ссылка на DOM-элемент
        tempProperties: {}, // Временные свойства для редактирования
        custom: isCustom,
      };

      // Устанавливаем свойства по умолчанию для пользовательских элементов
      if (isCustom) {
        const customElData = customElements.find(el => el.name === type);
        if (customElData) {
          elementData.properties = { ...customElData.params, codeTemplate: customElData.codeTemplate };
        }
      }

      elements.push(elementData);

      // Добавляем элемент на рабочую область и делаем его перетаскиваемым
      workspace.appendChild(elem);
      makeElementDraggable(elem);

      // Обработчик выбора элемента
      elem.addEventListener('click', (e) => {
        e.stopPropagation();
        if (!e.shiftKey && !e.ctrlKey) {
          clearSelection();
        }
        selectElement(elem);
      });

      // Обновляем код
      generateCode();

      return elementData;
    }

    // Функция добавления точек соединения к элементу
    function addConnectors(elem, connectorsType) {
      // Удаляем существующие коннекторы
      const existingConnectors = elem.querySelectorAll('.connector');
      existingConnectors.forEach(connector => connector.remove());

      if (connectorsType === 'input' || connectorsType === 'input-output') {
        // Левая точка (Вход)
        const inputConnector = document.createElement('div');
        inputConnector.classList.add('connector', 'input');
        inputConnector.dataset.type = 'input';
        inputConnector.dataset.tooltip = 'Входная точка';
        elem.appendChild(inputConnector);

        // Обработчик события для соединения
        inputConnector.addEventListener('mousedown', connectorMouseDown);
      }

      if (connectorsType === 'output' || connectorsType === 'input-output') {
        // Правая точка (Выход)
        const outputConnector = document.createElement('div');
        outputConnector.classList.add('connector', 'output');
        outputConnector.dataset.type = 'output';
        outputConnector.dataset.tooltip = 'Выходная точка';
        elem.appendChild(outputConnector);

        // Обработчик события для соединения
        outputConnector.addEventListener('mousedown', connectorMouseDown);
      }
    }

    // Функция для перетаскивания элементов внутри рабочей области
    function makeElementDraggable(elem) {
      let offsetX, offsetY;

      elem.addEventListener('mousedown', (e) => {
        if (e.target.classList.contains('connector')) {
          // Если кликнули на точке соединения, не перемещаем элемент
          return;
        }
        if (!selectedElements.includes(elem)) {
          if (!e.shiftKey && !e.ctrlKey) {
            clearSelection();
          }
          selectElement(elem);
        }
        offsetX = e.clientX;
        offsetY = e.clientY;

        const initialPositions = selectedElements.map((el) => {
          return {
            el: el,
            x: parseInt(el.style.left),
            y: parseInt(el.style.top),
          };
        });

        function mouseMove(e) {
          const dx = e.clientX - offsetX;
          const dy = e.clientY - offsetY;

          initialPositions.forEach((pos) => {
            pos.el.style.left = pos.x + dx + 'px';
            pos.el.style.top = pos.y + dy + 'px';

            // Обновляем позицию в данных
            const elementData = elements.find((elData) => elData.id === pos.el.dataset.id);
            if (elementData) {
              elementData.x = parseInt(pos.el.style.left);
              elementData.y = parseInt(pos.el.style.top);
            }
          });

          // Обновляем соединения
          drawConnections();
        }

        function mouseUp() {
          document.removeEventListener('mousemove', mouseMove);
          document.removeEventListener('mouseup', mouseUp);
          generateCode();
        }

        document.addEventListener('mousemove', mouseMove);
        document.addEventListener('mouseup', mouseUp);
      });
    }

    // Функция выбора элемента
    function selectElement(elem) {
      if (!selectedElements.includes(elem)) {
        selectedElements.push(elem);
        elem.classList.add('selected');
        showProperties();
      }
    }

    // Функция очистки выделения
    function clearSelection() {
      selectedElements.forEach((el) => el.classList.remove('selected'));
      selectedElements = [];
      showProperties();
    }

    // Обработка области выделения
    let isSelecting = false;
    let selectionStart = { x: 0, y: 0 };
    let justSelected = false; // Флаг для предотвращения очистки выделения

    workspace.addEventListener('mousedown', (e) => {
      if (e.target === workspace) {
        isSelecting = true;
        const rect = workspace.getBoundingClientRect();
        selectionStart.x = e.clientX - rect.left + workspace.scrollLeft;
        selectionStart.y = e.clientY - rect.top + workspace.scrollTop;

        selectionRectangle.style.display = 'block';
        selectionRectangle.style.left = selectionStart.x + 'px';
        selectionRectangle.style.top = selectionStart.y + 'px';
        selectionRectangle.style.width = '0px';
        selectionRectangle.style.height = '0px';
      }
    });

    workspace.addEventListener('mousemove', (e) => {
      if (isSelecting) {
        const rect = workspace.getBoundingClientRect();
        const x = e.clientX - rect.left + workspace.scrollLeft;
        const y = e.clientY - rect.top + workspace.scrollTop;
        const rectX = Math.min(x, selectionStart.x);
        const rectY = Math.min(y, selectionStart.y);
        const rectWidth = Math.abs(x - selectionStart.x);
        const rectHeight = Math.abs(y - selectionStart.y);

        selectionRectangle.style.left = rectX + 'px';
        selectionRectangle.style.top = rectY + 'px';
        selectionRectangle.style.width = rectWidth + 'px';
        selectionRectangle.style.height = rectHeight + 'px';

        // Очищаем предыдущее выделение
        clearSelection();

        // Проверяем, какие элементы попадают в область выделения
        elements.forEach((elData) => {
          const el = elData.domElement;
          const elRect = el.getBoundingClientRect();

          const elementRect = {
            left: elRect.left,
            top: elRect.top,
            right: elRect.right,
            bottom: elRect.bottom,
          };

          if (rectsIntersect({
            left: rectX + workspace.getBoundingClientRect().left,
            top: rectY + workspace.getBoundingClientRect().top,
            right: rectX + rectWidth + workspace.getBoundingClientRect().left,
            bottom: rectY + rectHeight + workspace.getBoundingClientRect().top,
          }, elementRect)) {
            selectElement(el);
          }
        });
      }
    });

    workspace.addEventListener('mouseup', (e) => {
      if (isSelecting) {
        isSelecting = false;
        selectionRectangle.style.display = 'none';

        // Устанавливаем флаг, что только что произошло выделение
        justSelected = true;

        // Обновляем панель свойств
        showProperties();
      }
    });

    // Очистка выделения при клике на рабочей области
    workspace.addEventListener('click', (e) => {
      if (e.target === workspace) {
        if (!justSelected) {
          clearSelection();
        }
        // Сбрасываем флаг после обработки
        justSelected = false;
      }
    });

    // Вспомогательная функция для проверки пересечения прямоугольников
    function rectsIntersect(rect1, rect2) {
      return !(
        rect2.left > rect1.right ||
        rect2.right < rect1.left ||
        rect2.top > rect1.bottom ||
        rect2.bottom < rect1.top
      );
    }

    // Функция отображения свойств выбранных элементов
    function showProperties() {
      propertiesPanel.innerHTML = '';
      if (selectedElements.length === 0) {
        propertiesPanel.innerHTML = '<p>Выберите элемент, чтобы изменить его свойства.</p>';
        return;
      }

      selectedElements.forEach((el) => {
        const elementId = el.dataset.id;
        const elementData = elements.find((elData) => elData.id === elementId);

        if (elementData) {
          const container = document.createElement('div');
          container.classList.add('element-properties');

          const title = document.createElement('h4');
          title.textContent = `${capitalizeFirstLetter(elementData.type)} (${elementId})`;
          container.appendChild(title);

          const form = document.createElement('form');

          if (elementData.custom) {
            // Пользовательский элемент
            for (let paramName in elementData.properties) {
              if (paramName !== 'codeTemplate') { // Исключаем шаблон кода
                createInputField(form, paramName + ':', paramName, elementData.properties[paramName] || '');
              }
            }
          } else {
            switch (elementData.type) {
              case 'variable':
                createInputField(form, 'Имя переменной (a-h):', 'name', elementData.properties.name || 'a');
                createInputField(form, 'Значение переменной:', 'value', elementData.properties.value || '0');
                break;
              case 'condition':
                createInputField(form, 'Условие (например, a==10):', 'condition', elementData.properties.condition || '');
                break;
              case 'action':
                createInputField(form, 'Действие (например, out_1=1):', 'action', elementData.properties.action || '');
                break;
              case 'input':
                createInputField(form, 'Имя входа (in_1 - in_8):', 'name', elementData.properties.name || 'in_1');
                break;
              case 'output':
                createInputField(form, 'Имя выхода (out_1 - out_8):', 'name', elementData.properties.name || 'out_1');
                break;
              case 'timer':
                createInputField(form, 'Время (HH:MM):', 'time', elementData.properties.time || '12:00');
                break;
              default:
                break;
            }
          }

          // Кнопка "Применить" для каждого элемента
          const applyButton = document.createElement('button');
          applyButton.textContent = 'Применить';
          form.appendChild(applyButton);

          // Обработчик изменения свойств
          form.addEventListener('input', (e) => {
            const target = e.target;
            elementData.tempProperties[target.name] = target.value;
          });

          // Обработчик нажатия кнопки "Применить"
          form.addEventListener('submit', (e) => {
            e.preventDefault();
            if (Object.keys(elementData.tempProperties).length > 0) {
              Object.assign(elementData.properties, elementData.tempProperties);
              updateElementContent(el, elementData);
              generateCode();
              elementData.tempProperties = {}; // Очищаем временные свойства после применения
            }
          });

          container.appendChild(form);
          propertiesPanel.appendChild(container);
        }
      });
    }

    // Функция создания поля ввода
    function createInputField(form, labelText, propertyName, value) {
      const label = document.createElement('label');
      label.textContent = labelText;
      const input = document.createElement('input');
      input.type = 'text';
      input.name = propertyName;
      input.value = value;
      label.appendChild(input);
      form.appendChild(label);
    }

    // Функция обновления содержимого элемента на рабочей области
    function updateElementContent(elem, elementData) {
      const content = elem.querySelector('div');
      if (elementData.custom) {
        content.textContent = elementData.type;
      } else {
        switch (elementData.type) {
          case 'variable':
            content.textContent = `${elementData.properties.name} = ${elementData.properties.value}`;
            break;
          case 'condition':
            content.textContent = `if (${elementData.properties.condition})`;
            break;
          case 'action':
            content.textContent = `{ ${elementData.properties.action} }`;
            break;
          case 'input':
          case 'output':
            content.textContent = elementData.properties.name;
            break;
          case 'timer':
            content.textContent = `time = ${elementData.properties.time}`;
            break;
          default:
            break;
        }
      }
    }

    // Глобальные переменные для соединения
    let isConnecting = false;
    let startConnector = null;

    // Обработчик начала соединения
    function connectorMouseDown(e) {
      e.stopPropagation();
      isConnecting = true;
      startConnector = e.target;
      startConnector.classList.add('connecting');

      // Начальная позиция
      const startPos = getConnectorPosition(startConnector);
      tempLine.setAttribute('x1', startPos.x);
      tempLine.setAttribute('y1', startPos.y);
      tempLine.setAttribute('x2', startPos.x);
      tempLine.setAttribute('y2', startPos.y);
      tempLine.style.display = 'block';

      workspace.addEventListener('mousemove', connectorMouseMove);
      document.addEventListener('mouseup', connectorMouseUp);
    }

    // Обработчик движения мыши при соединении
    function connectorMouseMove(e) {
      const rect = workspace.getBoundingClientRect();
      const x = e.clientX - rect.left + workspace.scrollLeft;
      const y = e.clientY - rect.top + workspace.scrollTop;
      tempLine.setAttribute('x2', x);
      tempLine.setAttribute('y2', y);
    }

    // Обработчик окончания соединения
    function connectorMouseUp(e) {
      workspace.removeEventListener('mousemove', connectorMouseMove);
      document.removeEventListener('mouseup', connectorMouseUp);

      tempLine.style.display = 'none';
      startConnector.classList.remove('connecting');

      if (e.target.classList.contains('connector') && e.target !== startConnector) {
        const fromConnector = startConnector;
        const toConnector = e.target;

        // Проверка разрешенных типов соединения
        if (fromConnector.dataset.type !== toConnector.dataset.type) {
          const fromElementId = fromConnector.parentElement.dataset.id;
          const toElementId = toConnector.parentElement.dataset.id;

          // Определяем направление соединения
          let sourceId, targetId;
          let sourceConnectorType = fromConnector.dataset.type;
          let targetConnectorType = toConnector.dataset.type;

          if (fromConnector.dataset.type === 'output') {
            sourceId = fromElementId;
            targetId = toElementId;
          } else {
            sourceId = toElementId;
            targetId = fromElementId;
            // Меняем типы коннекторов местами
            sourceConnectorType = toConnector.dataset.type;
            targetConnectorType = fromConnector.dataset.type;
          }

          // Проверяем на существование соединения
          const existingConnection = connections.find(
            (conn) =>
              conn.from === sourceId &&
              conn.to === targetId &&
              conn.fromConnectorType === sourceConnectorType &&
              conn.toConnectorType === targetConnectorType
          );

          if (!existingConnection) {
            connections.push({
              from: sourceId,
              to: targetId,
              fromConnectorType: sourceConnectorType,
              toConnectorType: targetConnectorType,
            });

            // Обновляем соединения и код
            drawConnections();
            generateCode();
          } else {
            alert('Соединение уже существует.');
          }
        } else {
          alert('Неверное соединение. Соединяйте выход с входом.');
        }
      }

      isConnecting = false;
      startConnector = null;
    }

    // Функция обновления всех соединений
    function drawConnections() {
      // Очищаем все линии, кроме временной
      connectionsSvg.querySelectorAll('.line').forEach((line) => line.remove());

      connections.forEach((conn) => {
        const fromElem = document.querySelector(`.workspace-element[data-id="${conn.from}"]`);
        const toElem = document.querySelector(`.workspace-element[data-id="${conn.to}"]`);

        const fromConnector = fromElem.querySelector('.connector.output');
        const toConnector = toElem.querySelector('.connector.input');

        if (fromConnector && toConnector) {
          const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');

          const fromPos = getConnectorPosition(fromConnector);
          const toPos = getConnectorPosition(toConnector);

          line.setAttribute('x1', fromPos.x);
          line.setAttribute('y1', fromPos.y);
          line.setAttribute('x2', toPos.x);
          line.setAttribute('y2', toPos.y);
          line.classList.add('line');

          // Добавляем стрелку на линию
          line.setAttribute('marker-end', 'url(#arrowhead)');

          // Сохранение ссылки на соединение
          line.dataset.from = conn.from;
          line.dataset.to = conn.to;
          line.dataset.fromConnectorType = conn.fromConnectorType;
          line.dataset.toConnectorType = conn.toConnectorType;

          // Обработчик для удаления соединения
          line.addEventListener('click', (e) => {
            e.stopPropagation();
            if (confirm('Удалить соединение?')) {
              // Удаляем соединение из массива
              const index = connections.findIndex(
                (c) =>
                  c.from === conn.from &&
                  c.to === conn.to &&
                  c.fromConnectorType === conn.fromConnectorType &&
                  c.toConnectorType === conn.toConnectorType
              );
              if (index !== -1) {
                connections.splice(index, 1);
              }

              // Обновляем соединения и код
              drawConnections();
              generateCode();
            }
          });

          connectionsSvg.appendChild(line);
        }
      });
    }

    // Функция получения позиции точки соединения
    function getConnectorPosition(connector) {
      const rect = connector.getBoundingClientRect();
      const parentRect = workspace.getBoundingClientRect();

      return {
        x: rect.left - parentRect.left + rect.width / 2 + workspace.scrollLeft,
        y: rect.top - parentRect.top + rect.height / 2 + workspace.scrollTop,
      };
    }

    // Функция генерации кода
    function generateCode() {
      const codeLines = [];

      // Шаг 1: Задание переменных
      elements
        .filter((el) => el.type === 'variable')
        .forEach((variable) => {
          const name = variable.properties.name;
          const value = variable.properties.value;
          if (name && value !== undefined) {
            codeLines.push(`${name} = ${value};`);
          }
        });

      // Шаг 2: Работа с логическими входами и специальными константами
      elements
        .filter((el) => el.type === 'input' || el.type === 'timer')
        .forEach((el) => {
          if (el.type === 'input') {
            const name = el.properties.name;
            if (name) {
              codeLines.push(`${name} = ?;`);
            }
          } else if (el.type === 'timer') {
            const timeValue = el.properties.time;
            if (timeValue) {
              codeLines.push(`time = ${timeValue};`);
            }
          }
        });

      // Шаг 3: Обработка всех элементов, начиная с корневых
      const processedElements = new Set();

      // Ищем элементы без входящих соединений (корневые)
      elements
        .filter((el) => !hasIncomingConnections(el.id))
        .forEach((el) => {
          generateElementCode(el, codeLines, 0, processedElements);
        });

      // Шаг 4: Выводим код
      consoleOutput.textContent = codeLines.join('\n');
    }

    // Функция рекурсивной генерации кода для элемента и его потомков
    function generateElementCode(element, codeLines, indentLevel, processedElements) {
      if (processedElements.has(element.id)) {
        return;
      }
      processedElements.add(element.id);

      const indent = '  '.repeat(indentLevel);

      switch (element.type) {
        case 'condition':
          const condText = element.properties.condition;
          if (condText) {
            codeLines.push(`${indent}if (${condText}) {`);
            const connectedElements = getOutgoingConnectedElements(element.id);
            connectedElements.forEach((el) => {
              generateElementCode(el, codeLines, indentLevel + 1, processedElements);
            });
            codeLines.push(`${indent}}`);
          }
          break;

        case 'action':
          const actionText = element.properties.action;
          if (actionText) {
            codeLines.push(`${indent}${actionText};`);
          }
          break;

        case 'output':
          const outputName = element.properties.name;
          if (outputName) {
            codeLines.push(`${indent}${outputName} = 1;`);
          }
          break;

        // Обработка пользовательских элементов
        default:
          if (element.custom) {
            const customCode = generateCustomElementCode(element, indent);
            if (customCode) {
              codeLines.push(customCode);
            }
          } else {
            // Обработка других типов элементов при необходимости
          }
          break;
      }

      // Обрабатываем связанные элементы, если они не были обработаны ранее
      const nextElements = getOutgoingConnectedElements(element.id);
      nextElements.forEach((el) => {
        if (!processedElements.has(el.id)) {
          generateElementCode(el, codeLines, indentLevel, processedElements);
        }
      });
    }

    // Функция для генерации кода пользовательского элемента
    function generateCustomElementCode(element, indent) {
      const codeTemplate = element.properties.codeTemplate;
      if (codeTemplate) {
        let code = codeTemplate;
        for (const param in element.properties) {
          if (param !== 'codeTemplate') {
            const regex = new RegExp(`{${param}}`, 'g');
            code = code.replace(regex, element.properties[param]);
          }
        }
        return `${indent}${code};`;
      }
      return '';
    }

    // Проверка наличия входящих соединений у элемента
    function hasIncomingConnections(elementId) {
      return connections.some((conn) => conn.to === elementId);
    }

    // Получение исходящих соединенных элементов
    function getOutgoingConnectedElements(elementId) {
      return connections
        .filter((conn) => conn.from === elementId)
        .map((conn) => elements.find((el) => el.id === conn.to))
        .filter((el) => el);
    }

    // Вспомогательная функция для капитализации первой буквы строки
    function capitalizeFirstLetter(string) {
      return string.charAt(0).toUpperCase() + string.slice(1);
    }

    // Функция для удаления элемента
    workspace.addEventListener('contextmenu', (e) => {
      e.preventDefault();
      if (
        e.target.classList.contains('workspace-element') ||
        e.target.parentElement.classList.contains('workspace-element')
      ) {
        const element = e.target.classList.contains('workspace-element') ? e.target : e.target.parentElement;
        const elementId = element.dataset.id;

        if (confirm('Удалить элемент и все связанные с ним соединения?')) {
          // Анимация удаления элемента
          element.style.transition = 'opacity 0.5s, transform 0.5s';
          element.style.opacity = '0';
          element.style.transform = 'scale(0.5)';

          setTimeout(() => {
            // Удаляем элемент из массива элементов
            const elementIndex = elements.findIndex((el) => el.id === elementId);
            if (elementIndex !== -1) {
              elements.splice(elementIndex, 1);
            }

            // Удаляем связанные соединения
            for (let i = connections.length - 1; i >= 0; i--) {
              if (connections[i].from === elementId || connections[i].to === elementId) {
                connections.splice(i, 1);
              }
            }

            // Удаляем элемент из DOM
            element.remove();

            // Снимаем выделение
            if (selectedElements.includes(element)) {
              selectedElements = selectedElements.filter((el) => el !== element);
              showProperties();
            }

            // Обновляем соединения и код
            drawConnections();
            generateCode();
          }, 500); // Время должно совпадать со временем анимации
        }
      }
    });

    // Функции для управления пользовательскими элементами

    // Открытие модального окна управления элементами
    function openManageElementsModal() {
      manageElementsModalOverlay.style.display = 'block';
      renderCustomElementsList();
    }

    // Закрытие модального окна управления элементами
    closeManageModalBtn.addEventListener('click', () => {
      manageElementsModalOverlay.style.display = 'none';
      customElementsList.innerHTML = '';
    });

    // Функция рендеринга списка пользовательских элементов в модальном окне
    function renderCustomElementsList() {
      customElementsList.innerHTML = '';
      customElements.forEach((el, index) => {
        const li = document.createElement('li');
        li.textContent = el.name;
        // Кнопки редактирования и удаления
        const editBtn = document.createElement('button');
        editBtn.textContent = 'Редактировать';
        editBtn.classList.add('edit-button');
        editBtn.addEventListener('click', () => {
          openEditCustomElementModal(index);
        });

        const deleteBtn = document.createElement('button');
        deleteBtn.textContent = 'Удалить';
        deleteBtn.classList.add('delete-button');
        deleteBtn.addEventListener('click', () => {
          if (confirm(`Вы уверены, что хотите удалить элемент "${el.name}"?`)) {
            // Удаляем элемент из массива пользовательских элементов
            customElements.splice(index, 1);
            saveCustomElementsToLocalStorage();

            // Удаляем элементы с рабочей области, которые используют этот пользовательский элемент
            elements = elements.filter((elData) => {
              if (elData.custom && elData.type === el.name) {
                // Удаляем элемент с рабочей области
                elData.domElement.remove();
                return false;
              }
              return true;
            });

            // Обновляем боковую панель
            customElementsContainer.innerHTML = '<h4>Пользовательские элементы</h4>';
            customElements.forEach(customEl => addCustomElementToSidebar(customEl));

            // Обновляем соединения и код
            drawConnections();
            generateCode();

            // Обновляем список в модальном окне
            renderCustomElementsList();
          }
        });

        li.appendChild(editBtn);
        li.appendChild(deleteBtn);
        customElementsList.appendChild(li);
      });
    }

    // Открытие модального окна для редактирования пользовательского элемента
    function openEditCustomElementModal(index) {
      const el = customElements[index];
      // Заполняем форму модального окна создания элемента значениями элемента
      document.getElementById('custom-element-name').value = el.name;
      document.getElementById('custom-element-params').value = JSON.stringify(el.params, null, 2);
      document.getElementById('custom-element-code-template').value = el.codeTemplate;
      document.getElementById('custom-element-connectors').value = el.connectors;

      // Устанавливаем переменную редактирования
      editingElementIndex = index;

      // Изменяем заголовок и кнопку
      modalTitle.textContent = 'Редактировать элемент';
      createElementButton.textContent = 'Сохранить';

      // Открываем модальное окно создания/редактирования элемента
      manageElementsModalOverlay.style.display = 'none';
      modalOverlay.style.display = 'block';
    }

    // Обработчик создания/редактирования элемента
    function handleCreateElementSubmit(e) {
      e.preventDefault();
      const name = document.getElementById('custom-element-name').value.trim();
      const paramsText = document.getElementById('custom-element-params').value.trim();
      const codeTemplate = document.getElementById('custom-element-code-template').value.trim();
      const connectors = document.getElementById('custom-element-connectors').value;

      if (!name || !paramsText || !codeTemplate) {
        alert('Пожалуйста, заполните все поля.');
        return;
      }

      let params;
      try {
        params = JSON.parse(paramsText);
      } catch (error) {
        alert('Ошибка в формате параметров. Используйте корректный JSON.');
        return;
      }

      // Проверяем, редактируем ли мы элемент или создаём новый
      if (editingElementIndex !== null) {
        // Обновляем элемент
        customElements[editingElementIndex] = {
          name,
          params,
          codeTemplate,
          connectors,
        };
        saveCustomElementsToLocalStorage();

        // Обновляем боковую панель и список в модальном окне
        customElementsContainer.innerHTML = '<h4>Пользовательские элементы</h4>';
        customElements.forEach(customEl => addCustomElementToSidebar(customEl));

        // Обновляем экземпляры элемента на рабочей области
        elements.forEach((elData) => {
          if (elData.custom && elData.type === name) {
            elData.properties = { ...params, codeTemplate };
            // Обновляем точки соединения, если тип коннекторов изменился
            addConnectors(elData.domElement, connectors);
            // Обновляем содержимое элемента
            updateElementContent(elData.domElement, elData);
          }
        });

        // Обновляем соединения и код
        drawConnections();
        generateCode();

        // Возвращаем переменную редактирования в исходное состояние
        editingElementIndex = null;
        modalTitle.textContent = 'Создать новый элемент';
        createElementButton.textContent = 'Создать';

        // Закрываем модальное окно
        modalOverlay.style.display = 'none';
        createElementForm.reset();

        // Открываем обратно окно управления элементами
        manageElementsModalOverlay.style.display = 'block';
        renderCustomElementsList();
      } else {
        // Создаём новый элемент
        const customElement = {
          name,
          params,
          codeTemplate,
          connectors,
        };

        customElements.push(customElement);
        saveCustomElementsToLocalStorage();
        addCustomElementToSidebar(customElement);

        // Закрываем модальное окно и очищаем форму
        modalOverlay.style.display = 'none';
        createElementForm.reset();
      }
    }

    // Привязываем обработчик к форме создания элемента
    createElementForm.addEventListener('submit', handleCreateElementSubmit);

    // Загружаем пользовательские элементы при загрузке страницы
    loadCustomElementsFromLocalStorage();

  </script>
</body>
</html>