<template>
    <div id="map" :class="isDark ? 'dark' : ''"></div>

    <!-- List different matching language versions if multiple locales match a single WALS code -->
    <div v-if="dialog.visible" class="modal d-block-force modal-shown" @click.self="dialog.visible = false">
        <div :class="['modal-dialog', 'modal-dialog-centered', 'modal-dialog-scrollable']" role="document">
            <div class="modal-content shadow">
                <div class="modal-body">
                    <div class="list-group">
                        <a
                            v-for="language in dialog.languages"
                            :key="language.walsCode"
                            :href="language.url"
                            target="_blank"
                            class="list-group-item list-group-item-action"
                        >
                            <div class="d-flex w-100 justify-content-between">
                                <h5 class="mb-1">{{ language.fullName }}</h5>
                            </div>
                            <p class="mb-1">{{ language.url }}</p>
                        </a>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
import { defineComponent, reactive } from 'vue';

import locales from '../../locale/locales.ts';
import walsLanguages from '../assets/languages.tsv';

import { clearUrl } from '#shared/helpers.ts';
import useDark from '~/composables/useDark.ts';

const MOBILE_BREAKPOINT = 992;

const localesByWalsCode = locales.reduce((acc, language) => {
    if (language.walsCode && language.published) {
        acc[language.walsCode] = [...(acc[language.walsCode] || []), language];
    }
    return acc;
}, {});

export default defineComponent({
    setup() {
        useDark();

        return {
            dialog: reactive({
                visible: false,
                languages: [],
            }),
        };
    },
    async mounted() {
        await this.$loadStylesheet(
            'leaflet',
            'https://unpkg.com/leaflet@1.9.4/dist/leaflet.css',
        );
        await this.$loadScript(
            'leaflet',
            'https://unpkg.com/leaflet@1.9.4/dist/leaflet.js',
        );
        await this.$loadScript(
            'tinyworldmap',
            'https://tinyworldmap.com/dist/v3/tiny-world-borders.js',
        );

        const pos = window.innerWidth < MOBILE_BREAKPOINT ? [45, 15] : [40, 65];
        const map = window.L.map('map', { attributionControl: false }).setView(pos, 3);

        window.L.control.attribution({ position: 'bottomright' })
            .addAttribution('&copy; <a href="https://doi.org/10.5281/zenodo.7385533" target="_blank" title="Dryer, Matthew S. & Haspelmath, Martin (eds.) 2013. The World Atlas of Language Structures Online. Leipzig: Max Planck Institute for Evolutionary Anthropology.">WALS</a>')
            .addAttribution('<a href="https://wals.info" target="_blank">wals.info</a>')
            .addTo(map);

        new window.L.GridLayer.TinyWorld({ maxZoom: 19 }).addTo(map);

        for (const walsLanguage of walsLanguages) {
            if (!Object.hasOwn(localesByWalsCode, walsLanguage.id)) {
                continue;
            }
            const locales = localesByWalsCode[walsLanguage.id];

            const circle = window.L.circle([walsLanguage.latitude, walsLanguage.longitude], {
                color: '#971064',
                fillColor: '#c71585',
                fillOpacity: 0.5,
                radius: 300000 * Math.cos(walsLanguage.latitude * Math.PI / 180), // compensate for Mercator projection
            }).addTo(map);

            circle.bindTooltip(locales.map((locale) => `<strong>${locale.fullName}</strong><br/>${clearUrl(locale.url)}`).join('<br/>'));

            if (locales.length === 1) {
                // If only one locale matches the WALS code, open it directly on click
                circle.on('click', () => {
                    window.open(locales[0].url);
                    return;
                });
            } else {
                // If multiple locales match the WALS code, show a list of them in a modal
                circle.on('click', () => {
                    this.dialog.languages = locales;
                    this.dialog.visible = true;
                });
            }
        }
    },
});
</script>

<style lang="scss">
#map {
    height: 500px;
    z-index: 0;
    &.dark {
        .leaflet-layer,
        .leaflet-control-zoom-in,
        .leaflet-control-zoom-out,
        .leaflet-control-attribution {
            filter: invert(100%) hue-rotate(180deg) brightness(95%) contrast(90%);
            svg, img {
                filter: invert(100%) hue-rotate(180deg) brightness(95%) contrast(90%);
            }
        }
    }
}
</style>
