/**
 * @license Highcharts JS v11.4.8 (2024-08-29)
 *
 * (c) 2009-2024
 *
 * License: www.highcharts.com/license
 */
(function (factory) {
    if (typeof module === 'object' && module.exports) {
        factory['default'] = factory;
        module.exports = factory;
    } else if (typeof define === 'function' && define.amd) {
        define('highcharts/modules/tiledwebmap', ['highcharts'], function (Highcharts) {
            factory(Highcharts);
            factory.Highcharts = Highcharts;
            return factory;
        });
    } else {
        factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined);
    }
}(function (Highcharts) {
    'use strict';
    var _modules = Highcharts ? Highcharts._modules : {};
    function _registerModule(obj, path, args, fn) {
        if (!obj.hasOwnProperty(path)) {
            obj[path] = fn.apply(null, args);

            if (typeof CustomEvent === 'function') {
                Highcharts.win.dispatchEvent(new CustomEvent(
                    'HighchartsModuleLoaded',
                    { detail: { path: path, module: obj[path] } }
                ));
            }
        }
    }
    _registerModule(_modules, 'Maps/TilesProviders/OpenStreetMap.js', [], function () {
        /* *
         * OpenStreetMap provider, used for tile map services
         * */
        /* *
         *
         *  Class
         *
         * */
        class OpenStreetMap {
            constructor() {
                /* *
                 *
                 *  Properties
                 *
                 * */
                this.defaultCredits = ('Map data &copy2023' +
                    ' <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>');
                this.initialProjectionName = 'WebMercator';
                this.subdomains = ['a', 'b', 'c'];
                this.themes = {
                    Standard: {
                        url: 'https://tile.openstreetmap.org/{zoom}/{x}/{y}.png',
                        minZoom: 0,
                        maxZoom: 19
                    },
                    Hot: {
                        url: 'https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png',
                        minZoom: 0,
                        maxZoom: 19
                    },
                    OpenTopoMap: {
                        url: 'https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png',
                        minZoom: 0,
                        maxZoom: 17,
                        credits: `Map data: &copy; <a href="https://www.openstreetmap.org/copyright">
                        OpenStreetMap</a> contributors, <a href="https://viewfinderpanoramas.org">SRTM</a> 
                        | Map style: &copy; <a href="https://opentopomap.org">OpenTopoMap</a> 
                        (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)`
                    }
                };
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return OpenStreetMap;
    });
    _registerModule(_modules, 'Maps/TilesProviders/Stamen.js', [], function () {
        /* *
         * Stamen provider, used for tile map services
         * */
        /* *
         *
         *  Class
         *
         * */
        class Stamen {
            constructor() {
                /* *
                 *
                 *  Properties
                 *
                 * */
                this.defaultCredits = ('&copy; Map tiles by <a href="https://stamen.com">Stamen Design</a>,' +
                    ' under <a href="https://creativecommons.org/licenses/by/3.0">CC BY' +
                    ' 3.0</a>. Data by <a href="https://openstreetmap.org">OpenStreetMap' +
                    '</a>, under <a href="https://www.openstreetmap.org/copyright">ODbL</a>');
                this.initialProjectionName = 'WebMercator';
                this.subdomains = ['a', 'b', 'c', 'd'];
                this.themes = {
                    Toner: {
                        url: 'https://stamen-tiles-{s}.a.ssl.fastly.net/toner/{z}/{x}/{y}.png',
                        minZoom: 0,
                        maxZoom: 20
                    },
                    TonerBackground: {
                        url: 'https://stamen-tiles-{s}.a.ssl.fastly.net/toner-background/{z}/{x}/{y}.png',
                        minZoom: 0,
                        maxZoom: 20
                    },
                    TonerLite: {
                        url: 'https://stamen-tiles-{s}.a.ssl.fastly.net/toner-lite/{z}/{x}/{y}.png',
                        minZoom: 0,
                        maxZoom: 20
                    },
                    Terrain: {
                        url: 'https://stamen-tiles-{s}.a.ssl.fastly.net/terrain/{z}/{x}/{y}.png',
                        minZoom: 0,
                        maxZoom: 18
                    },
                    TerrainBackground: {
                        url: 'https://stamen-tiles-{s}.a.ssl.fastly.net/terrain-background/{z}/{x}/{y}.png',
                        minZoom: 0,
                        maxZoom: 18
                    },
                    Watercolor: {
                        url: 'https://stamen-tiles-{s}.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.png',
                        minZoom: 1,
                        maxZoom: 16,
                        credits: ('&copy Map tiles by <a href="https://stamen.com">Stamen' +
                            ' Design</a>, under <a href="https://creativecommons.org/' +
                            'licenses/by/3.0">CC BY 3.0</a>. Data by <a href="https://' +
                            'openstreetmap.org">OpenStreetMap</a>, under <a href=' +
                            '"https://creativecommons.org/licenses/by-sa/3.0">CC BY SA</a>')
                    }
                };
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return Stamen;
    });
    _registerModule(_modules, 'Maps/TilesProviders/LimaLabs.js', [], function () {
        /* *
         * LimaLabs provider, used for tile map services
         * */
        /* *
         *
         *  Class
         *
         * */
        class LimaLabs {
            constructor() {
                /* *
                 *
                 *  Properties
                 *
                 * */
                this.defaultCredits = ('Map data &copy;2023' +
                    ' <a href="https://maps.lima-labs.com/">LimaLabs</a>');
                this.initialProjectionName = 'WebMercator';
                this.requiresApiKey = true;
                this.themes = {
                    Standard: {
                        url: 'https://cdn.lima-labs.com/{zoom}/{x}/{y}.png?api={apikey}',
                        minZoom: 0,
                        maxZoom: 20
                    }
                };
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return LimaLabs;
    });
    _registerModule(_modules, 'Maps/TilesProviders/Thunderforest.js', [], function () {
        /* *
         * Thunderforest provider, used for tile map services
         * */
        /* *
         *
         *  Class
         *
         * */
        class Thunderforest {
            constructor() {
                /* *
                 *
                 *  Properties
                 *
                 * */
                this.defaultCredits = ('Maps &copy <a href="https://www.thunderforest.com">Thunderforest</a>' +
                    ', Data &copy; <a href="https://www.openstreetmap.org/copyright">' +
                    'OpenStreetMap contributors</a>');
                this.initialProjectionName = 'WebMercator';
                this.requiresApiKey = true;
                this.subdomains = ['a', 'b', 'c'];
                this.themes = {
                    OpenCycleMap: {
                        url: 'https://{s}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png?apikey={apikey}',
                        minZoom: 0,
                        maxZoom: 22
                    },
                    Transport: {
                        url: 'https://{s}.tile.thunderforest.com/transport/{z}/{x}/{y}.png?apikey={apikey}',
                        minZoom: 0,
                        maxZoom: 22
                    },
                    TransportDark: {
                        url: 'https://{s}.tile.thunderforest.com/transport-dark/{z}/{x}/{y}.png?apikey={apikey}',
                        minZoom: 0,
                        maxZoom: 22
                    },
                    SpinalMap: {
                        url: 'https://{s}.tile.thunderforest.com/spinal-map/{z}/{x}/{y}.png?apikey={apikey}',
                        minZoom: 0,
                        maxZoom: 22
                    },
                    Landscape: {
                        url: 'https://{s}.tile.thunderforest.com/landscape/{z}/{x}/{y}.png?apikey={apikey}',
                        minZoom: 0,
                        maxZoom: 22
                    },
                    Outdoors: {
                        url: 'https://{s}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png?apikey={apikey}',
                        minZoom: 0,
                        maxZoom: 22
                    },
                    Pioneer: {
                        url: 'https://{s}.tile.thunderforest.com/pioneer/{z}/{x}/{y}.png?apikey={apikey}',
                        minZoom: 0,
                        maxZoom: 22
                    },
                    MobileAtlas: {
                        url: 'https://{s}.tile.thunderforest.com/mobile-atlas/{z}/{x}/{y}.png?apikey={apikey}',
                        minZoom: 0,
                        maxZoom: 22
                    },
                    Neighbourhood: {
                        url: 'https://{s}.tile.thunderforest.com/neighbourhood/{z}/{x}/{y}.png?apikey={apikey}',
                        minZoom: 0,
                        maxZoom: 22
                    }
                };
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return Thunderforest;
    });
    _registerModule(_modules, 'Maps/TilesProviders/Esri.js', [], function () {
        /* *
         * Esri provider, used for tile map services
         * */
        /* *
         *
         *  Class
         *
         * */
        class Esri {
            constructor() {
                /* *
                 *
                 *  Properties
                 *
                 * */
                this.defaultCredits = ('Tiles &copy; Esri &mdash; Source: Esri, DeLorme, NAVTEQ, USGS, ' +
                    ' Intermap, iPC, NRCAN, Esri Japan, METI, Esri China (Hong Kong),' +
                    ' Esri (Thailand), TomTom, 2012');
                this.initialProjectionName = 'WebMercator';
                this.themes = {
                    WorldStreetMap: {
                        url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}',
                        minZoom: 0,
                        maxZoom: 20
                    },
                    DeLorme: {
                        url: 'https://server.arcgisonline.com/ArcGIS/rest/services/Specialty/DeLorme_World_Base_Map/MapServer/tile/{z}/{y}/{x}',
                        minZoom: 1,
                        maxZoom: 11,
                        credits: 'Tiles &copy; Esri &mdash; Copyright: &copy;2012 DeLorme'
                    },
                    WorldTopoMap: {
                        url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{z}/{y}/{x}',
                        minZoom: 0,
                        maxZoom: 20,
                        credits: ('Tiles &copy; Esri &mdash; Esri, DeLorme, NAVTEQ, TomTom,' +
                            ' Intermap, iPC, USGS, FAO, NPS, NRCAN, GeoBase, Kadaster NL,' +
                            ' Ordnance Survey, Esri Japan, METI, Esri China (Hong Kong),' +
                            ' and the GIS User Community')
                    },
                    WorldImagery: {
                        url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
                        minZoom: 0,
                        maxZoom: 20,
                        credits: ('Tiles &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS,' +
                            ' AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP,' +
                            ' and the GIS User Community')
                    },
                    WorldTerrain: {
                        url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Terrain_Base/MapServer/tile/{z}/{y}/{x}',
                        minZoom: 0,
                        maxZoom: 13,
                        credits: ('Tiles &copy; Esri &mdash; Source: USGS, Esri, TANA, DeLorme,' +
                            ' and NPS')
                    },
                    WorldShadedRelief: {
                        url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Shaded_Relief/MapServer/tile/{z}/{y}/{x}',
                        minZoom: 0,
                        maxZoom: 13,
                        credits: 'Tiles &copy; Esri &mdash; Source: Esri'
                    },
                    WorldPhysical: {
                        url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Physical_Map/MapServer/tile/{z}/{y}/{x}',
                        minZoom: 0,
                        maxZoom: 8,
                        credits: 'Tiles &copy; Esri &mdash; Source: US National Park Service'
                    },
                    NatGeoWorldMap: {
                        url: 'https://server.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer/tile/{z}/{y}/{x}',
                        minZoom: 0,
                        maxZoom: 16,
                        credits: ('Tiles &copy; Esri &mdash; National Geographic, Esri,' +
                            ' DeLorme, NAVTEQ, UNEP-WCMC, USGS, NASA, ESA, METI, NRCAN,' +
                            ' GEBCO, NOAA, iPC')
                    },
                    WorldGrayCanvas: {
                        url: 'https://server.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer/tile/{z}/{y}/{x}',
                        minZoom: 0,
                        maxZoom: 16,
                        credits: 'Tiles &copy; Esri &mdash; Esri, DeLorme, NAVTEQ'
                    }
                };
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return Esri;
    });
    _registerModule(_modules, 'Maps/TilesProviders/USGS.js', [], function () {
        /* *
         * USGS provider, used for tile map services
         * */
        /* *
         *
         *  Class
         *
         * */
        class USGS {
            constructor() {
                /* *
                 *
                 *  Properties
                 *
                 * */
                this.defaultCredits = ('Tiles courtesy of the <a href="https://usgs.gov/">U.S. Geological' +
                    'Survey</a>');
                this.initialProjectionName = 'WebMercator';
                this.themes = {
                    USTopo: {
                        url: 'https://basemap.nationalmap.gov/arcgis/rest/services/USGSTopo/MapServer/tile/{z}/{y}/{x}',
                        minZoom: 0,
                        maxZoom: 20
                    },
                    USImagery: {
                        url: 'https://basemap.nationalmap.gov/arcgis/rest/services/USGSImageryOnly/MapServer/tile/{z}/{y}/{x}',
                        minZoom: 0,
                        maxZoom: 20
                    },
                    USImageryTopo: {
                        url: 'https://basemap.nationalmap.gov/arcgis/rest/services/USGSImageryTopo/MapServer/tile/{z}/{y}/{x}',
                        minZoom: 0,
                        maxZoom: 20
                    }
                };
            }
        }
        /* *
         *
         *  Default Export
         *
         * */

        return USGS;
    });
    _registerModule(_modules, 'Maps/TilesProviders/TilesProviderRegistry.js', [_modules['Maps/TilesProviders/OpenStreetMap.js'], _modules['Maps/TilesProviders/Stamen.js'], _modules['Maps/TilesProviders/LimaLabs.js'], _modules['Maps/TilesProviders/Thunderforest.js'], _modules['Maps/TilesProviders/Esri.js'], _modules['Maps/TilesProviders/USGS.js']], function (OpenStreetMap, Stamen, LimaLabs, Thunderforest, Esri, USGS) {
        /* *
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        /* *
         *
         *  Imports
         *
         * */
        /* *
         *
         *  Constants
         *
         * */
        const tilesProviderRegistry = {
            Esri,
            LimaLabs,
            OpenStreetMap,
            Stamen,
            Thunderforest,
            USGS
        };
        /* *
         *
         *  Default Export
         *
         * */

        return tilesProviderRegistry;
    });
    _registerModule(_modules, 'Series/TiledWebMap/TiledWebMapSeriesDefaults.js', [], function () {
        /* *
         *
         *  (c) 2010-2024 Hubert Kozik, Kamil Musiałowski
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        /* *
         *
         *  API Options
         *
         * */
        /**
         * A tiledwebmap series allows user to display dynamically joined individual
         * images (tiles) and join them together to create a map.
         *
         * @sample maps/series-tiledwebmap/simple-demo-norway
         *         Simple demo of data for Norway on TiledWebMap
         * @sample maps/series-tiledwebmap/only-twm
         *         OpenStreetMap demo
         *
         * @extends      plotOptions.map
         * @excluding    affectsMapView, allAreas, allowPointSelect, animation,
         * animationLimit, boostBlending, boostThreshold, borderColor, borderWidth,
         * clip, color, colorAxis, colorByPoint, colorIndex, colorKey, colors,
         * cursor, dashStyle, dataLabels, dataParser, dataURL, dragDrop,
         * enableMouseTracking, findNearestPointBy, joinBy, keys, marker,
         * negativeColor, nullColor, nullInteraction, onPoint, point,
         * pointDescriptionFormatter, selected, shadow, showCheckbox,
         * sonification, stickyTracking, tooltip, type
         * @product      highmaps
         * @optionparent plotOptions.tiledwebmap
         */
        const TiledWebMapSeriesDefaults = {
            states: {
                inactive: {
                    enabled: false
                }
            }
        };
        /* *
         *
         *  API options
         *
         * */
        /**
         * A `tiledwebmap` series. The [type](#series.tiledwebmap.type) option is
         * not specified, it is inherited from [chart.type](#chart.type).
         *
         * @sample maps/series-tiledwebmap/simple-demo-norway
         *         Simple demo of data for Norway on TiledWebMap
         * @sample maps/series-tiledwebmap/only-twm
         *         OpenStreetMap demo
         *
         * @extends   series,plotOptions.tiledwebmap
         * @excluding affectsMapView, allAreas, allowPointSelect, animation,
         * animationLimit, boostBlending, boostThreshold, borderColor, borderWidth,
         * clip, color, colorAxis, colorByPoint, colorIndex, colorKey, colors, cursor,
         * dashStyle, dataLabels, dataParser, dataURL, dragDrop, enableMouseTracking,
         * findNearestPointBy, joinBy, keys, marker, negativeColor, nullColor,
         * nullInteraction, onPoint, point, pointDescriptionFormatter, selected, shadow,
         * showCheckbox, stickyTracking, tooltip, type
         * @product   highmaps
         * @apioption series.tiledwebmap
         */
        /**
         * Provider options for the series.
         *
         * @sample maps/series-tiledwebmap/human-anatomy
         *         Human Anatomy Explorer - Custom TiledWebMap Provider
         *
         * @since 11.1.0
         * @product   highmaps
         * @apioption plotOptions.tiledwebmap.provider
         */
        /**
         * Provider type to pull data (tiles) from.
         *
         * @sample maps/series-tiledwebmap/basic-configuration
         *         Basic configuration for TiledWebMap
         *
         * @type      {string}
         * @since 11.1.0
         * @product   highmaps
         * @apioption plotOptions.tiledwebmap.provider.type
         */
        /**
         * Set a tiles theme. Check the [providers documentation](https://www.highcharts.com/docs/maps/tiledwebmap)
         * for official list of available themes.
         *
         * @sample maps/series-tiledwebmap/europe-timezones
         *         Imagery basemap for Europe
         * @sample maps/series-tiledwebmap/hiking-trail
         *         Topo basemap and MapLine
         *
         * @type      {string}
         * @since 11.1.0
         * @product   highmaps
         * @apioption plotOptions.tiledwebmap.provider.theme
         */
        /**
         * Subdomain required by each provider. Check the [providers documentation](https://www.highcharts.com/docs/maps/tiledwebmap)
         * for available subdomains.
         *
         * @sample maps/series-tiledwebmap/basic-configuration
         *         Basic configuration for TiledWebMap
         *
         * @type      {string}
         * @since 11.1.0
         * @product   highmaps
         * @apioption plotOptions.tiledwebmap.provider.subdomain
         */
        /**
         * API key for providers that require using one.
         *
         * @type      {string}
         * @since 11.1.0
         * @product   highmaps
         * @apioption plotOptions.tiledwebmap.provider.apiKey
         */
        /**
         * Custom URL for providers not specified in [providers type](#series.
         * tiledwebmap.provider.type). Available variables to use in URL are: `{x}`,
         * `{y}`, `{z}` or `{zoom}`. Remember to always specify a projection, when
         * using a custom URL.
         *
         * @sample maps/series-tiledwebmap/custom-url
         *         Custom URL with projection in TiledWebMap configuration
         *
         * @type      {string}
         * @since 11.1.0
         * @product   highmaps
         * @apioption plotOptions.tiledwebmap.provider.url
         */
        ''; // Keeps doclets above detached
        /* *
         *
         *  Default Export
         *
         * */

        return TiledWebMapSeriesDefaults;
    });
    _registerModule(_modules, 'Series/TiledWebMap/TiledWebMapSeries.js', [_modules['Core/Globals.js'], _modules['Core/Series/SeriesRegistry.js'], _modules['Maps/TilesProviders/TilesProviderRegistry.js'], _modules['Series/TiledWebMap/TiledWebMapSeriesDefaults.js'], _modules['Core/Utilities.js']], function (H, SeriesRegistry, TilesProvidersRegistry, TiledWebMapSeriesDefaults, U) {
        /* *
         *
         *  (c) 2010-2024 Hubert Kozik, Kamil Musiałowski
         *
         *  License: www.highcharts.com/license
         *
         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
         *
         * */
        const { composed } = H;
        const { map: MapSeries } = SeriesRegistry.seriesTypes;
        const { addEvent, defined, error, merge, pick, pushUnique } = U;
        /* *
         *
         *  Functions
         *
         * */
        /** @private */
        function onRecommendMapView(e) {
            const { geoBounds, chart } = e, twm = (chart.options.series || []).filter((s) => s.type === 'tiledwebmap')[0];
            if (twm && twm.provider && twm.provider.type && !twm.provider.url) {
                const ProviderDefinition = TilesProvidersRegistry[twm.provider.type];
                if (!defined(ProviderDefinition)) {
                    error('Highcharts warning: Tiles Provider not defined in the ' +
                        'Provider Registry.', false);
                }
                else {
                    const def = new ProviderDefinition(), { initialProjectionName: providerProjectionName } = def;
                    if (geoBounds) {
                        const { x1, y1, x2, y2 } = geoBounds;
                        this.recommendedMapView = {
                            projection: {
                                name: providerProjectionName,
                                parallels: [y1, y2],
                                rotation: [-(x1 + x2) / 2]
                            }
                        };
                    }
                    else {
                        this.recommendedMapView = {
                            projection: {
                                name: providerProjectionName
                            },
                            minZoom: 0
                        };
                    }
                    return false;
                }
            }
            return true;
        }
        /* *
         *
         *  Class
         *
         * */
        /**
         * The series type
         *
         * @private
         * @class
         * @name Highcharts.seriesTypes.tiledwebmap
         *
         * @augments Highcharts.Series
         */
        class TiledWebMapSeries extends MapSeries {
            constructor() {
                /* *
                 *
                 *  Static Properties
                 *
                 * */
                super(...arguments);
                this.redrawTiles = false;
                this.isAnimating = false;
            }
            /* *
             *
             *  Static Functions
             *
             * */
            static compose(MapViewClass) {
                if (pushUnique(composed, 'TiledWebMapSeries')) {
                    addEvent(MapViewClass, 'onRecommendMapView', onRecommendMapView);
                }
            }
            /* *
             *
             *  Functions
             *
             * */
            /**
             * Convert map coordinates in longitude/latitude to tile
             * @private
             * @param  {Highcharts.MapLonLatObject} lonLat
             *         The map coordinates
             * @return {Highcharts.PositionObject}
             *         Array of x and y positions of the tile
             */
            lonLatToTile(lonLat, zoom) {
                const { lon, lat } = lonLat, xTile = Math.floor((lon + 180) / 360 * Math.pow(2, zoom)), yTile = Math.floor((1 - Math.log(Math.tan(lat * Math.PI / 180) +
                    1 / Math.cos(lat * Math.PI / 180)) / Math.PI) /
                    2 * Math.pow(2, zoom));
                return { x: xTile, y: yTile };
            }
            /**
             * Convert tile to map coordinates in longitude/latitude
             * @private
             * @param  xTile
             *         Position x of the tile
             * @param  yTile
             *         Position y of the tile
             * @param  zTile
             *         Zoom of the tile
             * @return {Highcharts.MapLonLatObject}
             *         The map coordinates
             */
            tileToLonLat(xTile, yTile, zTile) {
                const lon = xTile / Math.pow(2, zTile) * 360 - 180, n = Math.PI - 2 * Math.PI * yTile / Math.pow(2, zTile), lat = (180 /
                    Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))));
                return { lon, lat };
            }
            drawPoints() {
                const chart = this.chart, mapView = chart.mapView;
                if (!mapView) {
                    return;
                }
                const tiles = (this.tiles = this.tiles || {}), transformGroups = (this.transformGroups = this.transformGroups || []), series = this, options = this.options, provider = options.provider, { zoom } = mapView, lambda = pick((mapView.projection.options.rotation &&
                    mapView.projection.options.rotation[0]), 0), worldSize = 400.979322, tileSize = 256, duration = chart.renderer.forExport ? 0 : 200, animateTiles = (duration) => {
                    for (const zoomKey of Object.keys(tiles)) {
                        if ((parseFloat(zoomKey) === (mapView.zoom < 0 ? 0 :
                            Math.floor(mapView.zoom))) ||
                            (series.minZoom &&
                                (mapView.zoom < 0 ? 0 :
                                    Math.floor(mapView.zoom)) < series.minZoom &&
                                parseFloat(zoomKey) === series.minZoom) ||
                            (series.maxZoom &&
                                (mapView.zoom < 0 ? 0 :
                                    Math.floor(mapView.zoom)) > series.maxZoom &&
                                parseFloat(zoomKey) === series.maxZoom)) {
                            Object
                                .keys(tiles[zoomKey].tiles)
                                .forEach((key, i) => {
                                tiles[zoomKey].tiles[key].animate({
                                    opacity: 1
                                }, {
                                    duration: duration
                                }, () => {
                                    if (i === Object.keys(tiles[zoomKey].tiles)
                                        .length - 1) {
                                        tiles[zoomKey].isActive = true;
                                    }
                                });
                            });
                        }
                        else {
                            Object
                                .keys(tiles[zoomKey].tiles)
                                .forEach((key, i) => {
                                tiles[zoomKey].tiles[key].animate({
                                    opacity: 0
                                }, {
                                    duration: duration,
                                    defer: duration / 2
                                }, () => {
                                    tiles[zoomKey].tiles[key].destroy();
                                    delete tiles[zoomKey].tiles[key];
                                    if (i === Object.keys(tiles[zoomKey].tiles)
                                        .length - 1) {
                                        tiles[zoomKey].isActive = false;
                                        tiles[zoomKey].loaded = false;
                                    }
                                });
                            });
                        }
                    }
                };
                let zoomFloor = zoom < 0 ? 0 : Math.floor(zoom), maxTile = Math.pow(2, zoomFloor), scale = ((tileSize / worldSize) * Math.pow(2, zoom)) /
                    ((tileSize / worldSize) * Math.pow(2, zoomFloor)), scaledTileSize = scale * 256;
                if (provider && (provider.type || provider.url)) {
                    if (provider.type && !provider.url) {
                        const ProviderDefinition = TilesProvidersRegistry[provider.type];
                        if (!defined(ProviderDefinition)) {
                            error('Highcharts warning: Tiles Provider \'' +
                                provider.type + '\' not defined in the Provider' +
                                'Registry.', false);
                            return;
                        }
                        const def = new ProviderDefinition(), providerProjection = def.initialProjectionName;
                        let theme, subdomain = '';
                        if (provider.theme && defined(def.themes[provider.theme])) {
                            theme = def.themes[provider.theme];
                        }
                        else {
                            // If nothing set take first theme
                            const firstTheme = Object.keys(def.themes)[0];
                            theme = def.themes[firstTheme];
                            error('Highcharts warning: The Tiles Provider\'s Theme \'' +
                                provider.theme + '\' is not defined in the Provider ' +
                                'definition - falling back to \'' + firstTheme + '\'.', false);
                        }
                        if (provider.subdomain &&
                            def.subdomains &&
                            def.subdomains.indexOf(provider.subdomain) !== -1) {
                            subdomain = provider.subdomain;
                        }
                        else if (defined(def.subdomains) &&
                            // Do not show warning if no subdomain in URL
                            theme.url.indexOf('{s}') !== -1) {
                            subdomain = pick(def.subdomains && def.subdomains[0], '');
                            error('Highcharts warning: The Tiles Provider\'s Subdomain ' +
                                '\'' + provider.subdomain + '\' is not defined in ' +
                                'the Provider definition - falling back to \'' +
                                subdomain + '\'.', false);
                        }
                        if (def.requiresApiKey) {
                            if (provider.apiKey) {
                                theme.url =
                                    theme.url.replace('{apikey}', provider.apiKey);
                            }
                            else {
                                error('Highcharts warning: The Tiles Provider requires ' +
                                    'API Key to use tiles, use provider.apiKey to ' +
                                    'provide a token.', false);
                                theme.url = theme.url.replace('?apikey={apikey}', '');
                            }
                        }
                        provider.url = theme.url
                            .replace('{s}', subdomain);
                        this.minZoom = theme.minZoom;
                        this.maxZoom = theme.maxZoom;
                        // Add as credits.text, to prevent changing the default mapText
                        const creditsText = pick(chart.userOptions.credits && chart.userOptions.credits.text, 'Highcharts.com ' + pick(theme.credits, def.defaultCredits));
                        if (chart.credits) {
                            chart.credits.update({
                                text: creditsText
                            });
                        }
                        else {
                            chart.addCredits({
                                text: creditsText,
                                style: pick(chart.options.credits?.style, {})
                            });
                        }
                        if (mapView.projection.options.name !== providerProjection) {
                            error('Highcharts warning: The set projection is different ' +
                                'than supported by Tiles Provider.', false);
                        }
                    }
                    else {
                        if (!mapView.projection.options.name) {
                            error('Highcharts warning: The set projection is different ' +
                                'than supported by Tiles Provider.', false);
                        }
                    }
                    // If zoom is smaller/higher than supported by provider
                    if (defined(this.minZoom) && zoomFloor < this.minZoom) {
                        zoomFloor = this.minZoom;
                        maxTile = Math.pow(2, zoomFloor);
                        scale = ((tileSize / worldSize) * Math.pow(2, zoom)) /
                            ((tileSize / worldSize) * Math.pow(2, zoomFloor));
                        scaledTileSize = scale * 256;
                    }
                    else if (defined(this.maxZoom) && zoomFloor > this.maxZoom) {
                        zoomFloor = this.maxZoom;
                        maxTile = Math.pow(2, zoomFloor);
                        scale = ((tileSize / worldSize) * Math.pow(2, zoom)) /
                            ((tileSize / worldSize) * Math.pow(2, zoomFloor));
                        scaledTileSize = scale * 256;
                    }
                    if (mapView.projection && mapView.projection.def) {
                        // Always true for tile maps
                        mapView.projection.hasCoordinates = true;
                        if (!transformGroups[zoomFloor]) {
                            transformGroups[zoomFloor] =
                                chart.renderer.g().add(this.group);
                        }
                        const replaceVariables = (url, x, y, zoom) => url
                            .replace('{x}', x.toString())
                            .replace('{y}', y.toString())
                            .replace('{zoom}', zoom.toString())
                            .replace('{z}', zoom.toString());
                        const addTile = (x, y, givenZoom, translateX, translateY) => {
                            const modX = x % maxTile, modY = y % maxTile, tileX = modX < 0 ? modX + maxTile : modX, tileY = modY < 0 ? modY + maxTile : modY;
                            if (!tiles[`${givenZoom}`].tiles[`${x},${y}`]) {
                                if (provider.url) {
                                    const url = replaceVariables(provider.url, tileX, tileY, givenZoom);
                                    tiles[givenZoom].loaded = false;
                                    tiles[`${givenZoom}`].tiles[`${x},${y}`] =
                                        chart.renderer.image(url, (x * scaledTileSize) - translateX, (y * scaledTileSize) - translateY, scaledTileSize, scaledTileSize)
                                            .attr({
                                            zIndex: 2,
                                            opacity: 0
                                        })
                                            .on('load', function () {
                                            if (provider.onload) {
                                                provider.onload.apply(this);
                                            }
                                            if ((givenZoom ===
                                                (mapView.zoom < 0 ? 0 :
                                                    Math.floor(mapView.zoom))) ||
                                                givenZoom === series.minZoom) {
                                                tiles[`${givenZoom}`]
                                                    .actualTilesCount++;
                                                // If last tile
                                                if (tiles[`${givenZoom}`]
                                                    .howManyTiles ===
                                                    tiles[`${givenZoom}`]
                                                        .actualTilesCount) {
                                                    tiles[givenZoom].loaded = true;
                                                    // Fade-in new tiles if there is
                                                    // no other animation
                                                    if (!series.isAnimating) {
                                                        series.redrawTiles = false;
                                                        animateTiles(duration);
                                                    }
                                                    else {
                                                        series.redrawTiles = true;
                                                    }
                                                    tiles[`${givenZoom}`]
                                                        .actualTilesCount = 0;
                                                }
                                            }
                                        })
                                            .add(transformGroups[givenZoom]);
                                    tiles[`${givenZoom}`].tiles[`${x},${y}`].posX = x;
                                    tiles[`${givenZoom}`].tiles[`${x},${y}`].posY = y;
                                    tiles[`${givenZoom}`].tiles[`${x},${y}`]
                                        .originalURL = url;
                                }
                            }
                        };
                        // Calculate topLeft and bottomRight corners without normalize
                        const topLeftUnits = mapView.pixelsToProjectedUnits({
                            x: 0,
                            y: 0
                        }), topLeftArr = mapView.projection.def.inverse([topLeftUnits.x, topLeftUnits.y]), topLeft = {
                            lon: topLeftArr[0] - lambda,
                            lat: topLeftArr[1]
                        }, bottomRightUnits = mapView.pixelsToProjectedUnits({
                            x: chart.plotWidth,
                            y: chart.plotHeight
                        }), bottomRightArr = mapView.projection.def.inverse([bottomRightUnits.x, bottomRightUnits.y]), bottomRight = {
                            lon: bottomRightArr[0] - lambda,
                            lat: bottomRightArr[1]
                        };
                        // Do not support vertical looping
                        if (topLeft.lat > mapView.projection.maxLatitude ||
                            bottomRight.lat < -1 * mapView.projection.maxLatitude) {
                            topLeft.lat = mapView.projection.maxLatitude;
                            bottomRight.lat = -1 * mapView.projection.maxLatitude;
                        }
                        const startPos = this.lonLatToTile(topLeft, zoomFloor), endPos = this.lonLatToTile(bottomRight, zoomFloor);
                        // Calculate group translations based on first loaded tile
                        const firstTileLonLat = this.tileToLonLat(startPos.x, startPos.y, zoomFloor), units = mapView.projection.def.forward([
                            firstTileLonLat.lon + lambda,
                            firstTileLonLat.lat
                        ]), firstTilePx = mapView.projectedUnitsToPixels({
                            x: units[0], y: units[1]
                        }), translateX = (startPos.x * scaledTileSize - firstTilePx.x), translateY = (startPos.y * scaledTileSize - firstTilePx.y);
                        if (!tiles[`${zoomFloor}`]) {
                            tiles[`${zoomFloor}`] = {
                                tiles: {},
                                isActive: false,
                                howManyTiles: 0,
                                actualTilesCount: 0,
                                loaded: false
                            };
                        }
                        tiles[`${zoomFloor}`].howManyTiles =
                            (endPos.x - startPos.x + 1) * (endPos.y - startPos.y + 1);
                        tiles[`${zoomFloor}`].actualTilesCount = 0;
                        for (let x = startPos.x; x <= endPos.x; x++) {
                            for (let y = startPos.y; y <= endPos.y; y++) {
                                addTile(x, y, zoomFloor, translateX, translateY);
                            }
                        }
                    }
                    for (const zoomKey of Object.keys(tiles)) {
                        for (const key of Object.keys(tiles[zoomKey].tiles)) {
                            if (mapView.projection && mapView.projection.def) {
                                // Calculate group translations based on first loaded
                                // tile
                                const scale = ((tileSize / worldSize) *
                                    Math.pow(2, zoom)) / ((tileSize / worldSize) *
                                    Math.pow(2, parseFloat(zoomKey))), scaledTileSize = scale * 256, firstTile = tiles[zoomKey].tiles[Object.keys(tiles[zoomKey].tiles)[0]], { posX, posY } = tiles[zoomKey].tiles[key];
                                if (defined(posX) &&
                                    defined(posY) &&
                                    defined(firstTile.posX) &&
                                    defined(firstTile.posY)) {
                                    const firstTileLonLat = this.tileToLonLat(firstTile.posX, firstTile.posY, parseFloat(zoomKey)), units = mapView.projection.def.forward([
                                        firstTileLonLat.lon + lambda,
                                        firstTileLonLat.lat
                                    ]), firstTilePx = mapView.projectedUnitsToPixels({
                                        x: units[0], y: units[1]
                                    }), tilesOffsetX = (firstTile.posX * scaledTileSize) -
                                        firstTilePx.x, tilesOffsetY = (firstTile.posY * scaledTileSize) -
                                        firstTilePx.y;
                                    if (chart.renderer.globalAnimation &&
                                        chart.hasRendered) {
                                        const startX = Number(tiles[zoomKey].tiles[key].attr('x')), startY = Number(tiles[zoomKey].tiles[key].attr('y')), startWidth = Number(tiles[zoomKey].tiles[key].attr('width')), startHeight = Number(tiles[zoomKey].tiles[key].attr('height'));
                                        const step = (now, fx) => {
                                            tiles[zoomKey].tiles[key].attr({
                                                x: (startX + (((posX * scaledTileSize) -
                                                    tilesOffsetX - startX) * fx.pos)),
                                                y: (startY + (((posY * scaledTileSize) -
                                                    tilesOffsetY - startY) * fx.pos)),
                                                width: (startWidth + ((Math.ceil(scaledTileSize) + 1 -
                                                    startWidth) * fx.pos)),
                                                height: (startHeight + ((Math.ceil(scaledTileSize) + 1 -
                                                    startHeight) * fx.pos))
                                            });
                                        };
                                        series.isAnimating = true;
                                        tiles[zoomKey].tiles[key]
                                            .attr({ animator: 0 })
                                            .animate({ animator: 1 }, { step }, function () {
                                            series.isAnimating = false;
                                            // If animate ended after loading
                                            // the tiles
                                            if (series.redrawTiles) {
                                                series.redrawTiles = false;
                                                animateTiles(duration);
                                            }
                                        });
                                        // When dragging or first rendering,
                                        // animation is off
                                    }
                                    else {
                                        // Animate tiles if something broke
                                        if (series.redrawTiles ||
                                            parseFloat(zoomKey) !== zoomFloor ||
                                            ((tiles[zoomKey].isActive ||
                                                parseFloat(zoomKey) === zoomFloor) &&
                                                Object.keys(tiles[zoomKey].tiles)
                                                    .map((key) => tiles[zoomKey].tiles[key])
                                                    .some((tile) => tile.opacity === 0))) {
                                            series.redrawTiles = false;
                                            animateTiles(duration);
                                        }
                                        tiles[zoomKey].tiles[key].attr({
                                            x: (posX * scaledTileSize) - tilesOffsetX,
                                            y: (posY * scaledTileSize) - tilesOffsetY,
                                            width: Math.ceil(scaledTileSize) + 1,
                                            height: Math.ceil(scaledTileSize) + 1
                                        });
                                    }
                                }
                            }
                        }
                    }
                }
                else {
                    error('Highcharts warning: Tiles Provider not defined in the ' +
                        'Provider Registry.', false);
                }
            }
            update() {
                const series = this, { transformGroups } = series, chart = this.chart, mapView = chart.mapView, options = arguments[0], { provider } = options;
                if (transformGroups) {
                    transformGroups.forEach((group) => {
                        if (Object.keys(group).length !== 0) {
                            group.destroy();
                        }
                    });
                    this.transformGroups = [];
                }
                if (mapView &&
                    !defined(chart.userOptions.mapView?.projection) &&
                    provider &&
                    provider.type) {
                    const ProviderDefinition = TilesProvidersRegistry[provider.type];
                    if (ProviderDefinition) {
                        const def = new ProviderDefinition(), { initialProjectionName: providerProjectionName } = def;
                        mapView.update({
                            projection: {
                                name: providerProjectionName
                            }
                        });
                    }
                }
                super.update.apply(series, arguments);
            }
        }
        TiledWebMapSeries.defaultOptions = merge(MapSeries.defaultOptions, TiledWebMapSeriesDefaults);
        SeriesRegistry.registerSeriesType('tiledwebmap', TiledWebMapSeries);
        /* *
         *
         *  Default Export
         *
         * */

        return TiledWebMapSeries;
    });
    _registerModule(_modules, 'masters/modules/tiledwebmap.src.js', [_modules['Core/Globals.js'], _modules['Maps/TilesProviders/TilesProviderRegistry.js'], _modules['Series/TiledWebMap/TiledWebMapSeries.js']], function (Highcharts, TilesProviderRegistry, TiledWebMapSeries) {

        const G = Highcharts;
        G.TilesProviderRegistry = G.TilesProviderRegistry || TilesProviderRegistry;
        TiledWebMapSeries.compose(G.MapView);

        return Highcharts;
    });
}));
