/**
 * Arma 3 Map Viewer
 * Vanilla JavaScript map system with pan, zoom, markers, and grid overlay
 */

(function () {
    'use strict';

    // ===================
    // Configuration
    // ===================
    const CONFIG = {
        mapSize: 8192,           // SVG map dimensions
        minZoom: 0.05,           // Minimum zoom level (5%)
        maxZoom: 4,              // Maximum zoom level (400%)
        zoomStep: 0.15,          // Zoom increment per step
        storageKey: 'arma3MapViewer'
    };

    // ===================
    // State
    // ===================
    const state = {
        zoom: 0.1,
        panX: 0,
        panY: 0,
        isPanning: false,
        startX: 0,
        startY: 0,
        markers: [],
        pendingMarker: null,
        selectedColor: '#ff4444',
        currentMap: '../Stratis_Map.svg'
    };

    // ===================
    // DOM Elements
    // ===================
    const elements = {};

    function cacheElements() {
        elements.mapContainer = document.getElementById('mapContainer');
        elements.mapViewport = document.getElementById('mapViewport');
        elements.mapObject = document.getElementById('mapObject');
        elements.mapSelect = document.getElementById('mapSelect');
        elements.zoomIn = document.getElementById('zoomIn');
        elements.zoomOut = document.getElementById('zoomOut');
        elements.zoomReset = document.getElementById('zoomReset');
        elements.zoomLevel = document.getElementById('zoomLevel');
        elements.coordsX = document.getElementById('coordsX');
        elements.coordsY = document.getElementById('coordsY');
        elements.markersLayer = document.getElementById('markersLayer');
        elements.clearMarkers = document.getElementById('clearMarkers');
        elements.sidebar = document.getElementById('sidebar');
        elements.toggleSidebar = document.getElementById('toggleSidebar');
        elements.markerList = document.getElementById('markerList');
        elements.contextMenu = document.getElementById('contextMenu');
        elements.markerModal = document.getElementById('markerModal');
        elements.markerName = document.getElementById('markerName');
        elements.cancelMarker = document.getElementById('cancelMarker');
        elements.saveMarker = document.getElementById('saveMarker');
        elements.colorBtns = document.querySelectorAll('.color-btn');
    }

    // ===================
    // Transform & Rendering
    // ===================
    function updateTransform() {
        elements.mapViewport.style.transform =
            `translate(${state.panX}px, ${state.panY}px) scale(${state.zoom})`;
    }

    function updateZoomDisplay() {
        elements.zoomLevel.textContent = Math.round(state.zoom * 100) + '%';
    }

    function clampPan() {
        const container = elements.mapContainer.getBoundingClientRect();
        const scaledSize = CONFIG.mapSize * state.zoom;

        // Allow some overflow but keep map mostly visible
        const minX = container.width - scaledSize - 100;
        const minY = container.height - scaledSize - 100;
        const maxX = 100;
        const maxY = 100;

        state.panX = Math.max(minX, Math.min(maxX, state.panX));
        state.panY = Math.max(minY, Math.min(maxY, state.panY));
    }

    // ===================
    // Coordinate Conversion
    // ===================
    function screenToMap(screenX, screenY) {
        const rect = elements.mapContainer.getBoundingClientRect();
        const x = (screenX - rect.left - state.panX) / state.zoom;
        const y = (screenY - rect.top - state.panY) / state.zoom;
        return { x, y };
    }

    function mapToArma(mapX, mapY) {
        // Convert SVG coordinates to Arma 3 grid coordinates
        // Arma Y is inverted (0 at bottom)
        return {
            x: Math.round(mapX),
            y: Math.round(CONFIG.mapSize - mapY)
        };
    }

    function updateCoordinates(e) {
        const mapCoords = screenToMap(e.clientX, e.clientY);
        const armaCoords = mapToArma(mapCoords.x, mapCoords.y);

        elements.coordsX.textContent = `X: ${armaCoords.x}`;
        elements.coordsY.textContent = `Y: ${armaCoords.y}`;
    }

    // ===================
    // Zoom Functions
    // ===================
    function zoomAt(delta, centerX, centerY) {
        const oldZoom = state.zoom;
        state.zoom = Math.max(CONFIG.minZoom, Math.min(CONFIG.maxZoom, state.zoom * (1 + delta)));

        // Zoom towards cursor position
        const zoomRatio = state.zoom / oldZoom;
        const rect = elements.mapContainer.getBoundingClientRect();
        const mouseX = centerX - rect.left;
        const mouseY = centerY - rect.top;

        state.panX = mouseX - (mouseX - state.panX) * zoomRatio;
        state.panY = mouseY - (mouseY - state.panY) * zoomRatio;

        clampPan();
        updateTransform();
        updateZoomDisplay();
        saveState();
    }

    function zoomIn() {
        const rect = elements.mapContainer.getBoundingClientRect();
        zoomAt(CONFIG.zoomStep, rect.left + rect.width / 2, rect.top + rect.height / 2);
    }

    function zoomOut() {
        const rect = elements.mapContainer.getBoundingClientRect();
        zoomAt(-CONFIG.zoomStep, rect.left + rect.width / 2, rect.top + rect.height / 2);
    }

    function resetView() {
        const container = elements.mapContainer.getBoundingClientRect();

        // Fit map to container
        state.zoom = Math.min(
            container.width / CONFIG.mapSize,
            container.height / CONFIG.mapSize
        ) * 0.9;

        // Center map
        const scaledSize = CONFIG.mapSize * state.zoom;
        state.panX = (container.width - scaledSize) / 2;
        state.panY = (container.height - scaledSize) / 2;

        updateTransform();
        updateZoomDisplay();
        saveState();
    }

    // ===================
    // Pan Functions
    // ===================
    function startPan(e) {
        if (e.button !== 0) return; // Only left click
        state.isPanning = true;
        state.startX = e.clientX - state.panX;
        state.startY = e.clientY - state.panY;
        elements.mapContainer.style.cursor = 'grabbing';
    }

    function doPan(e) {
        if (!state.isPanning) return;
        state.panX = e.clientX - state.startX;
        state.panY = e.clientY - state.startY;
        clampPan();
        updateTransform();
    }

    function endPan() {
        if (state.isPanning) {
            state.isPanning = false;
            elements.mapContainer.style.cursor = 'grab';
            saveState();
        }
    }

    // ===================
    // Markers
    // ===================
    function createMarkerElement(marker) {
        const el = document.createElement('div');
        el.className = 'marker';
        el.style.left = marker.x + 'px';
        el.style.top = marker.y + 'px';
        el.style.color = marker.color;
        el.dataset.id = marker.id;

        const label = document.createElement('span');
        label.className = 'marker-label';
        label.textContent = marker.name;
        el.appendChild(label);

        el.addEventListener('click', (e) => {
            e.stopPropagation();
            panToMarker(marker);
        });

        el.addEventListener('contextmenu', (e) => {
            e.preventDefault();
            e.stopPropagation();
            deleteMarker(marker.id);
        });

        return el;
    }

    function addMarker(x, y, name, color) {
        const marker = {
            id: Date.now().toString(),
            x,
            y,
            name: name || `Marker ${state.markers.length + 1}`,
            color: color || state.selectedColor
        };

        state.markers.push(marker);
        elements.markersLayer.appendChild(createMarkerElement(marker));
        updateMarkerList();
        saveState();
    }

    function deleteMarker(id) {
        const index = state.markers.findIndex(m => m.id === id);
        if (index !== -1) {
            state.markers.splice(index, 1);
            const el = elements.markersLayer.querySelector(`[data-id="${id}"]`);
            if (el) el.remove();
            updateMarkerList();
            saveState();
        }
    }

    function clearAllMarkers() {
        if (state.markers.length === 0) return;
        if (confirm('Clear all markers?')) {
            state.markers = [];
            elements.markersLayer.innerHTML = '';
            updateMarkerList();
            saveState();
        }
    }

    function panToMarker(marker) {
        const container = elements.mapContainer.getBoundingClientRect();
        state.panX = container.width / 2 - marker.x * state.zoom;
        state.panY = container.height / 2 - marker.y * state.zoom;
        clampPan();
        updateTransform();
        saveState();
    }

    function updateMarkerList() {
        if (state.markers.length === 0) {
            elements.markerList.innerHTML = '<p class="empty-state">Click on the map to add markers</p>';
            return;
        }

        elements.markerList.innerHTML = state.markers.map(marker => {
            const armaCoords = mapToArma(marker.x, marker.y);
            return `
                <div class="marker-item" data-id="${marker.id}">
                    <div class="marker-color" style="background:${marker.color}"></div>
                    <div class="marker-info">
                        <div class="marker-name">${escapeHtml(marker.name)}</div>
                        <div class="marker-coords">${armaCoords.x}, ${armaCoords.y}</div>
                    </div>
                    <button class="marker-delete" data-id="${marker.id}">✕</button>
                </div>
            `;
        }).join('');

        // Add click handlers
        elements.markerList.querySelectorAll('.marker-item').forEach(item => {
            item.addEventListener('click', (e) => {
                if (e.target.classList.contains('marker-delete')) return;
                const marker = state.markers.find(m => m.id === item.dataset.id);
                if (marker) panToMarker(marker);
            });
        });

        elements.markerList.querySelectorAll('.marker-delete').forEach(btn => {
            btn.addEventListener('click', (e) => {
                e.stopPropagation();
                deleteMarker(btn.dataset.id);
            });
        });
    }

    function renderMarkers() {
        elements.markersLayer.innerHTML = '';
        state.markers.forEach(marker => {
            elements.markersLayer.appendChild(createMarkerElement(marker));
        });
    }

    // ===================
    // Context Menu
    // ===================
    function showContextMenu(e) {
        e.preventDefault();
        const mapCoords = screenToMap(e.clientX, e.clientY);

        // Check if click is within map bounds
        if (mapCoords.x < 0 || mapCoords.x > CONFIG.mapSize ||
            mapCoords.y < 0 || mapCoords.y > CONFIG.mapSize) {
            return;
        }

        state.pendingMarker = { x: mapCoords.x, y: mapCoords.y };

        elements.contextMenu.style.left = e.clientX + 'px';
        elements.contextMenu.style.top = e.clientY + 'px';
        elements.contextMenu.classList.add('visible');
    }

    function hideContextMenu() {
        elements.contextMenu.classList.remove('visible');
    }

    function handleContextAction(action) {
        hideContextMenu();

        if (!state.pendingMarker) return;

        if (action === 'marker') {
            showMarkerModal();
        } else if (action === 'coords') {
            const armaCoords = mapToArma(state.pendingMarker.x, state.pendingMarker.y);
            const coordString = `${armaCoords.x}, ${armaCoords.y}`;
            navigator.clipboard.writeText(coordString).then(() => {
                console.log('Coordinates copied:', coordString);
            });
        }
    }

    // ===================
    // Marker Modal
    // ===================
    function showMarkerModal() {
        elements.markerModal.classList.add('visible');
        elements.markerName.value = '';
        elements.markerName.focus();
    }

    function hideMarkerModal() {
        elements.markerModal.classList.remove('visible');
        state.pendingMarker = null;
    }

    function saveMarkerFromModal() {
        if (!state.pendingMarker) return;

        const name = elements.markerName.value.trim() || `Marker ${state.markers.length + 1}`;
        addMarker(state.pendingMarker.x, state.pendingMarker.y, name, state.selectedColor);
        hideMarkerModal();
    }

    function selectColor(color) {
        state.selectedColor = color;
        elements.colorBtns.forEach(btn => {
            btn.classList.toggle('active', btn.dataset.color === color);
        });
    }

    // ===================
    // Map Switching
    // ===================
    function switchMap(mapPath) {
        state.currentMap = mapPath;
        elements.mapObject.data = mapPath;
        elements.mapContainer.classList.add('loading');

        elements.mapObject.onload = () => {
            elements.mapContainer.classList.remove('loading');
            resetView();
        };

        saveState();
    }

    // ===================
    // Sidebar
    // ===================
    function toggleSidebar() {
        elements.sidebar.classList.toggle('collapsed');
        elements.toggleSidebar.textContent =
            elements.sidebar.classList.contains('collapsed') ? '▶' : '◀';
    }

    // ===================
    // Persistence
    // ===================
    function saveState() {
        const data = {
            zoom: state.zoom,
            panX: state.panX,
            panY: state.panY,
            markers: state.markers,
            currentMap: state.currentMap
        };
        localStorage.setItem(CONFIG.storageKey, JSON.stringify(data));
    }

    function loadState() {
        try {
            const data = JSON.parse(localStorage.getItem(CONFIG.storageKey));
            if (data) {
                state.zoom = data.zoom || 0.1;
                state.panX = data.panX || 0;
                state.panY = data.panY || 0;
                state.markers = data.markers || [];
                state.currentMap = data.currentMap || '../Stratis_Map.svg';
            }
        } catch (e) {
            console.warn('Failed to load state:', e);
        }
    }

    // ===================
    // Utility
    // ===================
    function escapeHtml(text) {
        const div = document.createElement('div');
        div.textContent = text;
        return div.innerHTML;
    }

    // ===================
    // Event Binding
    // ===================
    function bindEvents() {
        // Zoom controls
        elements.zoomIn.addEventListener('click', zoomIn);
        elements.zoomOut.addEventListener('click', zoomOut);
        elements.zoomReset.addEventListener('click', resetView);

        // Mouse wheel zoom
        elements.mapContainer.addEventListener('wheel', (e) => {
            e.preventDefault();
            const delta = e.deltaY > 0 ? -CONFIG.zoomStep : CONFIG.zoomStep;
            zoomAt(delta, e.clientX, e.clientY);
        }, { passive: false });

        // Pan controls
        elements.mapContainer.addEventListener('mousedown', startPan);
        document.addEventListener('mousemove', (e) => {
            doPan(e);
            if (!state.isPanning) updateCoordinates(e);
        });
        document.addEventListener('mouseup', endPan);
        document.addEventListener('mouseleave', endPan);

        // Context menu
        elements.mapContainer.addEventListener('contextmenu', showContextMenu);
        document.addEventListener('click', hideContextMenu);
        elements.contextMenu.querySelectorAll('.context-item').forEach(item => {
            item.addEventListener('click', (e) => {
                e.stopPropagation();
                handleContextAction(item.dataset.action);
            });
        });

        // Marker modal
        elements.cancelMarker.addEventListener('click', hideMarkerModal);
        elements.saveMarker.addEventListener('click', saveMarkerFromModal);
        elements.markerModal.addEventListener('click', (e) => {
            if (e.target === elements.markerModal) hideMarkerModal();
        });
        elements.markerName.addEventListener('keydown', (e) => {
            if (e.key === 'Enter') saveMarkerFromModal();
            if (e.key === 'Escape') hideMarkerModal();
        });
        elements.colorBtns.forEach(btn => {
            btn.addEventListener('click', () => selectColor(btn.dataset.color));
        });

        // Clear markers
        elements.clearMarkers.addEventListener('click', clearAllMarkers);

        // Sidebar
        elements.toggleSidebar.addEventListener('click', toggleSidebar);

        // Map select
        elements.mapSelect.addEventListener('change', (e) => switchMap(e.target.value));

        // Keyboard shortcuts
        document.addEventListener('keydown', (e) => {
            if (e.target.tagName === 'INPUT') return;

            switch (e.key) {
                case '+':
                case '=':
                    zoomIn();
                    break;
                case '-':
                    zoomOut();
                    break;
                case '0':
                    resetView();
                    break;
                case 'Escape':
                    hideContextMenu();
                    hideMarkerModal();
                    break;
            }
        });

        // Window resize
        window.addEventListener('resize', () => {
            clampPan();
            updateTransform();
        });
    }

    // ===================
    // Initialization
    // ===================
    function init() {
        cacheElements();
        loadState();

        // Set initial map
        elements.mapSelect.value = state.currentMap;
        elements.mapObject.data = state.currentMap;

        // Render markers
        renderMarkers();
        updateMarkerList();

        // Bind events
        bindEvents();

        // Initial view
        elements.mapObject.onload = () => {
            if (state.zoom === 0.1 && state.panX === 0 && state.panY === 0) {
                resetView();
            } else {
                updateTransform();
                updateZoomDisplay();
            }
        };

        // Fallback if already loaded
        setTimeout(() => {
            if (state.zoom === 0.1 && state.panX === 0 && state.panY === 0) {
                resetView();
            } else {
                updateTransform();
                updateZoomDisplay();
            }
        }, 100);
    }

    // Start when DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
})();
