{% extends "mainapp/base.html" %}
{% load static %}
{% block title %}Анимация движения объектов{% endblock title %}

{% block extra_css %}
<link href="{% static 'leaflet/leaflet.css' %}" rel="stylesheet">
<link href="{% static 'leaflet-measure/leaflet-measure.css' %}" rel="stylesheet">
<link href="{% static 'leaflet-geoman/leaflet-geoman.css' %}" rel="stylesheet">
<link href="{% static 'leaflet-panel/leaflet-panel-layers.css' %}" rel="stylesheet">
<link href="{% static 'css/multi_sources_playback_map.css' %}" rel="stylesheet">
{% endblock %}

{% block content %}
<div id="loadingOverlay" class="loading-overlay">
    <div class="spinner-border text-primary" role="status">
        <span class="visually-hidden">Загрузка...</span>
    </div>
    <p class="mt-3">Загрузка данных...</p>
</div>

<div id="map"></div>

<!-- Layer Toggle Button -->
<button class="layer-toggle-btn" id="layerToggleBtn" title="Управление слоями">
    <i class="bi bi-layers"></i> Слои
</button>

<!-- Layer Manager Panel -->
<div class="layer-manager-panel" id="layerManagerPanel" style="display: none;">
    <div class="layer-manager-header">
        <h6> Управление слоями</h6>
        <button type="button" class="btn-close btn-close-white btn-sm" id="closeLayerPanel"></button>
    </div>
    <div class="layer-manager-body">
        <!-- Base Layers Section -->
        <div class="layer-section">
            <div class="layer-section-title">
                <span>Базовые слои (тайлы)</span>
            </div>
            <div id="baseLayers"></div>
        </div>
        
        <!-- Markers Layer Section (Playback) -->
        <div class="layer-section">
            <div class="layer-section-title">
                <span> Слой маркеров (Playback)</span>
            </div>
            <div id="markersLayerControl"></div>
        </div>
        
        <!-- Drawing Layers Section -->
        <div class="layer-section">
            <div class="layer-section-title">
                <span> Слои рисования</span>
                <button class="btn btn-sm btn-primary add-layer-btn" id="addDrawingLayerBtn" style="width: auto; margin: 0; padding: 2px 8px;">
                    <i class="bi bi-plus"></i> Добавить
                </button>
            </div>
            <div id="drawingLayers"></div>
        </div>
    </div>
    
    <!-- Import/Export -->
    <div class="io-buttons">
        <button class="btn-import" id="importLayersBtn">
            <i class="bi bi-upload"></i> Импорт
        </button>
        <button class="btn-export" id="exportLayersBtn">
            <i class="bi bi-download"></i> Экспорт
        </button>
    </div>
</div>

<div class="marker-size-control">
    <label>Размер маркеров:</label>
    <input type="range" id="markerSizeSlider" min="0.5" max="2" step="0.1" value="1">
    <span class="size-value" id="sizeValue">1.0x</span>
</div>

<div class="playback-control" id="playbackControl" style="display: none;">
    <button id="playBtn" title="Воспроизвести">▶</button>
    <button id="pauseBtn" title="Пауза" disabled>⏸</button>
    <button id="resetBtn" title="В начало">⏮</button>
    <input type="range" id="timeSlider" min="0" max="100" value="0" step="1">
    <div class="time-display" id="timeDisplay">--</div>
    <div class="speed-control">
        <label for="speedSelect">Скорость:</label>
        <select id="speedSelect">
            <option value="0.25">0.25x</option>
            <option value="0.5">0.5x</option>
            <option value="1" selected>1x</option>
            <option value="2">2x</option>
            <option value="5">5x</option>
            <option value="10">10x</option>
            <option value="20">20x</option>
        </select>
    </div>
</div>

<!-- Style Edit Modal -->
<div class="style-modal-overlay" id="styleModalOverlay"></div>
<div class="style-modal" id="styleModal">
    <h5 id="styleModalTitle">Редактирование элемента</h5>
    <div class="form-group">
        <label for="elementLabel">Подпись / Текст:</label>
        <input type="text" id="elementLabel" placeholder="Введите подпись">
    </div>
    <div class="form-group">
        <label for="elementColor">Цвет:</label>
        <input type="color" id="elementColor" value="#3388ff">
    </div>
    <div class="form-group" id="fillColorGroup">
        <label for="elementFillColor">Цвет заливки:</label>
        <input type="color" id="elementFillColor" value="#3388ff">
    </div>
    <div class="form-group" id="strokeWidthGroup">
        <label for="elementStrokeWidth">Толщина линии:</label>
        <input type="number" id="elementStrokeWidth" value="3" min="1" max="20">
    </div>
    <div class="form-group" id="opacityGroup">
        <label for="elementOpacity">Прозрачность заливки:</label>
        <input type="range" id="elementOpacity" min="0" max="1" step="0.1" value="0.2">
    </div>
    <div class="btn-row">
        <button class="btn-cancel" id="styleModalCancel">Отмена</button>
        <button class="btn-save" id="styleModalSave">Сохранить</button>
    </div>
</div>

<!-- Hidden file input for import -->
<input type="file" id="importFileInput" accept=".json,.geojson" style="display: none;">

<!-- Custom edit mode indicator -->
<div class="custom-edit-indicator" id="customEditIndicator">
    <i class="bi bi-pencil-square"></i> Режим редактирования стилей активен. Кликните на элемент для редактирования.
</div>
{% endblock content %}

{% block extra_js %}
<script src="{% static 'leaflet/leaflet.js' %}"></script>
<script src="{% static 'leaflet-measure/leaflet-measure.ru.js' %}"></script>
<script src="{% static 'leaflet-geoman/leafllet-geoman.js' %}"></script>
<script src="{% static 'leaflet-panel/leaflet-panel-layers.js' %}"></script>
<script src="{% static 'js/custom_marker_tool.js' %}"></script>

<script>
const SOURCE_IDS = "{{ source_ids }}";
const API_URL = "{% url 'mainapp:multi_sources_playback_api' %}";

// ==================== MAP INITIALIZATION ====================
let map = L.map('map', {
    center: [55.75, 37.62],
    zoom: 5,
    pmIgnore: false
});

L.control.scale({ imperial: false, metric: true }).addTo(map);
map.attributionControl.setPrefix(false);

// Base tile layers
const baseLayers = {
    'Улицы (OSM)': L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        maxZoom: 19,
        attribution: '&copy; OpenStreetMap contributors'
    }),
    'Спутник (Esri)': L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
        attribution: 'Tiles &copy; Esri'
    }),
    'Топографическая': L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
        maxZoom: 17,
        attribution: '&copy; OpenTopoMap'
    }),
    'Локальная': L.tileLayer('/tiles/styles/basic-preview/512/{z}/{x}/{y}.png', {
      maxZoom: 19,
      attribution: 'Local Tiles'
    })
};

// Set default base layer
let currentBaseLayer = baseLayers['Улицы (OSM)'];
currentBaseLayer.addTo(map);

// Measure control - moved to left side
L.control.measure({ 
    primaryLengthUnit: 'kilometers',
    position: 'topleft'
}).addTo(map);

// ==================== LAYER MANAGEMENT ====================
// Make these global for CustomMarkerTool access
window.drawingLayers = {}; // { layerId: { name, layerGroup, visible, elements: [] } }
let drawingLayers = window.drawingLayers;
let layerIdCounter = 0;

// Use getter/setter for activeDrawingLayerId to keep window.activeDrawingLayerId in sync
let _activeDrawingLayerId = null;
Object.defineProperty(window, 'activeDrawingLayerId', {
    get: () => _activeDrawingLayerId,
    set: (value) => { _activeDrawingLayerId = value; }
});
let activeDrawingLayerId = null;

// Markers layer for playback
let markersLayerGroup = L.layerGroup().addTo(map);
let markersLayerVisible = true;

// ==================== GEOMAN SETUP ====================
// Disable standard marker tool, use custom one instead
map.pm.addControls({
    position: 'topleft',
    drawCircle: true,
    drawCircleMarker: true,
    drawPolyline: true,
    drawRectangle: true,
    drawPolygon: true,
    drawMarker: false, // Disabled - using custom marker tool integrated below
    drawText: true,
    editMode: true,
    dragMode: true,
    cutPolygon: false,
    removalMode: true,
    rotateMode: true,
    scaleMode: true
});

// Add custom edit control after Geoman is initialized
addCustomEditControl();

// Set default path options
map.pm.setPathOptions({
    color: '#3388ff',
    fillColor: '#3388ff',
    fillOpacity: 0.2,
    weight: 3
});

// ==================== PLAYBACK STATE ====================
let sourcesData = [];
let timeRange = null;
let currentProgress = 0;
let playbackInterval = null;
let playbackSpeed = 50;
let speedMultiplier = 1;
let totalSteps = 1000;

let sourceLayerGroups = {};
let currentMarkers = {};
let trailPolylines = {};
let staticMarkers = {};

// Color and shape mappings
const colorMap = {
    'red': '#dc3545', 'blue': '#007bff', 'green': '#28a745', 'purple': '#6f42c1',
    'orange': '#fd7e14', 'cyan': '#17a2b8', 'magenta': '#e83e8c', 'pink': '#ff69b4',
    'teal': '#20c997', 'indigo': '#6610f2', 'brown': '#8b4513', 'navy': '#000080',
    'maroon': '#800000', 'olive': '#808000', 'coral': '#ff7f50', 'turquoise': '#40e0d0'
};

const shapeMap = {
    'circle': (color, size) => {
        const adjustedSize = Math.round(size * 0.85);
        return `<div style="background: ${color}; width: ${adjustedSize}px; height: ${adjustedSize}px; border-radius: 50%; border: 1px solid black; box-sizing: border-box;"></div>`;
    },
    'square': (color, size) => {
        const adjustedSize = Math.round(size * 0.85);
        return `<div style="background: ${color}; width: ${adjustedSize}px; height: ${adjustedSize}px; border: 1px solid black; box-sizing: border-box;"></div>`;
    },
    'triangle': (color, size) => {
        const adjustedSize = Math.round(size * 0.8);
        return `<svg width="${adjustedSize}" height="${adjustedSize}" viewBox="0 0 100 100"><polygon points="50,10 90,90 10,90" fill="${color}" stroke="black" stroke-width="2"/></svg>`;
    },
    'star': (color, size) => `<svg width="${size}" height="${size}" viewBox="0 0 24 24"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" fill="${color}" stroke="black" stroke-width="0.8"/></svg>`,
    'pentagon': (color, size) => `<svg width="${size}" height="${size}" viewBox="0 0 24 24"><path d="M12 2l7.5 5.5-2.9 9H7.4l-2.9-9z" fill="${color}" stroke="black" stroke-width="0.8"/></svg>`,
    'hexagon': (color, size) => `<svg width="${size}" height="${size}" viewBox="0 0 24 24"><path d="M12 2l6 4v8l-6 4-6-4V6z" fill="${color}" stroke="black" stroke-width="0.8"/></svg>`,
    'diamond': (color, size) => {
        const adjustedSize = Math.round(size * 0.85);
        return `<div style="background: ${color}; width: ${adjustedSize}px; height: ${adjustedSize}px; transform: rotate(45deg); border: 1px solid black; box-sizing: border-box;"></div>`;
    },
    'cross': (color, size) => `<svg width="${size}" height="${size}" viewBox="0 0 24 24"><path d="M9 2h6v7h7v6h-7v7H9v-7H2V9h7V2z" fill="${color}" stroke="black" stroke-width="0.8"/></svg>`
};

const availableShapes = ['circle', 'square', 'triangle', 'star', 'pentagon', 'hexagon', 'diamond', 'cross'];
let markerSizeMultiplier = 1.0;

// ==================== MARKER ICON FUNCTIONS ====================
function createStaticMarkerIcon(type, color, shape) {
    const hexColor = colorMap[color] || color;
    let baseSize = 12;
    if (type === 'start' || type === 'end') baseSize = 14;
    else if (type === 'intermediate') baseSize = 10;
    
    const size = Math.round(baseSize * markerSizeMultiplier);
    const shapeFunc = shapeMap[shape] || shapeMap['circle'];
    
    return L.divIcon({
        className: 'static-marker',
        iconSize: [size, size],
        iconAnchor: [size/2, size/2],
        popupAnchor: [0, -size/2],
        html: shapeFunc(hexColor, size)
    });
}

function createMovingMarkerIcon(color, shape) {
    const hexColor = colorMap[color] || color;
    const baseSize = 16;
    const size = Math.round(baseSize * markerSizeMultiplier);
    const shapeFunc = shapeMap[shape] || shapeMap['circle'];
    
    return L.divIcon({
        className: 'current-marker moving-marker',
        iconSize: [size, size],
        iconAnchor: [size/2, size/2],
        popupAnchor: [0, -size/2],
        html: shapeFunc(hexColor, size)
    });
}

// ==================== UTILITY FUNCTIONS ====================
function formatDate(isoString) {
    const date = new Date(isoString);
    return date.toLocaleString('ru-RU', {
        year: 'numeric', month: '2-digit', day: '2-digit',
        hour: '2-digit', minute: '2-digit'
    });
}

function interpolatePosition(p1, p2, t) {
    return { lat: p1.lat + (p2.lat - p1.lat) * t, lng: p1.lng + (p2.lng - p1.lng) * t };
}

function getPositionAtProgress(source, progress) {
    const points = source.points;
    if (!points || points.length === 0) return null;
    if (points.length === 1) return { lat: points[0].lat, lng: points[0].lng, pointIndex: 0, segmentProgress: 1 };
    
    progress = Math.max(0, Math.min(1, progress));
    const numSegments = points.length - 1;
    const segmentLength = 1 / numSegments;
    const segmentIndex = Math.min(Math.floor(progress / segmentLength), numSegments - 1);
    const segmentProgress = (progress - segmentIndex * segmentLength) / segmentLength;
    
    const p1 = points[segmentIndex];
    const p2 = points[segmentIndex + 1];
    const pos = interpolatePosition(p1, p2, segmentProgress);
    pos.pointIndex = segmentIndex;
    pos.segmentProgress = segmentProgress;
    
    if (progress >= 1) {
        const lastPoint = points[points.length - 1];
        return { lat: lastPoint.lat, lng: lastPoint.lng, pointIndex: points.length - 1, segmentProgress: 1 };
    }
    return pos;
}

// ==================== LAYER PANEL UI ====================
function renderLayerPanel() {
    // Base layers
    const baseLayersDiv = document.getElementById('baseLayers');
    baseLayersDiv.innerHTML = '';
    Object.keys(baseLayers).forEach(name => {
        const isActive = map.hasLayer(baseLayers[name]);
        const item = document.createElement('div');
        item.className = 'layer-item';
        item.innerHTML = `
            <input type="radio" name="baseLayer" ${isActive ? 'checked' : ''} data-layer="${name}">
            <span class="layer-name">${name}</span>
        `;
        item.querySelector('input').addEventListener('change', () => {
            Object.values(baseLayers).forEach(l => map.removeLayer(l));
            baseLayers[name].addTo(map);
            currentBaseLayer = baseLayers[name];
        });
        baseLayersDiv.appendChild(item);
    });
    
    // Markers layer control
    const markersDiv = document.getElementById('markersLayerControl');
    markersDiv.innerHTML = `
        <div class="layer-item ${markersLayerVisible ? '' : 'opacity-50'}">
            <input type="checkbox" id="markersLayerCheckbox" ${markersLayerVisible ? 'checked' : ''}>
            <span class="layer-name">Точки из базы (Playback)</span>
        </div>
    `;
    document.getElementById('markersLayerCheckbox').addEventListener('change', function() {
        markersLayerVisible = this.checked;
        if (markersLayerVisible) {
            markersLayerGroup.addTo(map);
            Object.values(sourceLayerGroups).forEach(g => g.addTo(map));
        } else {
            map.removeLayer(markersLayerGroup);
            Object.values(sourceLayerGroups).forEach(g => map.removeLayer(g));
        }
    });
    
    // Drawing layers
    renderDrawingLayers();
}

// Make this function global for CustomMarkerTool
window.renderDrawingLayers = renderDrawingLayers;
function renderDrawingLayers() {
    const drawingLayersDiv = document.getElementById('drawingLayers');
    drawingLayersDiv.innerHTML = '';
    
    if (Object.keys(drawingLayers).length === 0) {
        drawingLayersDiv.innerHTML = '<p style="font-size: 11px; color: #888; margin: 5px 0;">Нет слоёв рисования</p>';
        return;
    }
    
    Object.entries(drawingLayers).forEach(([layerId, layer]) => {
        const isActive = activeDrawingLayerId === layerId;
        const item = document.createElement('div');
        item.className = `layer-item ${isActive ? 'active' : ''}`;
        item.innerHTML = `
            <input type="checkbox" ${layer.visible ? 'checked' : ''} data-layer-id="${layerId}">
            <span class="layer-name" data-layer-id="${layerId}">${layer.name}</span>
            <div class="layer-actions">
                <button class="btn-expand" data-layer-id="${layerId}" title="Развернуть">▼</button>
                <button class="btn-edit" data-layer-id="${layerId}" title="Переименовать">✎</button>
                <button class="btn-delete" data-layer-id="${layerId}" title="Удалить">✕</button>
            </div>
        `;
        
        // Visibility toggle
        item.querySelector('input[type="checkbox"]').addEventListener('change', function() {
            toggleLayerVisibility(layerId, this.checked);
        });
        
        // Select as active
        item.querySelector('.layer-name').addEventListener('click', () => {
            setActiveDrawingLayer(layerId);
        });
        
        // Expand/collapse elements
        const expandBtn = item.querySelector('.btn-expand');
        expandBtn.addEventListener('click', () => {
            const children = item.nextElementSibling;
            if (children && children.classList.contains('layer-children')) {
                children.classList.toggle('expanded');
                expandBtn.textContent = children.classList.contains('expanded') ? '▲' : '▼';
            }
        });
        
        // Rename
        item.querySelector('.btn-edit').addEventListener('click', () => {
            const newName = prompt('Новое имя слоя:', layer.name);
            if (newName && newName.trim()) {
                layer.name = newName.trim();
                renderDrawingLayers();
            }
        });
        
        // Delete
        item.querySelector('.btn-delete').addEventListener('click', () => {
            if (confirm(`Удалить слой "${layer.name}"?`)) {
                deleteDrawingLayer(layerId);
            }
        });
        
        drawingLayersDiv.appendChild(item);
        
        // Elements list
        const childrenDiv = document.createElement('div');
        childrenDiv.className = 'layer-children';
        layer.elements.forEach((el, idx) => {
            const childItem = document.createElement('div');
            childItem.className = 'layer-child-item';
            const elType = getElementTypeName(el.layer);
            childItem.innerHTML = `
                <input type="checkbox" ${el.visible ? 'checked' : ''} data-el-idx="${idx}">
                <span class="layer-name" style="flex:1">${el.label || elType} #${idx + 1}</span>
                <div class="layer-actions">
                    <button class="btn-edit" data-el-idx="${idx}" title="Редактировать">✎</button>
                    <button class="btn-delete" data-el-idx="${idx}" title="Удалить">✕</button>
                </div>
            `;
            
            // Element visibility
            childItem.querySelector('input[type="checkbox"]').addEventListener('change', function() {
                toggleElementVisibility(layerId, idx, this.checked);
            });
            
            // Edit element
            childItem.querySelector('.btn-edit').addEventListener('click', () => {
                openStyleModal(layerId, idx);
            });
            
            // Delete element
            childItem.querySelector('.btn-delete').addEventListener('click', () => {
                deleteElement(layerId, idx);
            });
            
            childrenDiv.appendChild(childItem);
        });
        drawingLayersDiv.appendChild(childrenDiv);
    });
}

function getElementTypeName(layer) {
    if (layer instanceof L.Marker) return 'Маркер';
    if (layer instanceof L.Circle) return 'Круг';
    if (layer instanceof L.Rectangle) return 'Прямоугольник';
    if (layer instanceof L.Polygon) return 'Полигон';
    if (layer instanceof L.Polyline) return 'Линия';
    if (layer instanceof L.CircleMarker) return 'Точка';
    if (layer.pm && layer.pm.textArea) return 'Текст';
    return 'Элемент';
}

// ==================== LAYER OPERATIONS ====================
function createDrawingLayer(name) {
    const layerId = 'layer_' + (++layerIdCounter);
    const layerGroup = L.layerGroup().addTo(map);
    
    drawingLayers[layerId] = {
        name: name || `Слой ${layerIdCounter}`,
        layerGroup: layerGroup,
        visible: true,
        elements: []
    };
    
    setActiveDrawingLayer(layerId);
    renderDrawingLayers();
    return layerId;
}

function setActiveDrawingLayer(layerId) {
    _activeDrawingLayerId = layerId;
    activeDrawingLayerId = layerId;
    renderDrawingLayers();
}

function toggleLayerVisibility(layerId, visible) {
    const layer = drawingLayers[layerId];
    if (!layer) return;
    
    layer.visible = visible;
    if (visible) {
        layer.layerGroup.addTo(map);
    } else {
        map.removeLayer(layer.layerGroup);
    }
    renderDrawingLayers();
}

function toggleElementVisibility(layerId, elementIdx, visible) {
    const layer = drawingLayers[layerId];
    if (!layer || !layer.elements[elementIdx]) return;
    
    const el = layer.elements[elementIdx];
    el.visible = visible;
    
    if (visible) {
        layer.layerGroup.addLayer(el.layer);
    } else {
        layer.layerGroup.removeLayer(el.layer);
    }
}

function deleteDrawingLayer(layerId) {
    const layer = drawingLayers[layerId];
    if (!layer) return;
    
    map.removeLayer(layer.layerGroup);
    delete drawingLayers[layerId];
    
    if (activeDrawingLayerId === layerId) {
        const newActiveId = Object.keys(drawingLayers)[0] || null;
        _activeDrawingLayerId = newActiveId;
        activeDrawingLayerId = newActiveId;
    }
    renderDrawingLayers();
}

function deleteElement(layerId, elementIdx) {
    const layer = drawingLayers[layerId];
    if (!layer || !layer.elements[elementIdx]) return;
    
    const el = layer.elements[elementIdx];
    layer.layerGroup.removeLayer(el.layer);
    layer.elements.splice(elementIdx, 1);
    renderDrawingLayers();
}

// ==================== CUSTOM EDIT MODE ====================
// Make this global for CustomMarkerTool access
window.customEditModeActive = false;

function toggleCustomEditMode() {
    window.customEditModeActive = !window.customEditModeActive;
    
    const btn = document.querySelector('.leaflet-pm-icon-custom-edit');
    const indicator = document.getElementById('customEditIndicator');
    const mapContainer = map.getContainer();
    
    if (btn && btn.parentElement) {
        if (window.customEditModeActive) {
            btn.parentElement.classList.add('active');
            // Disable other modes
            map.pm.disableDraw();
            map.pm.disableGlobalEditMode();
            map.pm.disableGlobalDragMode();
            map.pm.disableGlobalRemovalMode();
            
            // Show indicator
            if (indicator) {
                indicator.classList.add('active');
            }
            
            // Add cursor class
            mapContainer.classList.add('custom-edit-mode');
            
            // Fire custom event
            map.fire('customeditmodetoggled', { enabled: true });
        } else {
            btn.parentElement.classList.remove('active');
            
            // Hide indicator
            if (indicator) {
                indicator.classList.remove('active');
            }
            
            // Remove cursor class
            mapContainer.classList.remove('custom-edit-mode');
            
            // Fire custom event
            map.fire('customeditmodetoggled', { enabled: false });
        }
    }
}

// Add custom edit mode control to Geoman
function addCustomEditControl() {
    const customEditAction = {
        name: 'customEdit',
        block: 'edit',
        title: 'Редактировать стили элементов',
        className: 'leaflet-pm-icon-custom-edit',
        toggle: true,
        onClick: () => {},
        afterClick: () => {
            toggleCustomEditMode();
        }
    };
    
    // map.pm.Toolbar.createCustomControl(customEditAction);
    
    // Add custom icon style
    const style = document.createElement('style');
    style.textContent = `
        .leaflet-pm-icon-custom-edit {
            background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiMzMzMiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNMTEgNEgyMGE0IDQgMCAwIDEgNCA0djhhNCA0IDAgMCAxLTQgNEg0YTQgNCAwIDAgMS00LTRWOGE0IDQgMCAwIDEgNC00aDciPjwvcGF0aD48cGF0aCBkPSJNOSAxNWgxMCI+PC9wYXRoPjxwYXRoIGQ9Ik05IDExaDE0Ij48L3BhdGg+PC9zdmc+');
            background-size: 18px 18px;
            background-position: center;
            background-repeat: no-repeat;
        }
    `;
    document.head.appendChild(style);
}

// ==================== GEOMAN EVENT HANDLERS ====================
map.on('pm:create', function(e) {
    const layer = e.layer;
    const shape = e.shape;
    
    // Ensure we have an active drawing layer
    if (!activeDrawingLayerId || !drawingLayers[activeDrawingLayerId]) {
        createDrawingLayer('Новый слой');
    }
    
    const activeLayer = drawingLayers[activeDrawingLayerId];
    
    // Handle Text elements specially - keep on map for Geoman text editing to work
    if (shape === 'Text') {
        const elementInfo = {
            layer: layer,
            visible: true,
            label: 'Текст',
            style: extractStyle(layer),
            isText: true
        };
        
        activeLayer.elements.push(elementInfo);
        // Don't move text layer - Geoman needs it on the map for editing
        
        renderDrawingLayers();
        return;
    }
    
    // Remove from map (will be added to layer group)
    map.removeLayer(layer);
    
    // Add to active layer group
    activeLayer.layerGroup.addLayer(layer);
    
    // Store element info
    const elementInfo = {
        layer: layer,
        visible: true,
        label: '',
        style: extractStyle(layer)
    };
    
    activeLayer.elements.push(elementInfo);
    
    // Add click handler for editing ONLY in custom edit mode
    // Capture layerId in closure for correct reference when clicked later
    const capturedLayerId = activeDrawingLayerId;
    layer.on('click', function(e) {
        if (window.customEditModeActive) {
            L.DomEvent.stopPropagation(e);
            const layerData = drawingLayers[capturedLayerId];
            if (layerData) {
                const idx = layerData.elements.findIndex(el => el.layer === layer);
                if (idx !== -1) {
                    openStyleModal(capturedLayerId, idx);
                }
            }
        }
    });
    
    renderDrawingLayers();
});

map.on('pm:remove', function(e) {
    const layer = e.layer;
    
    // Find and remove from our tracking
    Object.entries(drawingLayers).forEach(([layerId, layerData]) => {
        const idx = layerData.elements.findIndex(el => el.layer === layer);
        if (idx !== -1) {
            layerData.elements.splice(idx, 1);
        }
    });
    
    renderDrawingLayers();
});

// Helper function to disable custom edit mode
function disableCustomEditMode() {
    if (window.customEditModeActive) {
        window.customEditModeActive = false;
        
        const btn = document.querySelector('.leaflet-pm-icon-custom-edit');
        if (btn && btn.parentElement) {
            btn.parentElement.classList.remove('active');
        }
        
        const indicator = document.getElementById('customEditIndicator');
        if (indicator) {
            indicator.classList.remove('active');
        }
        
        const mapContainer = map.getContainer();
        mapContainer.classList.remove('custom-edit-mode');
    }
}

// Disable custom edit mode when other modes are activated
map.on('pm:globaldrawmodetoggled', (e) => {
    if (e.enabled) {
        disableCustomEditMode();
    }
});

map.on('pm:globaleditmodetoggled', (e) => {
    if (e.enabled) {
        disableCustomEditMode();
    }
});

map.on('pm:globaldragmodetoggled', (e) => {
    if (e.enabled) {
        disableCustomEditMode();
    }
});

map.on('pm:globalremovalmodetoggled', (e) => {
    if (e.enabled) {
        disableCustomEditMode();
    }
});

function extractStyle(layer) {
    if (layer.options) {
        return {
            color: layer.options.color || '#3388ff',
            fillColor: layer.options.fillColor || '#3388ff',
            fillOpacity: layer.options.fillOpacity || 0.2,
            weight: layer.options.weight || 3
        };
    }
    return { color: '#3388ff', fillColor: '#3388ff', fillOpacity: 0.2, weight: 3 };
}

// ==================== STYLE MODAL ====================
let currentEditingLayerId = null;
let currentEditingElementIdx = null;

// Make this function global for CustomMarkerTool
window.openStyleModal = openStyleModal;
function openStyleModal(layerId, elementIdx) {
    const layer = drawingLayers[layerId];
    if (!layer || !layer.elements[elementIdx]) return;
    
    currentEditingLayerId = layerId;
    currentEditingElementIdx = elementIdx;
    
    const el = layer.elements[elementIdx];
    const style = el.style || extractStyle(el.layer);
    
    document.getElementById('elementLabel').value = el.label || '';
    document.getElementById('elementColor').value = style.color || '#3388ff';
    document.getElementById('elementFillColor').value = style.fillColor || '#3388ff';
    document.getElementById('elementStrokeWidth').value = style.weight || 3;
    document.getElementById('elementOpacity').value = style.fillOpacity || 0.2;
    
    // Show/hide relevant fields based on element type
    const isMarker = el.layer instanceof L.Marker;
    const isLine = el.layer instanceof L.Polyline && !(el.layer instanceof L.Polygon);
    
    document.getElementById('fillColorGroup').style.display = isMarker || isLine ? 'none' : 'block';
    document.getElementById('opacityGroup').style.display = isMarker || isLine ? 'none' : 'block';
    document.getElementById('strokeWidthGroup').style.display = isMarker ? 'none' : 'block';
    
    document.getElementById('styleModalTitle').textContent = `Редактирование: ${getElementTypeName(el.layer)}`;
    document.getElementById('styleModalOverlay').classList.add('show');
    document.getElementById('styleModal').classList.add('show');
}

function closeStyleModal() {
    document.getElementById('styleModalOverlay').classList.remove('show');
    document.getElementById('styleModal').classList.remove('show');
    currentEditingLayerId = null;
    currentEditingElementIdx = null;
}

function saveStyleModal() {
    if (currentEditingLayerId === null || currentEditingElementIdx === null) return;
    
    const layer = drawingLayers[currentEditingLayerId];
    if (!layer || !layer.elements[currentEditingElementIdx]) return;
    
    const el = layer.elements[currentEditingElementIdx];
    
    el.label = document.getElementById('elementLabel').value;
    el.style = {
        color: document.getElementById('elementColor').value,
        fillColor: document.getElementById('elementFillColor').value,
        fillOpacity: parseFloat(document.getElementById('elementOpacity').value),
        weight: parseInt(document.getElementById('elementStrokeWidth').value)
    };
    
    // Apply style to layer
    if (el.layer.setStyle) {
        el.layer.setStyle(el.style);
    }
    
    // Update popup/tooltip with label
    if (el.label) {
        el.layer.bindTooltip(el.label, { permanent: false, direction: 'top' });
    } else {
        el.layer.unbindTooltip();
    }
    
    closeStyleModal();
    renderDrawingLayers();
}

document.getElementById('styleModalCancel').addEventListener('click', closeStyleModal);
document.getElementById('styleModalSave').addEventListener('click', saveStyleModal);
document.getElementById('styleModalOverlay').addEventListener('click', closeStyleModal);

// ==================== IMPORT/EXPORT ====================
function exportDrawingLayers() {
    const exportData = {
        version: 2,
        layers: {}
    };
    
    Object.entries(drawingLayers).forEach(([layerId, layer]) => {
        const layerExport = {
            name: layer.name,
            elements: []
        };
        
        layer.elements.forEach(el => {
            const elExport = {
                type: getElementTypeName(el.layer),
                label: el.label,
                style: el.style,
                geojson: el.layer.toGeoJSON ? el.layer.toGeoJSON() : null
            };
            
            // Handle markers specially - save custom marker data
            if (el.layer instanceof L.Marker) {
                const latlng = el.layer.getLatLng();
                elExport.latlng = { lat: latlng.lat, lng: latlng.lng };
                
                // Check if it's a custom marker with shape/color info in style
                if (el.style && el.style.shape) {
                    elExport.isCustomMarker = true;
                    elExport.customStyle = {
                        shape: el.style.shape,
                        color: el.style.color, // Can be hex or color name
                        size: el.style.size || 1.0,
                        opacity: el.style.opacity || 1.0
                    };
                }
            }
            
            // Handle circles
            if (el.layer instanceof L.Circle) {
                elExport.radius = el.layer.getRadius();
            }
            
            // Handle text layers
            if (el.isText || (el.layer.pm && el.layer.pm.textArea)) {
                elExport.isText = true;
                elExport.text = el.layer.pm && el.layer.pm.getText ? el.layer.pm.getText() : (el.label || '');
                // Save position for text
                if (el.layer.getLatLng) {
                    const latlng = el.layer.getLatLng();
                    elExport.latlng = { lat: latlng.lat, lng: latlng.lng };
                }
            }
            
            // Handle imported text markers
            if (el.style && el.style.isImportedText) {
                elExport.isText = true;
                elExport.text = el.style.textContent || el.label || '';
                if (el.layer.getLatLng) {
                    const latlng = el.layer.getLatLng();
                    elExport.latlng = { lat: latlng.lat, lng: latlng.lng };
                }
            }
            
            layerExport.elements.push(elExport);
        });
        
        exportData.layers[layerId] = layerExport;
    });
    
    const blob = new Blob([JSON.stringify(exportData, null, 2)], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `map_layers_${new Date().toISOString().slice(0,10)}.json`;
    a.click();
    URL.revokeObjectURL(url);
}

// Helper function to create custom marker icon for import
function createCustomMarkerIcon(customStyle) {
    const colorInput = customStyle.color;
    // Handle both color names (e.g. 'red') and hex colors (e.g. '#dc3545')
    let hexColor;
    if (colorInput && colorInput.startsWith('#')) {
        hexColor = colorInput; // Already a hex color
    } else {
        hexColor = colorMap[colorInput] || colorInput || '#3388ff';
    }
    
    const baseSize = 16;
    const size = Math.round(baseSize * (customStyle.size || 1.0));
    const shape = customStyle.shape || 'circle';
    const shapeFunc = shapeMap[shape] || shapeMap['circle'];
    const opacity = customStyle.opacity || 1.0;
    
    return L.divIcon({
        className: 'custom-placed-marker',
        iconSize: [size, size],
        iconAnchor: [size/2, size/2],
        popupAnchor: [0, -size/2],
        html: `<div style="opacity: ${opacity}">${shapeFunc(hexColor, size)}</div>`
    });
}

function importDrawingLayers(file) {
    const reader = new FileReader();
    reader.onload = function(e) {
        try {
            const data = JSON.parse(e.target.result);
            
            if (!data.layers) {
                alert('Неверный формат файла');
                return;
            }
            
            Object.entries(data.layers).forEach(([_, layerData]) => {
                const newLayerId = createDrawingLayer(layerData.name);
                const newLayer = drawingLayers[newLayerId];
                
                layerData.elements.forEach(elData => {
                    let layer = null;
                    let elementStyle = elData.style || {};
                    let isTextElement = false;
                    
                    // Handle text elements first - they need special treatment
                    if (elData.isText || elData.type === 'Текст') {
                        // Text elements cannot be fully restored programmatically
                        // Create a marker with text label as fallback
                        if (elData.latlng || (elData.geojson && elData.geojson.geometry)) {
                            let lat, lng;
                            if (elData.latlng) {
                                lat = elData.latlng.lat;
                                lng = elData.latlng.lng;
                            } else {
                                const coords = elData.geojson.geometry.coordinates;
                                lng = coords[0];
                                lat = coords[1];
                            }
                            
                            // Create a text marker using divIcon
                            const textContent = elData.text || elData.label || 'Текст';
                            const textIcon = L.divIcon({
                                className: 'imported-text-marker',
                                html: `<div style="background: white; padding: 4px 8px; border: 1px solid #333; border-radius: 3px; white-space: nowrap; font-size: 14px;">${textContent}</div>`,
                                iconSize: null,
                                iconAnchor: [0, 0]
                            });
                            layer = L.marker([lat, lng], { icon: textIcon });
                            elementStyle.isImportedText = true;
                            elementStyle.textContent = textContent;
                            isTextElement = true;
                        }
                    }
                    // Handle custom markers with shape/color
                    else if (elData.type === 'Маркер' && elData.latlng) {
                        if (elData.isCustomMarker && elData.customStyle) {
                            // Restore custom marker with icon
                            const icon = createCustomMarkerIcon(elData.customStyle);
                            layer = L.marker([elData.latlng.lat, elData.latlng.lng], { icon: icon });
                            // Preserve custom style info
                            elementStyle = {
                                ...elementStyle,
                                shape: elData.customStyle.shape,
                                color: elData.customStyle.color,
                                size: elData.customStyle.size,
                                opacity: elData.customStyle.opacity
                            };
                        } else {
                            // Standard marker
                            layer = L.marker([elData.latlng.lat, elData.latlng.lng]);
                        }
                    } else if (elData.type === 'Круг' && elData.geojson && elData.radius) {
                        const coords = elData.geojson.geometry.coordinates;
                        layer = L.circle([coords[1], coords[0]], { radius: elData.radius });
                    } else if (elData.geojson) {
                        layer = L.geoJSON(elData.geojson).getLayers()[0];
                    }
                    
                    if (layer) {
                        if (elData.style && layer.setStyle) {
                            layer.setStyle(elData.style);
                        }
                        
                        newLayer.layerGroup.addLayer(layer);
                        
                        const elementInfo = {
                            layer: layer,
                            visible: true,
                            label: elData.label || '',
                            style: elementStyle
                        };
                        
                        if (elData.label) {
                            layer.bindTooltip(elData.label, { permanent: false, direction: 'top' });
                            layer.bindPopup(`<b>${elData.label}</b>`);
                        }
                        
                        // Capture layerId for click handler
                        const capturedLayerId = newLayerId;
                        layer.on('click', function(e) {
                            if (window.customEditModeActive) {
                                L.DomEvent.stopPropagation(e);
                                const ld = drawingLayers[capturedLayerId];
                                if (ld) {
                                    const idx = ld.elements.findIndex(el => el.layer === layer);
                                    if (idx !== -1) {
                                        openStyleModal(capturedLayerId, idx);
                                    }
                                }
                            }
                        });
                        
                        newLayer.elements.push(elementInfo);
                    }
                });
            });
            
            renderDrawingLayers();
            alert('Слои успешно импортированы');
        } catch (err) {
            console.error('Import error:', err);
            alert('Ошибка при импорте: ' + err.message);
        }
    };
    reader.readAsText(file);
}

document.getElementById('exportLayersBtn').addEventListener('click', exportDrawingLayers);
document.getElementById('importLayersBtn').addEventListener('click', () => {
    document.getElementById('importFileInput').click();
});
document.getElementById('importFileInput').addEventListener('change', function() {
    if (this.files.length > 0) {
        importDrawingLayers(this.files[0]);
        this.value = '';
    }
});

// ==================== LAYER PANEL TOGGLE ====================
document.getElementById('layerToggleBtn').addEventListener('click', () => {
    const panel = document.getElementById('layerManagerPanel');
    const btn = document.getElementById('layerToggleBtn');
    if (panel.style.display === 'none') {
        panel.style.display = 'flex';
        btn.style.display = 'none';
    }
});

document.getElementById('closeLayerPanel').addEventListener('click', () => {
    document.getElementById('layerManagerPanel').style.display = 'none';
    document.getElementById('layerToggleBtn').style.display = 'block';
});

document.getElementById('addDrawingLayerBtn').addEventListener('click', () => {
    const name = prompt('Название нового слоя:', `Слой ${layerIdCounter + 1}`);
    if (name && name.trim()) {
        createDrawingLayer(name.trim());
    }
});

// Prevent map interactions on panel
const layerPanel = document.getElementById('layerManagerPanel');
L.DomEvent.disableScrollPropagation(layerPanel);
L.DomEvent.disableClickPropagation(layerPanel);
</script>

<script>
// ==================== PLAYBACK FUNCTIONS ====================
function updateDisplay(progress) {
    const timeDisplay = document.getElementById('timeDisplay');
    const slider = document.getElementById('timeSlider');
    slider.value = progress * 100;
    
    const progressPercent = Math.round(progress * 100);
    timeDisplay.textContent = `Прогресс: ${progressPercent}%`;
    
    sourcesData.forEach(source => {
        const pos = getPositionAtProgress(source, progress);
        const color = source.color;
        const shape = source.shape;
        
        if (pos) {
            const isAtEnd = (progress >= 1 || pos.pointIndex === source.points.length - 1) && pos.segmentProgress >= 0.99;
            
            if (isAtEnd) {
                if (currentMarkers[source.source_id]) {
                    sourceLayerGroups[source.source_id].removeLayer(currentMarkers[source.source_id]);
                    delete currentMarkers[source.source_id];
                }
            } else {
                if (!currentMarkers[source.source_id]) {
                    const firstPointName = source.points && source.points.length > 0 ? source.points[0].name : '';
                    const popupContent = `<b>ID ${source.source_id}:</b> ${firstPointName}<br><i style="color: #666;">Текущая позиция</i>`;
                    
                    currentMarkers[source.source_id] = L.marker([pos.lat, pos.lng], {
                        icon: createMovingMarkerIcon(color, shape),
                        zIndexOffset: 1000
                    }).bindPopup(popupContent);
                    sourceLayerGroups[source.source_id].addLayer(currentMarkers[source.source_id]);
                } else {
                    currentMarkers[source.source_id].setLatLng([pos.lat, pos.lng]);
                }
            }
            
            const trailCoords = [];
            for (let i = 0; i <= pos.pointIndex; i++) {
                trailCoords.push([source.points[i].lat, source.points[i].lng]);
            }
            trailCoords.push([pos.lat, pos.lng]);
            
            if (trailPolylines[source.source_id]) {
                trailPolylines[source.source_id].setLatLngs(trailCoords);
            }
            
            source.points.forEach((point, idx) => {
                const markerKey = `${source.source_id}_${idx}`;
                if (staticMarkers[markerKey]) return;
                
                if (idx <= pos.pointIndex) {
                    let markerType = 'intermediate';
                    let popupPrefix = '';
                    
                    if (idx === 0) {
                        markerType = 'start';
                        popupPrefix = '<span style="color: green;">▶ Начало</span><br>';
                    } else if (idx === source.points.length - 1) {
                        markerType = 'end';
                        popupPrefix = '<span style="color: red;">■ Конец</span><br>';
                    } else {
                        popupPrefix = `<span style="color: gray;">● Точка ${idx + 1}</span><br>`;
                    }
                    
                    const marker = L.marker([point.lat, point.lng], {
                        icon: createStaticMarkerIcon(markerType, color, shape),
                        zIndexOffset: markerType === 'start' ? 500 : (markerType === 'end' ? 600 : 100)
                    }).bindPopup(`<b>${source.source_name}</b><br>${popupPrefix}${point.name}<br>${point.frequency}<br>${formatDate(point.timestamp)}`);
                    
                    sourceLayerGroups[source.source_id].addLayer(marker);
                    staticMarkers[markerKey] = marker;
                }
            });
            
            if (progress >= 1 || pos.pointIndex === source.points.length - 1) {
                const endMarkerKey = `${source.source_id}_${source.points.length - 1}`;
                if (!staticMarkers[endMarkerKey] && source.points.length > 1) {
                    const lastPoint = source.points[source.points.length - 1];
                    const endMarker = L.marker([lastPoint.lat, lastPoint.lng], {
                        icon: createStaticMarkerIcon('end', color, shape),
                        zIndexOffset: 600
                    }).bindPopup(`<b>${source.source_name}</b><br><span style="color: red;">■ Конец</span><br>${lastPoint.name}<br>${lastPoint.frequency}<br>${formatDate(lastPoint.timestamp)}`);
                    sourceLayerGroups[source.source_id].addLayer(endMarker);
                    staticMarkers[endMarkerKey] = endMarker;
                }
            }
        }
    });
}

function resetPlayback() {
    Object.values(sourceLayerGroups).forEach(group => group.clearLayers());
    currentMarkers = {};
    staticMarkers = {};
    
    sourcesData.forEach(source => {
        const color = colorMap[source.color] || source.color;
        const shape = source.shape;
        
        trailPolylines[source.source_id] = L.polyline([], {
            color: color,
            weight: 2,
            opacity: 0.7,
            dashArray: '5, 10'
        });
        sourceLayerGroups[source.source_id].addLayer(trailPolylines[source.source_id]);
        
        if (source.points && source.points.length > 0) {
            const firstPoint = source.points[0];
            const startMarker = L.marker([firstPoint.lat, firstPoint.lng], {
                icon: createStaticMarkerIcon('start', color, shape),
                zIndexOffset: 500
            }).bindPopup(`<b>${source.source_name}</b><br><span style="color: green;">▶ Начало</span><br>${firstPoint.name}<br>${firstPoint.frequency}<br>${formatDate(firstPoint.timestamp)}`);
            sourceLayerGroups[source.source_id].addLayer(startMarker);
            staticMarkers[`${source.source_id}_0`] = startMarker;
        }
    });
    
    currentProgress = 0;
    updateDisplay(currentProgress);
}

function updateMarkerSizes() {
    pause();
    const currentProg = currentProgress;
    resetPlayback();
    currentProgress = currentProg;
    updateDisplay(currentProgress);
}

function play() {
    if (playbackInterval) return;
    
    document.getElementById('playBtn').disabled = true;
    document.getElementById('pauseBtn').disabled = false;
    
    const progressStep = 1 / totalSteps;
    
    playbackInterval = setInterval(() => {
        currentProgress += progressStep * speedMultiplier;
        
        if (currentProgress >= 1) {
            currentProgress = 1;
            pause();
        }
        
        updateDisplay(currentProgress);
    }, playbackSpeed);
}

function pause() {
    if (playbackInterval) {
        clearInterval(playbackInterval);
        playbackInterval = null;
    }
    document.getElementById('playBtn').disabled = false;
    document.getElementById('pauseBtn').disabled = true;
}

// ==================== LEGEND ====================
function addLegend() {
    const legend = L.control({ position: 'bottomleft' });
    legend.onAdd = function(map) {
        const div = L.DomUtil.create('div', 'legend');
        
        L.DomEvent.disableScrollPropagation(div);
        L.DomEvent.disableClickPropagation(div);
        
        let html = '<h6><strong>Объекты</strong></h6>';
        
        sourcesData.forEach(source => {
            const color = colorMap[source.color] || source.color;
            const shape = source.shape;
            const points = source.points;
            
            const shapeFunc = shapeMap[shape] || shapeMap['circle'];
            const shapePreview = shapeFunc(color, 16);
            
            let firstPointName = '';
            let timeInfo = '';
            if (points && points.length > 0) {
                firstPointName = points[0].name || '';
                const firstDate = formatDate(points[0].timestamp).split(',')[0];
                const lastDate = formatDate(points[points.length - 1].timestamp).split(',')[0];
                if (firstDate !== lastDate) {
                    timeInfo = `<br><small style="color: #666;">${firstDate} — ${lastDate}</small>`;
                } else {
                    timeInfo = `<br><small style="color: #666;">${firstDate}</small>`;
                }
            }
            
            html += `
                <div class="legend-item" style="flex-direction: column; align-items: flex-start; margin-bottom: 8px;">
                    <div style="display: flex; align-items: center;">
                        <div style="width: 20px; height: 20px; display: flex; align-items: center; justify-content: center; margin-right: 6px;">
                            ${shapePreview}
                        </div>
                        <span><strong>ID ${source.source_id}:</strong> ${firstPointName}</span>
                    </div>
                    <div style="margin-left: 26px;">
                        <small style="color: #666;">${source.points_count} точек</small>
                        ${timeInfo}
                    </div>
                </div>
            `;
        });
        
        div.innerHTML = html;
        return div;
    };
    legend.addTo(map);
}

// ==================== DATA LOADING ====================
async function loadData() {
    try {
        const response = await fetch(`${API_URL}?ids=${SOURCE_IDS}`);
        const data = await response.json();
        
        if (data.error) {
            throw new Error(data.error);
        }
        
        sourcesData = data.sources;
        timeRange = data.time_range;
        
        sourcesData = sourcesData.filter(s => s.points && s.points.length > 0);
        
        sourcesData.forEach((source, idx) => {
            source.shape = availableShapes[idx % availableShapes.length];
        });
        
        if (!sourcesData || sourcesData.length === 0) {
            document.getElementById('loadingOverlay').innerHTML = `
                <div class="alert alert-warning">
                    <h5>Нет данных для отображения</h5>
                    <p>Выбранные источники не содержат точек с временными метками.</p>
                    <a href="{% url 'mainapp:source_list' %}" class="btn btn-primary">Вернуться к списку</a>
                </div>
            `;
            return;
        }
        
        const bounds = L.latLngBounds();
        
        sourcesData.forEach(source => {
            sourceLayerGroups[source.source_id] = L.layerGroup().addTo(map);
            source.points.forEach(point => {
                bounds.extend([point.lat, point.lng]);
            });
        });
        
        if (bounds.isValid()) {
            map.fitBounds(bounds.pad(0.1));
        }
        
        const slider = document.getElementById('timeSlider');
        slider.min = 0;
        slider.max = 100;
        slider.value = 0;
        
        addLegend();
        resetPlayback();
        
        document.getElementById('loadingOverlay').style.display = 'none';
        const playbackControl = document.getElementById('playbackControl');
        playbackControl.style.display = 'flex';
        
        L.DomEvent.disableScrollPropagation(playbackControl);
        L.DomEvent.disableClickPropagation(playbackControl);
        
        // Setup playback event listeners
        document.getElementById('playBtn').addEventListener('click', play);
        document.getElementById('pauseBtn').addEventListener('click', pause);
        document.getElementById('resetBtn').addEventListener('click', () => {
            pause();
            resetPlayback();
        });
        
        slider.addEventListener('input', function() {
            pause();
            const newProgress = this.value / 100;
            if (newProgress < currentProgress) {
                resetPlayback();
            }
            currentProgress = newProgress;
            updateDisplay(currentProgress);
        });
        
        document.getElementById('speedSelect').addEventListener('change', function() {
            speedMultiplier = parseFloat(this.value);
        });
        
        // Marker size control
        const markerSizeSlider = document.getElementById('markerSizeSlider');
        const sizeValue = document.getElementById('sizeValue');
        
        markerSizeSlider.addEventListener('input', function() {
            markerSizeMultiplier = parseFloat(this.value);
            sizeValue.textContent = markerSizeMultiplier.toFixed(1) + 'x';
            updateMarkerSizes();
        });
        
        const markerSizeControl = document.querySelector('.marker-size-control');
        L.DomEvent.disableScrollPropagation(markerSizeControl);
        L.DomEvent.disableClickPropagation(markerSizeControl);
        
        // Initialize layer panel
        renderLayerPanel();
        
        // Create default drawing layer
        createDrawingLayer('Рисунки');
        
        // Initialize custom marker tool
        const customMarkerTool = new CustomMarkerTool(map, shapeMap, colorMap);
        
    } catch (error) {
        console.error('Error loading data:', error);
        document.getElementById('loadingOverlay').innerHTML = `
            <div class="alert alert-danger">
                <h5>Ошибка загрузки данных</h5>
                <p>${error.message}</p>
                <a href="{% url 'mainapp:source_list' %}" class="btn btn-primary">Вернуться к списку</a>
            </div>
        `;
    }
}

// Start loading
loadData();
</script>
{% endblock extra_js %}
