document.addEventListener('DOMContentLoaded', function() {
    var avoidHighwaysCheckbox = document.getElementById('avoidHighways');
    var useShortestCheckbox = document.getElementById('useShortest');
    var avoidTollRoadsCheckbox = document.getElementById('avoidTollRoads');
    var avoidFerriesCheckbox = document.getElementById('avoidFerries');
    var avoidUnpavedCheckbox = document.getElementById('avoidUnpaved');
    var points = [];
    var markers = [];
    var routePolyline = null;

    function calculateRoute() {
        if (points.length === 2) {
            var moto = {};
            // Avoid highways -> lower highway usage weight
            if (avoidHighwaysCheckbox && avoidHighwaysCheckbox.checked) {
                moto.use_highways = 0.0; // 0..1 (0 avoids, 1 prefers)
            }
            // Avoid ferries -> lower ferry usage weight
            if (avoidFerriesCheckbox && avoidFerriesCheckbox.checked) {
                moto.use_ferry = 0.0; // 0..1
            }
            // Avoid unpaved -> exclude unpaved roads entirely
            if (avoidUnpavedCheckbox && avoidUnpavedCheckbox.checked) {
                moto.exclude_unpaved = true;
            }
            // Avoid tolls -> exclude tolls
            if (avoidTollRoadsCheckbox && avoidTollRoadsCheckbox.checked) {
                moto.exclude_tolls = true;
            }

            var costing_options = { motorcycle: moto };

            var requestBody = {
                locations: [
                    { lat: points[0].lat, lon: points[0].lng },
                    { lat: points[1].lat, lon: points[1].lng }
                ],
                costing: "motorcycle",
                costing_options: costing_options,
                units: "kilometers"
            };
            if (useShortestCheckbox && useShortestCheckbox.checked) {
                requestBody.shortest = true; // top-level shortest flag
            }

            fetch('/route', {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify(requestBody)
            })
            .then(response => response.json())
            .then(data => {
                var leg = data.trip && data.trip.legs && data.trip.legs[0];
                var infoCard = document.getElementById('routeInfoCard');
                if (leg && leg.summary && typeof leg.summary.length === 'number' && typeof leg.summary.time === 'number') {
                    var distanceKm = (leg.summary.length).toFixed(1); // already in km
                    var durationMin = Math.round(leg.summary.time / 60); // seconds to minutes
                    var info = `<strong>Distance:</strong> ${distanceKm} km<br>
                                <strong>Estimated Time:</strong> ${durationMin} min<br>
                                <strong>Motorcycle Profile</strong>`;
                    infoCard.innerHTML = info;
                    infoCard.classList.remove('d-none');
                } else {
                    infoCard.innerHTML = `<strong>Route info unavailable.</strong>`;
                    infoCard.classList.remove('d-none');
                    console.log('Valhalla response:', data);
                }
                var latlngs = decodePolyline6(leg.shape);
                if (routePolyline) {
                    map.removeLayer(routePolyline);
                }
                routePolyline = L.polyline(latlngs, { color: 'red', weight: 5}).addTo(map);
                map.fitBounds(routePolyline.getBounds());
            });
        }
    }

    map.on('click', function(e) {
        if (points.length < 2) {
            var marker = L.marker(e.latlng).addTo(map);
            markers.push(marker);
            points.push(e.latlng);
            marker.bindPopup(points.length === 1 ? "Start" : "End").openPopup();

            // Reverse geocode and fill address field
            if (points.length === 1) {
                reverseGeocode(e.latlng.lat, e.latlng.lng, 'sourceInput');
            } else if (points.length === 2) {
                reverseGeocode(e.latlng.lat, e.latlng.lng, 'destInput');
            }
        }
        calculateRoute();
    });

    // Listen for changes on all checkboxes
    [
        avoidHighwaysCheckbox,
        useShortestCheckbox,
        avoidTollRoadsCheckbox,
        avoidFerriesCheckbox,
        avoidUnpavedCheckbox
    ].forEach(function(checkbox) {
        if (checkbox) {
            checkbox.addEventListener('change', calculateRoute);
        }
    });

    // Disable other checkboxes when "Use shortest route" is checked
    useShortestCheckbox.addEventListener('change', function() {
        var disable = useShortestCheckbox.checked;
        [
            avoidHighwaysCheckbox,
            avoidTollRoadsCheckbox,
            avoidFerriesCheckbox,
            avoidUnpavedCheckbox
        ].forEach(function(cb) {
            cb.disabled = disable;
        });
    });

    // Adapted from Valhalla docs — polyline6 decoder for JS
    function decodePolyline6(encoded) {
        var coords = [];
        var index = 0, lat = 0, lng = 0;
        var shift = 0, result = 0, byte = null, latitude_change, longitude_change;
        var factor = Math.pow(10, 6);
        while (index < encoded.length) {
            byte = shift = result = 0;
            do {
                byte = encoded.charCodeAt(index++) - 63;
                result |= (byte & 0x1f) << shift;
                shift += 5;
            } while (byte >= 0x20);
            latitude_change = (result & 1) ? ~(result >> 1) : (result >> 1);

            shift = result = 0;
            do {
                byte = encoded.charCodeAt(index++) - 63;
                result |= (byte & 0x1f) << shift;
                shift += 5;
            } while (byte >= 0x20);
            longitude_change = (result & 1) ? ~(result >> 1) : (result >> 1);

            lat += latitude_change;
            lng += longitude_change;

            coords.push([lat / factor, lng / factor]);
        }
        return coords;
    }

    // Remove Markers
    function resetMarkers() {
        markers.forEach(function(marker) {
            map.removeLayer(marker);
        });
        markers = [];
        points = [];
        if (routePolyline) {
            map.removeLayer(routePolyline);
            routePolyline = null;
        }
        // Clear address fields
        var sourceInput = document.getElementById('sourceInput');
        var destInput = document.getElementById('destInput');
        sourceInput.value = '';
        destInput.value = '';
        delete sourceInput.dataset.lat;
        delete sourceInput.dataset.lon;
        delete destInput.dataset.lat;
        delete destInput.dataset.lon;
    }

    // Make resetMarkers available globally
    window.resetMarkers = resetMarkers;

    // Plot Route button logic
    document.getElementById('plotRouteBtn').addEventListener('click', function() {
        var sourceInput = document.getElementById('sourceInput');
        var destInput = document.getElementById('destInput');
        var sourceLat = parseFloat(sourceInput.dataset.lat);
        var sourceLon = parseFloat(sourceInput.dataset.lon);
        var destLat = parseFloat(destInput.dataset.lat);
        var destLon = parseFloat(destInput.dataset.lon);

        if (!isNaN(sourceLat) && !isNaN(sourceLon) && !isNaN(destLat) && !isNaN(destLon)) {
            // Remove old markers
            markers.forEach(function(marker) {
                map.removeLayer(marker);
            });
            markers = [];
            points = [];

            // Add new markers
            var startMarker = L.marker([sourceLat, sourceLon]).addTo(map).bindPopup("Start").openPopup();
            var endMarker = L.marker([destLat, destLon]).addTo(map).bindPopup("End").openPopup();
            markers.push(startMarker, endMarker);
            points.push({lat: sourceLat, lng: sourceLon}, {lat: destLat, lng: destLon});

            calculateRoute();
        } else {
            alert("Please enter valid addresses for both start and destination.");
        }
    });

    function reverseGeocode(lat, lon, inputId) {
        fetch(`/reverse?format=json&lat=${lat}&lon=${lon}`)
            .then(response => response.json())
            .then(data => {
                var input = document.getElementById(inputId);
                if (data && data.address) {
                    // Use the same format as your autocomplete
                    input.value = formatAddress(data);
                } else {
                    input.value = `${lat}, ${lon}`;
                }
                input.dataset.lat = lat;
                input.dataset.lon = lon;
            });
    }

    function exportRouteAsGPX(latlngs) {
        if (!latlngs || latlngs.length === 0) {
            alert("No route to export.");
            return;
        }
        let gpx =
`<?xml version="1.0" encoding="UTF-8"?>
<gpx version="1.1" creator="FreeMoto" xmlns="http://www.topografix.com/GPX/1/1">
  <trk>
    <name>FreeMoto Route</name>
    <trkseg>
${latlngs.map(pt => `      <trkpt lat="${pt[0]}" lon="${pt[1]}"></trkpt>`).join('\n')}
    </trkseg>
  </trk>
</gpx>`;

        let blob = new Blob([gpx], {type: "application/gpx+xml"});
        let url = URL.createObjectURL(blob);

        // iOS workaround: open in new tab instead of triggering download
        if (navigator.userAgent.match(/(iPad|iPhone|iPod)/i)) {
            window.open(url, '_blank');
        } else {
            let a = document.createElement('a');
            a.href = url;
            a.download = "freemoto-route.gpx";
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
        }
        setTimeout(() => URL.revokeObjectURL(url), 1000);
    }

    document.getElementById('exportGpxBtn').addEventListener('click', function() {
        if (routePolyline) {
            // routePolyline.getLatLngs() returns array of LatLng objects
            let latlngs = routePolyline.getLatLngs().map(ll => [ll.lat, ll.lng]);
            exportRouteAsGPX(latlngs);
        } else {
            alert("No route to export.");
        }
    });
});