{% load static %}
{% load custom_tags %}
{% load i18n %}

<!-- add MapLibre JavaScript and CSS -->
<script src="{% settings_value "MAP_TILE_SERVER" %}/assets/lib/maplibre-gl/maplibre-gl.js"></script>
<link href="{% settings_value "MAP_TILE_SERVER" %}/assets/lib/maplibre-gl/maplibre-gl.css" rel="stylesheet"/>

<!-- add Turf see https://maplibre.org/maplibre-gl-js/docs/examples/draw-a-radius/ -->
<script src="{% static 'fellchensammlung/js/turf.min.js' %}"></script>

<!-- add container for the map -->
<div id="map" class="map"></div>

<!-- start map -->
<script>
    {% if zoom_level %}
        var zoom_level = {{ zoom_level }};
    {% else %}
        var zoom_level = 4;
    {% endif %}

    {% if map_center %}
        var map_center = [{{ map_center.longitude | pointdecimal }}, {{ map_center.latitude | pointdecimal }}];
    {% else %}
        var map_center = [10.49, 50.68]; <!-- Point middle of Germany -->
        zoom_level = 4;  //Overwrite zoom level when no place is found
    {% endif %}

    let map = new maplibregl.Map({
        container: 'map',
        style: '{% static "fellchensammlung/map/styles/colorful/style.json" %}',
        center: map_center,
        zoom: zoom_level
    });

    map.addControl(new maplibregl.FullscreenControl());
    map.addControl(new maplibregl.NavigationControl({showCompass: false}));


    map.on('load', async () => {
        {% if show_ANs %}
            // Load adoption notices as geojson
            map.addSource('adoption-notices', {
                type: 'geojson',
                data: '{% url "api-adoption-notice-list-geojson" %}',
                cluster: true,
                clusterMaxZoom: 14,
                clusterRadius: 50
            });

            // Layer for clusters
            map.addLayer({
                id: 'clusters',
                type: 'circle',
                source: 'adoption-notices',
                filter: ['has', 'point_count'],
                paint: {
                    'circle-color': [
                        'step',
                        ['get', 'point_count'],
                        '#51bbd6',
                        100,
                        '#f1f075',
                        750,
                        '#f28cb1'
                    ],
                    'circle-radius': [
                        'step',
                        ['get', 'point_count'],
                        20,
                        100,
                        30,
                        750,
                        40
                    ]
                }
            });

            map.addLayer({
                id: 'cluster-count',
                type: 'symbol',
                source: 'adoption-notices',
                filter: ['has', 'point_count'],
                layout: {
                    'text-field': '{point_count_abbreviated}',
                    'text-size': 12,
                    'text-font': ['open_sans_medium'],
                }
            });

            const rat_image = await map.loadImage('{% static 'fellchensammlung/img/logo_transparent.png' %}');
            map.addImage('rat', rat_image.data);


            map.addLayer({
                id: 'unclustered-point',
                type: 'symbol',
                source: 'adoption-notices',
                filter: ['!', ['has', 'point_count']],
                layout: {
                    'icon-image': ['get', 'species'],
                    'icon-size': 0.07,
                    'icon-allow-overlap': true
                }
            });



            // inspect an AN cluster on click
            map.on('click', 'clusters', async (e) => {
                const features = map.queryRenderedFeatures(e.point, {
                    layers: ['clusters']
                });
                const clusterId = features[0].properties.cluster_id;
                const zoom = await map.getSource('adoption-notices').getClusterExpansionZoom(clusterId);
                map.easeTo({
                    center: features[0].geometry.coordinates,
                    zoom
                });
            });

            // When a click event occurs on a feature in
            // the unclustered-point layer, open a popup at
            // the location of the feature, with
            // description HTML from its properties.
            map.on('click', 'unclustered-point', (e) => {
                const coordinates = e.features[0].geometry.coordinates.slice();
                const title = e.features[0].properties.title;
                const url = e.features[0].properties.url;
                const description = e.features[0].properties.description;
                const location_hr = e.features[0].properties.location_hr;
                const image_url = e.features[0].properties.image_url;
                const image_alt = e.features[0].properties.image_alt;

                // Ensure that if the map is zoomed out such that
                // multiple copies of the feature are visible, the
                // popup appears over the copy being pointed to.
                while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
                    coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
                }

                const description_column = `
                            <div class="column">
                                <strong><a class="is-size-7" href="${url}">${title}</strong> <i class="fa-solid fa-arrow-up-right-from-square"></i></a><br>
                                <span><strong>{% translate 'Ort' %}</strong>: ${location_hr}</span><br>
                                <p class="is-size-7">${truncate(description, 80, url)}</p>
                            </div>
                            `;
                let picture_column = '';
                if (image_url) {
                    picture_column = `
                            <div class="column">
                                <figure class="image is-128x128">
                                    <img src="${image_url}" alt="${image_alt}"/>
                                </figure>
                            </div>`;
                }

                new maplibregl.Popup()
                    .setLngLat(coordinates)
                    .setHTML(`
                    <div class="popup-content is-size-7">
                        <div class="columns">
                            ${description_column}
                            ${picture_column}
                        </div>
                    </div>`
                    )
                    .addTo(map);
            });

            map.on('mouseenter', 'clusters', () => {
                map.getCanvas().style.cursor = 'pointer';
            });
            map.on('mouseleave', 'clusters', () => {
                map.getCanvas().style.cursor = '';
            });
        {% endif %}

        {% if show_rescue_orgs %}
            // Load rescue_orgs as geojson
            map.addSource('rescue-orgs', {
                type: 'geojson',
                data: '{% url "api-organization-list-geojson" %}',
                cluster: true,
                clusterMaxZoom: 14,
                clusterRadius: 50
            });

            // Layer for clusters
            map.addLayer({
                id: 'org-clusters',
                type: 'circle',
                source: 'rescue-orgs',
                filter: ['has', 'point_count'],
                paint: {
                    'circle-color': [
                        'step',
                        ['get', 'point_count'],
                        '#51bbd6',
                        100,
                        '#f1f075',
                        750,
                        '#f28cb1'
                    ],
                    'circle-radius': [
                        'step',
                        ['get', 'point_count'],
                        20,
                        100,
                        30,
                        750,
                        40
                    ]
                }
            });

            map.addLayer({
                id: 'org-cluster-count',
                type: 'symbol',
                source: 'rescue-orgs',
                filter: ['has', 'point_count'],
                layout: {
                    'text-field': '{point_count_abbreviated}',
                    'text-size': 12,
                    'text-font': ['open_sans_medium'],
                }
            });

            const org_image = await map.loadImage('{% static 'fellchensammlung/img/animal_shelter.png' %}');
            map.addImage('org', org_image.data);


            map.addLayer({
                id: 'org-unclustered-point',
                type: 'symbol',
                source: 'rescue-orgs',
                filter: ['!', ['has', 'point_count']],
                layout: {
                    'icon-image': 'org',
                    'icon-size': 0.07,
                    'icon-allow-overlap': true
                }
            });

            // inspect an org cluster on click
            map.on('click', 'org-clusters', async (e) => {
                const features = map.queryRenderedFeatures(e.point, {
                    layers: ['org-clusters']
                });
                const clusterId = features[0].properties.cluster_id;
                const zoom = await map.getSource('rescue-orgs').getClusterExpansionZoom(clusterId);
                map.easeTo({
                    center: features[0].geometry.coordinates,
                    zoom
                });
            });

            // Same for orgs
            map.on('click', 'org-unclustered-point', (e) => {
                const coordinates = e.features[0].geometry.coordinates.slice();
                const name = e.features[0].properties.name;
                const url = e.features[0].properties.url;
                const description = e.features[0].properties.description;
                const location_hr = e.features[0].properties.location_hr;

                while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
                    coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
                }


                new maplibregl.Popup()
                    .setLngLat(coordinates)
                    .setHTML(`
                    <div class="popup-content is-size-7">
                        <strong><a class="is-size-7" href="${url}">${name}</a></strong> <i class="fa-solid fa-arrow-up-right-from-square"></i><br>
                            <span><strong>{% translate 'Ort' %}</strong>: ${location_hr}</span><br>
                            <p class="is-size-7">${truncate(description, 80, url)}</p>
                    </div>`
                    )
                    .addTo(map);
            });


            map.on('mouseenter', 'org-clusters', () => {
                map.getCanvas().style.cursor = 'pointer';
            });
            map.on('mouseleave', 'org-clusters', () => {
                map.getCanvas().style.cursor = '';
            });
        {% endif %}

        image = await map.loadImage('{% static "fellchensammlung/img/pin.png" %}');
        map.addImage('pin', image.data);
        {% for map_pin in map_pins %}
            map.addSource('point_{{ forloop.counter }}', {
                'type': 'geojson',
                'data': {
                    'type': 'FeatureCollection',
                    'features': [
                        {
                            'type': 'Feature',
                            'geometry': {
                                'type': 'Point',
                                'coordinates': [{{ map_pin.location.longitude | pointdecimal }}, {{ map_pin.location.latitude | pointdecimal }}]
                            }
                        }
                    ]
                }
            });
            map.addLayer({
                'id': 'point_{{ forloop.counter }}',
                'type': 'circle',
                'source': 'point_{{ forloop.counter }}',
                'paint': {
                    'circle-radius': 18,
                    'circle-color': '#ff878980'
                }
            });
        {% endfor %}
    });

    {% if search_center  %}
        var search_center = [{{ search_center.longitude | pointdecimal }}, {{ search_center.latitude | pointdecimal }}];
        map.on('load', () => {
            const radius = {{ search_radius }}; // kilometer
            const options = {
                steps: 64,
                units: 'kilometers'
            };
            const circle = turf.circle(search_center, radius, options);

            // Add the circle as a GeoJSON source
            map.addSource('location-radius', {
                type: 'geojson',
                data: circle
            });

            // Add a fill layer with some transparency
            map.addLayer({
                id: 'location-radius',
                type: 'fill',
                source: 'location-radius',
                paint: {
                    'fill-color': 'rgba(140,207,255,0.3)',
                    'fill-opacity': 0.5
                }
            });

            // Add a line layer to draw the circle outline
            map.addLayer({
                id: 'location-radius-outline',
                type: 'line',
                source: 'location-radius',
                paint: {
                    'line-color': '#0094ff',
                    'line-width': 3
                }
            });
        });
    {% endif %}

</script>
