<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>OpenStreetMap - Non-Intersecting Roads</title>

    <!-- Include Leaflet CSS -->
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.css" />
    <!-- Include Turf.js -->
    <script src="https://unpkg.com/@turf/turf@6.5.0/turf.min.js"></script>

    <style>
        #map {
            height: 800px;
            width: 100%;
        }
        .legend {
            position: absolute;
            top: 10px;
            right: 10px;
            z-index: 1000; /* Ensure the legend is above the map */
            background: white;
            padding: 10px;
            line-height: 1.5;
            border: 1px solid #ccc;
            border-radius: 5px;
            font-size: 12px;
            max-height: 90%;
            overflow-y: auto;
        }

        .legend span {
            display: inline-block;
            width: 15px;
            height: 15px;
            margin-right: 5px;
        }

        .legend-item {
            margin-bottom: 5px;
        }
    </style>
</head>
<body>
    <div id="map"></div>
    <div class="legend" id="legend">
        <strong>Road Types</strong>
    </div>
    <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js"></script>

    <script>
        const roadTypeGroups = {
    primary: "Primary Road",
    trunk: "Primary Road",
    motorway: "Primary Road",
    trunk_link: "Primary Road",
    primary_link: "Main Road",
    motorway_link: "Main Road",
    tertiary_link: "Main Road",
    territory: "Main Road",
    track: "Primary Road",
    secondary: "Secondary Road",
    secondary_link: "Secondary Road",
    construction: "Construction Road",
    cycleway: "Cycleway Road",
    raceway: "Raceway Road",
    residential: "Residential Road",
    service: "Service Road",
    living_street: "Service Road",
    footway: "Service Road",
    path: "Service Road",
    unclassified: "Service Road",
    steps: "Service Road",
    pedestrian: "Service Road",
    corridor: "Service Road",
    services: "Services Road"
};
var roadLayersByCategory = {}; // Layer groups by category
var colorMapByCategory = {};
        // Initialize the map
        var map = L.map('map').setView([28.57981636729179, 77.32036656283616], 15);

        // Add OpenStreetMap tile layer
        L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
            attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
        }).addTo(map);

        // Initialize the feature group for drawn items
        var drawnItems = new L.FeatureGroup();
        map.addLayer(drawnItems);

        // Initialize the draw control and pass it the FeatureGroup of editable layers
        var drawControl = new L.Control.Draw({
            edit: { featureGroup: drawnItems },
            draw: {
                rectangle: true,
                polygon: true,
                polyline: false,
                circle: false,
                marker: false,
                circlemarker: false
            }
        });
        map.addControl(drawControl);

        // Initialize roadLayers and colorMap
        var roadLayers = {}; // Object to hold layer groups for each road type
        var colorMap = {};    // Object to hold colors for each road type

        // Reference to the legend container
        var legendElement = document.getElementById('legend');

        // Function to sanitize road type names for HTML IDs
        function sanitizeForID(str) {
            return str.replace(/\s+/g, '-').replace(/[^\w-]/g, '');
        }

        // Event listener for when a new area is drawn
        map.on(L.Draw.Event.CREATED, function (event) {
            drawnItems.clearLayers(); // Clear previous drawn areas
            clearRoadLayers();        // Clear previous road layers and legend
            var layer = event.layer;
            drawnItems.addLayer(layer); // Add the new drawn area

            // Get the bounds of the drawn area
            var bounds = layer.getBounds();
            fetchRoadData(bounds.getSouthWest(), bounds.getNorthEast());
        });

        // Function to clear road layers and legend
        function clearRoadLayers() {
            // Remove all existing road layers from the map
            for (var roadType in roadLayers) {
                if (map.hasLayer(roadLayers[roadType])) {
                    map.removeLayer(roadLayers[roadType]);
                }
            }
            roadLayers = {}; // Reset the roadLayers object
            colorMap = {};    // Reset the colorMap object

            // Clear the legend (except the title)
            while (legendElement.children.length > 1) {
                legendElement.removeChild(legendElement.lastChild);
            }
        }

        // Function to fetch road data from Overpass API
        function fetchRoadData(southWest, northEast) {
            var query = `
                [out:json];
                way["highway"](${southWest.lat},${southWest.lng},${northEast.lat},${northEast.lng});
                out body;
                >;
                out skel qt;
            `;
            var overpassURL = "https://overpass-api.de/api/interpreter?data=" + encodeURIComponent(query);

            fetch(overpassURL)
                .then(response => response.json())
                .then(data => {
                    displayRoads(data);
                })
                .catch(error => {
                    console.error("Error fetching road data:", error);
                });
        }

        // Function to convert OSM data to GeoJSON
        function osmDataToGeoJSON(osmData) {
            var geojson = {
                type: "FeatureCollection",
                features: []
            };

            var nodes = {};
            osmData.elements.forEach(element => {
                if (element.type === "node") {
                    nodes[element.id] = [element.lon, element.lat];
                }
            });

            osmData.elements.forEach(element => {
                if (element.type === "way") {
                    var coordinates = element.nodes.map(nodeId => nodes[nodeId]);
                    if (coordinates.every(coord => coord)) {
                        geojson.features.push({
                            type: "Feature",
                            geometry: {
                                type: "LineString",
                                coordinates: coordinates
                            },
                            properties: element.tags
                        });
                    }
                }
            });

            return geojson;
        }

        // Function to display roads on the map
        function displayRoads(data) {
            var geoJSONRoads = osmDataToGeoJSON(data);

            // Get the drawn area's boundary as a Polygon
            var areaPolygon = drawnItems.getLayers()[0].toGeoJSON();

            // Ensure the drawn area's geometry is valid
            if (!["Polygon", "MultiPolygon"].includes(areaPolygon.geometry.type)) {
                console.error("Invalid drawn area geometry:", areaPolygon.geometry.type);
                return;
            }

            geoJSONRoads.features.forEach(road => {
                // Ensure the road's geometry is a valid GeoJSON LineString
                if (!["LineString", "MultiLineString"].includes(road.geometry.type)) {
                    console.warn("Skipping unsupported road geometry:", road.geometry.type);
                    return;
                }

                try {
                    // Buffer the road by 0.1 meters to create a thin polygon
                    var roadPolygon = turf.buffer(road, 0.1, { units: 'meters' });

                    // Perform the intersection to clip the road
                    var clippedRoad = turf.intersect(areaPolygon, roadPolygon);

                    if (clippedRoad) {
                        // Convert the clipped polygon back to LineString
                        var clippedLine = turf.polygonToLine(clippedRoad);

                        // If intersection exists, add the road
                        if (clippedLine) {
                            // Assign road type
                            var roadType = road.properties.highway || "unknown";

                            // Assign a random color if not already assigned
                            if (!colorMap[roadType]) {
                                colorMap[roadType] = getRandomColor();
                            }

                            // If the layer group for this road type doesn't exist, create it
                            if (!roadLayers[roadType]) {
                                roadLayers[roadType] = L.layerGroup().addTo(map);
                                addToLegend(roadType, colorMap[roadType]);
                            }

                            // Add the road to its corresponding layer group
                            L.geoJSON(clippedLine, {
                                style: { color: colorMap[roadType], weight: 4 }
                            }).addTo(roadLayers[roadType]);
                        }
                    }
                } catch (error) {
                    console.error("Error processing road:", road, error);
                }
            });
        }

        // Function to generate a random color in hex format
      function getRandomColor() {
    let r = Math.floor(Math.random() * 128); // Red value between 0 and 127
    let g = Math.floor(Math.random() * 128); // Green value between 0 and 127
    let b = Math.floor(Math.random() * 128); // Blue value between 0 and 127
    return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;
}

        // Function to add a road type to the legend with a checkbox
        function addToLegend(roadType, color) {
            var item = document.createElement('div');
            item.className = 'legend-item';
            var sanitizedRoadType = sanitizeForID(roadType);
            var checkboxId = `checkbox-${sanitizedRoadType}`;
            item.innerHTML = `
                <input type="checkbox" id="${checkboxId}" checked>
                <label for="${checkboxId}">
                    <span style="background: ${color};"></span> ${roadType}
                </label>
            `;
            legendElement.appendChild(item);

            // Attach event listener to the checkbox
            var checkbox = document.getElementById(checkboxId);
            checkbox.addEventListener('change', function () {
                if (checkbox.checked) {
                    // Add the layer group back to the map
                    roadLayers[roadType].addTo(map);
                } else {
                    // Remove the layer group from the map
                    map.removeLayer(roadLayers[roadType]);
                }
            });
        }
    </script>
</body>
</html>
