/**
 * Shared map provider utilities (Google / Mapbox / Neshan).
 * Neshan: official docs + vanilla-js-mapbox sample (SDK v1.1.1).
 */
(function (window) {
    'use strict';

    var neshanPromise = null;

    // Official CDN (docs + vanilla-js-mapbox)
    var NESHAN_SDK = {
        js: 'https://static.neshan.org/sdk/mapboxgl/v1.13.2/neshan-sdk/v1.1.1/index.js',
        css: 'https://static.neshan.org/sdk/mapboxgl/v1.13.2/neshan-sdk/v1.1.1/index.css',
        version: '1.1.1'
    };

    function stGetNeshanSdkUrls() {
        var cfg = stGetMapConfig();
        if (cfg.neshan_sdk && cfg.neshan_sdk.js) {
            return cfg.neshan_sdk;
        }
        return NESHAN_SDK;
    }

    var MAP_CONFIG_KEYS = [
        'map_provider',
        'st_googlemap_enabled',
        'token_mapbox',
        'token_neshan',
        'google_api_key',
        'st_icon_mapbox',
        'text_rtl_mapbox',
        'map_markers',
        'neshan_sdk'
    ];

    function stGetMapConfig() {
        var cfg = {};
        var fromParams = typeof st_params !== 'undefined' && st_params ? st_params : {};
        var fromMapConfig = typeof st_map_config !== 'undefined' && st_map_config ? st_map_config : {};

        var i;
        var key;

        for (i = 0; i < MAP_CONFIG_KEYS.length; i++) {
            key = MAP_CONFIG_KEYS[i];
            if (fromParams[key] !== undefined && fromParams[key] !== null && fromParams[key] !== '') {
                cfg[key] = fromParams[key];
            }
        }

        // Theme map helper / head+footer patch must win over ionCube legacy st_params.
        for (i = 0; i < MAP_CONFIG_KEYS.length; i++) {
            key = MAP_CONFIG_KEYS[i];
            if (fromMapConfig[key] !== undefined && fromMapConfig[key] !== null && fromMapConfig[key] !== '') {
                cfg[key] = fromMapConfig[key];
            }
        }

        if (document.body && document.body.getAttribute('data-st-map-provider')) {
            cfg.map_provider = document.body.getAttribute('data-st-map-provider');
            cfg.st_googlemap_enabled = cfg.map_provider === 'neshan' ? 'neshan' : cfg.st_googlemap_enabled;
        }

        if (document.body && document.body.getAttribute('data-st-token-neshan')) {
            cfg.token_neshan = document.body.getAttribute('data-st-token-neshan');
        }

        return cfg;
    }

    function stShouldUseNeshanMap() {
        if (stGetNeshanMapKey()) {
            var cfg = stGetMapConfig();
            if (cfg.map_provider === 'neshan' || cfg.st_googlemap_enabled === 'neshan') {
                return true;
            }
            if (document.body && document.body.classList.contains('st-map-provider-neshan')) {
                return true;
            }
            if (document.body && document.body.getAttribute('data-st-map-provider') === 'neshan') {
                return true;
            }
            if (window.nmp_mapboxgl && window.nmp_mapboxgl.Map && !cfg.token_mapbox) {
                return true;
            }
        }
        return stIsNeshanMap();
    }

    function stGetMapProvider() {
        var cfg = stGetMapConfig();
        if (cfg.map_provider) {
            return cfg.map_provider;
        }
        if (cfg.st_googlemap_enabled === 'neshan') {
            return 'neshan';
        }
        if (cfg.st_googlemap_enabled === 'off') {
            return 'mapbox';
        }
        return 'google';
    }

    function stIsNeshanMap() {
        var cfg = stGetMapConfig();
        if (cfg.map_provider === 'neshan' || cfg.st_googlemap_enabled === 'neshan') {
            return true;
        }
        return stGetMapProvider() === 'neshan';
    }

    function stGetNeshanMapKey() {
        var cfg = stGetMapConfig();
        return (cfg.token_neshan || '').trim();
    }

    function stIsMapboxMap() {
        var cfg = stGetMapConfig();
        if (cfg.map_provider === 'mapbox' || cfg.st_googlemap_enabled === 'off') {
            return true;
        }
        return stGetMapProvider() === 'mapbox';
    }

    function stGetMapGL() {
        if (stIsNeshanMap() && window.nmp_mapboxgl && window.nmp_mapboxgl.Map) {
            return window.nmp_mapboxgl;
        }
        return window.mapboxgl;
    }

    function stEnsureNeshanContainer(container) {
        if (!container) {
            return null;
        }
        var el = typeof container === 'string' ? document.getElementById(container) : container;
        if (!el) {
            return null;
        }
        el.style.width = el.style.width || '100%';
        if (!el.style.minHeight) {
            el.style.minHeight = '320px';
        }
        if (!el.style.height || el.style.height === '100%') {
            var parent = el.parentElement;
            if (!parent || parent.offsetHeight < 80) {
                el.style.height = el.style.minHeight;
            } else {
                el.style.height = el.style.height || '100%';
            }
        }
        return el;
    }

    /**
     * Official Neshan Map options (docs / vanilla-js-mapbox).
     */
    function stBuildNeshanMapOptions(opts) {
        opts = opts || {};
        var gl = window.nmp_mapboxgl;
        var containerEl = stEnsureNeshanContainer(opts.container);
        if (!containerEl) {
            console.warn('[Traveler] Neshan map container was not found:', opts.container);
            return null;
        }

        var mapKey = stGetNeshanMapKey();
        if (!mapKey) {
            console.warn('[Traveler] Neshan API key is empty. Theme Options > Map API > Neshan API key (Web SDK).');
            return null;
        }

        var lat = parseFloat(opts.lat);
        var lng = parseFloat(opts.lng);
        if (isNaN(lat) || isNaN(lng)) {
            lat = 35.6892;
            lng = 51.389;
        }

        var zoom = parseFloat(opts.zoom);
        if (isNaN(zoom)) {
            zoom = 11;
        }

        return {
            mapType: gl.Map.mapTypes.neshanVector,
            container: typeof opts.container === 'string' ? opts.container : containerEl,
            zoom: zoom,
            pitch: 0,
            center: [lng, lat],
            minZoom: 2,
            maxZoom: 21,
            trackResize: true,
            mapKey: mapKey,
            poi: typeof opts.poi !== 'undefined' ? opts.poi : false,
            traffic: typeof opts.traffic !== 'undefined' ? opts.traffic : false,
            mapTypeControllerOptions: {
                show: typeof opts.showMapTypeControl !== 'undefined' ? opts.showMapTypeControl : false,
                position: opts.mapTypeControlPosition || 'bottom-left'
            }
        };
    }

    function stWaitForWpNeshanScript() {
        var wpScript = document.getElementById('mapboxv5-js') || document.getElementById('neshan-map-sdk-js');
        if (!wpScript) {
            return Promise.resolve();
        }
        if (window.nmp_mapboxgl && window.nmp_mapboxgl.Map) {
            return Promise.resolve();
        }
        return new Promise(function (resolve, reject) {
            wpScript.addEventListener('load', function () { resolve(); });
            wpScript.addEventListener('error', function () {
                reject(new Error('Neshan SDK load failed'));
            });
        });
    }

    function stLoadNeshanSdk() {
        if (!stShouldUseNeshanMap()) {
            return Promise.resolve();
        }
        if (window.nmp_mapboxgl && window.nmp_mapboxgl.Map) {
            return Promise.resolve();
        }
        if (neshanPromise) {
            return neshanPromise;
        }

        var sdk = stGetNeshanSdkUrls();
        neshanPromise = stWaitForWpNeshanScript().then(function () {
            if (window.nmp_mapboxgl && window.nmp_mapboxgl.Map) {
                return;
            }

            var existing = document.querySelector('script[data-st-neshan-sdk="1"]');
            if (existing) {
                return new Promise(function (resolve, reject) {
                    if (existing.getAttribute('data-loaded') === '1') {
                        resolve();
                        return;
                    }
                    existing.addEventListener('load', function () { resolve(); });
                    existing.addEventListener('error', function () { reject(new Error('Neshan SDK load failed')); });
                });
            }

            return new Promise(function (resolve, reject) {
                if (!document.querySelector('link[data-st-neshan-sdk-css="1"]')) {
                    var link = document.createElement('link');
                    link.setAttribute('data-st-neshan-sdk-css', '1');
                    link.rel = 'stylesheet';
                    link.href = sdk.css;
                    document.head.appendChild(link);
                }

                var script = document.createElement('script');
                script.setAttribute('data-st-neshan-sdk', '1');
                script.src = sdk.js;
                script.onload = function () {
                    script.setAttribute('data-loaded', '1');
                    resolve();
                };
                script.onerror = function () {
                    console.warn('[Traveler] Neshan SDK failed to load:', sdk.js);
                    reject(new Error('Neshan SDK load failed'));
                };
                document.head.appendChild(script);
            });
        }).catch(function (err) {
            console.warn('[Traveler]', err.message || err);
        });

        return neshanPromise;
    }

    function stGetMarkerSize(mapEl, mapVersion) {
        if (mapEl && mapEl.length && mapEl.data('marker-size') === 'large') {
            return 'large';
        }
        if (mapVersion === 'elementorv2') {
            return 'small';
        }
        if (mapEl && mapEl.length && mapEl.closest('.search-result-page').length) {
            return 'small';
        }
        if (mapEl && mapEl.length && mapEl.data('marker-size') === 'small') {
            return 'small';
        }
        return 'large';
    }

    function stGetMapMarkerIcon(postType, size) {
        var icons = stGetMapConfig().map_markers || {};
        var pt = String(postType || '').replace(/^st_/, '');

        if (size === 'large') {
            if (pt === 'hotel') return icons.hotel_large || icons.hotel_small;
            if (pt === 'tours' || pt === 'tour') return icons.tour;
            if (pt === 'activity') return icons.activity;
            if (pt === 'rental') return icons.rental;
            if (pt === 'location') return icons.location;
            return icons.hotel_large || icons.hotel_small;
        }

        if (pt === 'hotel') return icons.hotel_small;
        if (pt === 'tours' || pt === 'tour') return icons.tour;
        if (pt === 'activity') return icons.activity;
        if (pt === 'rental') return icons.rental;
        if (pt === 'location') return icons.location;
        return icons.hotel_small;
    }

    function stCreateMapMarkerElement(location, mapEl, mapVersion, fallbackIcon) {
        var size = stGetMarkerSize(mapEl, mapVersion);
        var iconUrl = (location && location.icon_mk) ? location.icon_mk : stGetMapMarkerIcon(location && location.post_type, size);
        if (!iconUrl && fallbackIcon) {
            iconUrl = fallbackIcon;
        }

        var el = document.createElement('div');
        el.className = 'st-map-marker st-map-marker-' + size;
        if (location && location.id) {
            el.setAttribute('data-marker-id', location.id);
        }

        var imgSize = size === 'large' ? 48 : 28;
        var img = document.createElement('img');
        img.src = iconUrl;
        img.alt = (location && location.name) ? location.name : '';
        img.width = imgSize;
        img.style.width = imgSize + 'px';
        img.style.height = 'auto';
        img.style.display = 'block';
        img.decoding = 'async';
        img.loading = size === 'large' ? 'eager' : 'lazy';
        el.appendChild(img);
        return el;
    }

    function stRunAfterMapContainerLayout(container, callback) {
        if (typeof callback !== 'function') {
            return;
        }
        requestAnimationFrame(function () {
            requestAnimationFrame(callback);
        });
    }

    function stAttachMapResizeObserver(map, containerEl) {
        if (!map || !containerEl || typeof ResizeObserver === 'undefined') {
            return null;
        }

        var observerKey = 'stMapResizeObserver';
        if (map[observerKey]) {
            return map[observerKey];
        }

        var frameId = null;
        var ro = new ResizeObserver(function () {
            if (frameId) {
                cancelAnimationFrame(frameId);
            }
            frameId = requestAnimationFrame(function () {
                frameId = null;
                if (map.resize) {
                    map.resize();
                }
            });
        });
        ro.observe(containerEl);
        map[observerKey] = ro;

        if (map.on) {
            map.on('remove', function () {
                ro.disconnect();
                map[observerKey] = null;
            });
        }

        return ro;
    }

    /**
     * Enable smooth mouse-wheel zoom without breaking map layout (markers/canvas).
     */
    function stApplyMapScrollZoom(map, options) {
        if (!map || !map.scrollZoom) {
            return;
        }
        options = options || {};
        var rate = typeof options.wheelZoomRate === 'number' ? options.wheelZoomRate : 0.012;

        if (map.scrollZoom.enable) {
            map.scrollZoom.enable();
        }
        if (map.scrollZoom.setWheelZoomRate) {
            map.scrollZoom.setWheelZoomRate(rate);
        }
    }

    /**
     * Standard interaction: wheel zoom on, rotation off, canvas resync after zoom.
     */
    function stApplyMapInteractionOptions(map, options) {
        if (!map) {
            return;
        }
        options = options || {};

        stApplyMapScrollZoom(map, options);

        if (map.dragRotate && map.dragRotate.disable) {
            map.dragRotate.disable();
        }
        if (map.touchZoomRotate && map.touchZoomRotate.disableRotation) {
            map.touchZoomRotate.disableRotation();
        }

        if (!map._stTravelerZoomResizeBound && map.on) {
            map._stTravelerZoomResizeBound = true;
            map.on('zoomend', function () {
                if (map.resize) {
                    map.resize();
                }
            });
        }
    }

    function stCreateNeshanMap(opts) {
        return stLoadNeshanSdk().then(function () {
            var gl = window.nmp_mapboxgl;
            if (!gl || !gl.Map) {
                console.warn('[Traveler] nmp_mapboxgl is not available after SDK load.');
                return null;
            }
            var mapOptions = stBuildNeshanMapOptions(opts);
            if (!mapOptions) {
                return null;
            }
            var map = new gl.Map(mapOptions);
            stApplyMapInteractionOptions(map);
            map.on('load', function () {
                if (map.resize) {
                    map.resize();
                }
            });
            return map;
        }).catch(function () {
            return null;
        });
    }

    function stSetMapboxAccessToken(gl) {
        if (!gl || stIsNeshanMap()) {
            return;
        }
        var token = stGetMapConfig().token_mapbox;
        if (token) {
            gl.accessToken = token;
        }
    }

    function stCreateVectorMap(options) {
        options = options || {};
        var center = options.center || [51.389, 35.6892];
        var zoom = typeof options.zoom !== 'undefined' ? options.zoom : 13;

        if (stIsNeshanMap()) {
            return stCreateNeshanMap({
                container: options.container,
                lat: center[1],
                lng: center[0],
                zoom: zoom,
                poi: options.poi,
                traffic: options.traffic
            });
        }

        var gl = window.mapboxgl;
        if (!gl || !gl.Map) {
            return Promise.resolve(null);
        }
        stSetMapboxAccessToken(gl);
        var map = new gl.Map({
            container: options.container,
            style: options.style || 'mapbox://styles/mapbox/light-v10?optimize=true',
            center: center,
            zoom: parseFloat(zoom)
        });
        stApplyMapInteractionOptions(map);
        return Promise.resolve(map);
    }

    window.stGetNeshanSdkUrls = stGetNeshanSdkUrls;
    window.stGetMapProvider = stGetMapProvider;
    window.stIsNeshanMap = stIsNeshanMap;
    window.stIsMapboxMap = stIsMapboxMap;
    window.stGetMapGL = stGetMapGL;
    window.stLoadNeshanSdk = stLoadNeshanSdk;
    window.stEnsureNeshanContainer = stEnsureNeshanContainer;
    window.stBuildNeshanMapOptions = stBuildNeshanMapOptions;
    window.stCreateNeshanMap = stCreateNeshanMap;
    window.stSetMapboxAccessToken = stSetMapboxAccessToken;
    window.stCreateVectorMap = stCreateVectorMap;
    window.stGetNeshanMapKey = stGetNeshanMapKey;
    window.stGetMapMarkerIcon = stGetMapMarkerIcon;
    window.stGetMarkerSize = stGetMarkerSize;
    window.stCreateMapMarkerElement = stCreateMapMarkerElement;
    window.stGetMapConfig = stGetMapConfig;
    window.stShouldUseNeshanMap = stShouldUseNeshanMap;
    window.stRunAfterMapContainerLayout = stRunAfterMapContainerLayout;
    window.stAttachMapResizeObserver = stAttachMapResizeObserver;
    window.stApplyMapScrollZoom = stApplyMapScrollZoom;
    window.stApplyMapInteractionOptions = stApplyMapInteractionOptions;
})(window);
