/**
 * Yoro Widget — Interactive map picker for Django forms.
 *
 * Initializes a Leaflet map inside each .yoro-widget container.
 * Click on the map to encode a location, or type a code to decode.
 */
(function () {
    'use strict';

    function initWidget(container) {
        var domain = container.dataset.domain || 'CI';
        var precision = parseInt(container.dataset.precision || '12', 10);
        var tileUrl = container.dataset.tileUrl || 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
        var tileAttr = container.dataset.tileAttribution || '&copy; OpenStreetMap';

        var input = container.querySelector('.yoro-code-input');
        var infoEl = container.querySelector('.yoro-info');
        var coordsEl = container.querySelector('.yoro-coords');
        var mapDiv = container.querySelector('.yoro-map');

        if (!input || !mapDiv) return;

        // Determine initial center
        var center = YoroCodec.domainCenter(domain);
        var zoom = 7;

        // If there's already a value, decode it for initial position
        var initialValue = input.value.trim();
        var initialDecoded = null;
        if (initialValue && initialValue.indexOf('-') !== -1) {
            try {
                initialDecoded = YoroCodec.decode(initialValue);
                center = [initialDecoded.lat, initialDecoded.lon];
                zoom = 14;
            } catch (e) { /* ignore */ }
        }

        // Create Leaflet map
        var map = L.map(mapDiv, {
            center: center,
            zoom: zoom,
            scrollWheelZoom: true,
        });

        L.tileLayer(tileUrl, {
            attribution: tileAttr,
            maxZoom: 19,
        }).addTo(map);

        var cellLayer = null;
        var marker = null;

        // Show result on the widget
        function showResult(code, decoded, res) {
            input.value = code;
            // Trigger change event for Django form validation
            input.dispatchEvent(new Event('change', { bubbles: true }));

            if (infoEl) {
                infoEl.textContent = '~' + res.toFixed(1) + ' m | p=' + decoded.precision +
                    ' (' + code.split('-')[1].length + ' chars)';
            }
            if (coordsEl) {
                coordsEl.textContent = decoded.lat.toFixed(6) + ', ' + decoded.lon.toFixed(6);
            }

            drawCell(decoded);
        }

        function drawCell(decoded) {
            var b = decoded.bounds;

            // Remove previous
            if (cellLayer) map.removeLayer(cellLayer);
            if (marker) map.removeLayer(marker);

            // Draw cell rectangle
            cellLayer = L.rectangle(
                [[b.lat_min, b.lon_min], [b.lat_max, b.lon_max]],
                { color: '#e65100', weight: 2, fillOpacity: 0.12, dashArray: '5,5' }
            ).addTo(map);

            // Place marker at center
            marker = L.circleMarker(
                [decoded.lat, decoded.lon],
                { radius: 6, color: '#e65100', fillColor: '#ff9800', fillOpacity: 1, weight: 2 }
            ).addTo(map);
        }

        // Click on map → encode
        map.on('click', function (e) {
            var lat = e.latlng.lat;
            var lon = e.latlng.lng;

            try {
                var code = YoroCodec.encode(lat, lon, precision, domain);
                var decoded = YoroCodec.decode(code);
                var res = YoroCodec.resolution(decoded.precision, domain);
                showResult(code, decoded, res);
            } catch (err) {
                if (infoEl) infoEl.textContent = 'Out of domain';
            }
        });

        // Type a code → decode
        var debounceTimer = null;
        input.addEventListener('input', function () {
            clearTimeout(debounceTimer);
            debounceTimer = setTimeout(function () {
                var val = input.value.trim().toUpperCase();
                if (!val || val.indexOf('-') === -1 || val.split('-')[1].length < 1) return;

                try {
                    var decoded = YoroCodec.decode(val);
                    var res = YoroCodec.resolution(decoded.precision, decoded.domain);

                    if (infoEl) {
                        infoEl.textContent = '~' + res.toFixed(1) + ' m | p=' + decoded.precision +
                            ' (' + val.split('-')[1].length + ' chars)';
                    }
                    if (coordsEl) {
                        coordsEl.textContent = decoded.lat.toFixed(6) + ', ' + decoded.lon.toFixed(6);
                    }

                    drawCell(decoded);
                    map.flyTo([decoded.lat, decoded.lon], 15, { duration: 0.5 });
                } catch (err) {
                    if (infoEl) infoEl.textContent = '';
                    if (coordsEl) coordsEl.textContent = '';
                }
            }, 400);
        });

        // Show initial value
        if (initialDecoded) {
            var res = YoroCodec.resolution(initialDecoded.precision, domain);
            showResult(initialValue.toUpperCase(), initialDecoded, res);
        }

        // Fix Leaflet rendering in hidden containers (e.g. Django admin tabs)
        setTimeout(function () { map.invalidateSize(); }, 200);
    }

    // Initialize all widgets on page load
    function initAll() {
        var widgets = document.querySelectorAll('.yoro-widget:not([data-initialized])');
        widgets.forEach(function (w) {
            w.setAttribute('data-initialized', '1');
            initWidget(w);
        });
    }

    // Support both regular page load and Django admin inline additions
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initAll);
    } else {
        initAll();
    }

    // Re-init when Django admin adds inline forms
    if (typeof django !== 'undefined' && django.jQuery) {
        django.jQuery(document).on('formset:added', function () {
            setTimeout(initAll, 100);
        });
    }
})();
