/**
 * DevExtreme (esm/viz/vector_map/vector_map.js)
 * Version: 22.1.3 (build 22180-0310)
 * Build date: Wed Jun 29 2022
 *
 * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED
 * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
 */
import {
    parseScalar as _parseScalar
} from "../core/utils";
import {
    Projection
} from "./projection.main";
import {
    ControlBar
} from "./control_bar";
import {
    GestureHandler
} from "./gesture_handler";
import {
    Tracker
} from "./tracker";
import {
    DataExchanger
} from "./data_exchanger";
import {
    LegendsControl
} from "./legend";
import {
    LayoutControl
} from "./layout";
import {
    MapLayerCollection,
    getMaxBound
} from "./map_layer";
import {
    TooltipViewer
} from "./tooltip_viewer";
import {
    generateDataKey
} from "./vector_map.utils";
var DEFAULT_WIDTH = 800;
var DEFAULT_HEIGHT = 400;
var RE_STARTS_LAYERS = /^layers/;
var RE_ENDS_DATA_SOURCE = /\.dataSource$/;
import "./projection";
import BaseWidget from "../core/base_widget";

function mergeBounds(sumBounds, dataBounds) {
    return dataBounds ? [Math.min(dataBounds[0], dataBounds[2], sumBounds[0]), Math.min(dataBounds[1], dataBounds[3], sumBounds[3]), Math.max(dataBounds[0], dataBounds[2], sumBounds[2]), Math.max(dataBounds[1], dataBounds[3], sumBounds[1])] : sumBounds
}
var dxVectorMap = BaseWidget.inherit({
    _eventsMap: {
        onClick: {
            name: "click"
        },
        onCenterChanged: {
            name: "centerChanged"
        },
        onZoomFactorChanged: {
            name: "zoomFactorChanged"
        },
        onHoverChanged: {
            name: "hoverChanged"
        },
        onSelectionChanged: {
            name: "selectionChanged"
        }
    },
    _rootClassPrefix: "dxm",
    _rootClass: "dxm-vector-map",
    _themeSection: "map",
    _fontFields: ["layer:area.label.font", "layer:marker:dot.label.font", "layer:marker:bubble.label.font", "layer:marker:pie.label.font", "layer:marker:image.label.font", "legend.font", "legend.title.font", "legend.title.subtitle.font"],
    _initLayerCollection: function(dataKey) {
        var that = this;
        that._layerCollection = new MapLayerCollection({
            renderer: that._renderer,
            projection: that._projection,
            themeManager: that._themeManager,
            tracker: that._tracker,
            dataKey: dataKey,
            eventTrigger: that._eventTrigger,
            dataExchanger: that._dataExchanger,
            tooltip: that._tooltip,
            notifyDirty: that._notifyDirty,
            notifyReady: that._notifyReady,
            dataReady() {
                var bounds;
                if (that.option("getBoundsFromData") && !that.option("bounds")) {
                    that._preventProjectionEvents();
                    bounds = that._getBoundsFromData();
                    that._projection.setBounds(bounds);
                    that._allowProjectionEvents()
                }
                if (!that.option("projection")) {
                    bounds = bounds || that._getBoundsFromData();
                    if (Math.ceil(bounds[0]) < -180 || Math.ceil(bounds[3]) < -90 || Math.floor(bounds[2]) > 180 || Math.floor(bounds[1]) > 90) {
                        var longitudeLength = bounds[2] - bounds[0];
                        var latitudeLength = bounds[1] - bounds[3];
                        that._projection.setEngine({
                            to: coordinates => [2 * (coordinates[0] - bounds[0]) / longitudeLength - 1, 2 * (coordinates[1] - bounds[3]) / latitudeLength - 1],
                            from: coordinates => [(coordinates[0] + 1) * longitudeLength / 2 + bounds[0], (coordinates[1] + 1) * latitudeLength / 2 + bounds[3]]
                        })
                    }
                }
            }
        })
    },
    _getBoundsFromData() {
        var bounds = this._getBoundingBoxFromDataSource();
        if (!bounds) {
            var boundsByData = getMaxBound(this.getLayers().map(l => l.getBounds()));
            if (boundsByData) {
                bounds = boundsByData
            }
        }
        bounds = bounds || [];
        bounds = [bounds[0], bounds[3], bounds[2], bounds[1]];
        return bounds
    },
    _initLegendsControl: function() {
        this._legendsControl = new LegendsControl({
            renderer: this._renderer,
            container: this._root,
            widget: this,
            layoutControl: this._layoutControl,
            themeManager: this._themeManager,
            dataExchanger: this._dataExchanger,
            notifyDirty: this._notifyDirty,
            notifyReady: this._notifyReady
        })
    },
    _initControlBar: function(dataKey) {
        this._controlBar = new ControlBar({
            renderer: this._renderer,
            container: this._root,
            layoutControl: this._layoutControl,
            projection: this._projection,
            tracker: this._tracker,
            dataKey: dataKey
        })
    },
    _initElements: function() {
        var that = this;
        var dataKey = generateDataKey();
        var notifyCounter = 0;
        var preventProjectionEvents;
        that._preventProjectionEvents = function() {
            preventProjectionEvents = true
        };
        that._allowProjectionEvents = function() {
            preventProjectionEvents = false
        };
        that._notifyDirty = function() {
            that._resetIsReady();
            ++notifyCounter
        };
        that._notifyReady = function() {
            that._allowProjectionEvents();
            if (0 === --notifyCounter) {
                that._drawn()
            }
        };
        that._preventProjectionEvents();
        that._dataExchanger = new DataExchanger;
        that._projection = new Projection({
            centerChanged: function(value) {
                if (!preventProjectionEvents) {
                    that._eventTrigger("centerChanged", {
                        center: value
                    })
                }
            },
            zoomChanged: function(value) {
                if (!preventProjectionEvents) {
                    that._eventTrigger("zoomFactorChanged", {
                        zoomFactor: value
                    })
                }
            }
        });
        that._tracker = new Tracker({
            root: that._root,
            projection: that._projection,
            dataKey: dataKey
        });
        that._gestureHandler = new GestureHandler({
            projection: that._projection,
            renderer: that._renderer,
            tracker: that._tracker
        });
        that._layoutControl = new LayoutControl(that);
        that._layoutControl.suspend();
        that._initLayerCollection(dataKey);
        that._createHtmlStructure();
        that._initControlBar(dataKey);
        that._initLegendsControl();
        that._prepareExtraElements();
        that._tooltipViewer = new TooltipViewer({
            tracker: that._tracker,
            tooltip: that._tooltip,
            layerCollection: that._layerCollection
        })
    },
    _change_RESUME_LAYOUT: function() {
        this._layoutControl.resume()
    },
    _initialChanges: ["PROJECTION", "RESUME_LAYOUT", "LAYOUT_INIT", "BOUNDS", "MAX_ZOOM_FACTOR", "ZOOM_FACTOR", "CENTER"],
    _layoutChangesOrder: ["RESUME_LAYOUT", "LAYERS"],
    _customChangesOrder: ["EXTRA_ELEMENTS"],
    _initCore: function() {
        this._root = this._renderer.root.attr({
            align: "center",
            cursor: "default"
        });
        this._initElements()
    },
    _disposeCore: function() {
        this._controlBar.dispose();
        this._gestureHandler.dispose();
        this._tracker.dispose();
        this._legendsControl.dispose();
        this._layerCollection.dispose();
        this._layoutControl.dispose();
        this._tooltipViewer.dispose();
        this._dataExchanger.dispose();
        this._projection.dispose();
        this._dataExchanger = this._gestureHandler = this._projection = this._tracker = this._layoutControl = this._root = this._layerCollection = this._controlBar = this._legendsControl = null
    },
    _setupInteraction: function() {
        var options = {
            centeringEnabled: !!_parseScalar(this._getOption("panningEnabled", true), true),
            zoomingEnabled: !!_parseScalar(this._getOption("zoomingEnabled", true), true)
        };
        this._gestureHandler.setInteraction(options);
        this._controlBar.setInteraction(options)
    },
    _getDefaultSize: function() {
        return {
            width: DEFAULT_WIDTH,
            height: DEFAULT_HEIGHT
        }
    },
    _applySize: function(rect) {
        var layout = {
            left: rect[0],
            top: rect[1],
            width: rect[2] - rect[0],
            height: rect[3] - rect[1],
            right: 0,
            bottom: 0
        };
        this._projection.setSize(layout);
        this._layoutControl.setSize(layout);
        this._layerCollection.setRect([layout.left, layout.top, layout.width, layout.height]);
        this._requestChange(["EXTRA_ELEMENTS"])
    },
    _optionChanging: function(name, currentValue, nextValue) {
        if (currentValue && nextValue) {
            if (RE_STARTS_LAYERS.test(name)) {
                if (currentValue.dataSource && nextValue.dataSource && currentValue !== nextValue) {
                    currentValue.dataSource = null
                } else if (RE_ENDS_DATA_SOURCE.test(name)) {
                    this.option(name, null)
                }
            }
        }
    },
    _applyChanges: function() {
        this._notifyDirty();
        this.callBase.apply(this, arguments);
        this._notifyReady()
    },
    _optionChangesMap: {
        background: "BACKGROUND",
        layers: "LAYERS",
        extraElements: "EXTRA_ELEMENTS",
        controlBar: "CONTROL_BAR",
        legends: "LEGENDS",
        touchEnabled: "TRACKER",
        wheelEnabled: "TRACKER",
        panningEnabled: "INTERACTION",
        zoomingEnabled: "INTERACTION",
        projection: "PROJECTION",
        bounds: "BOUNDS",
        maxZoomFactor: "MAX_ZOOM_FACTOR",
        zoomFactor: "ZOOM_FACTOR",
        center: "CENTER"
    },
    _optionChangesOrder: ["PROJECTION", "BOUNDS", "MAX_ZOOM_FACTOR", "ZOOM_FACTOR", "CENTER", "BACKGROUND", "CONTROL_BAR", "LEGENDS", "TRACKER", "INTERACTION"],
    _change_PROJECTION: function() {
        this._setProjection()
    },
    _change_BOUNDS: function() {
        this._setBounds()
    },
    _change_MAX_ZOOM_FACTOR: function() {
        this._setMaxZoom()
    },
    _change_ZOOM_FACTOR: function() {
        this._setZoom()
    },
    _change_CENTER: function() {
        this._setCenter()
    },
    _change_BACKGROUND: function() {
        this._setBackgroundOptions()
    },
    _change_LAYERS: function() {
        this._setLayerCollectionOptions()
    },
    _change_CONTROL_BAR: function() {
        this._setControlBarOptions()
    },
    _change_EXTRA_ELEMENTS: function() {
        this._renderExtraElements()
    },
    _change_LEGENDS: function() {
        this._setLegendsOptions()
    },
    _change_TRACKER: function() {
        this._setTrackerOptions()
    },
    _change_INTERACTION: function() {
        this._setupInteraction()
    },
    _themeDependentChanges: ["BACKGROUND", "LAYERS", "CONTROL_BAR", "LEGENDS", "TRACKER", "INTERACTION"],
    _setProjection: function() {
        this._projection.setEngine(this.option("projection"))
    },
    _setBounds: function() {
        this._projection.setBounds(this.option("bounds"))
    },
    _setMaxZoom: function() {
        this._projection.setMaxZoom(this.option("maxZoomFactor"))
    },
    _setZoom: function() {
        this._projection.setZoom(this.option("zoomFactor"))
    },
    _setCenter: function() {
        this._projection.setCenter(this.option("center"))
    },
    _setBackgroundOptions: function() {
        this._layerCollection.setBackgroundOptions(this._getOption("background"))
    },
    _setLayerCollectionOptions: function() {
        this._layerCollection.setOptions(this.option("layers"))
    },
    _getBoundingBoxFromDataSource() {
        var layers = this._layerCollection.items();
        var infinityBounds = [1 / 0, -1 / 0, -1 / 0, 1 / 0];
        var resultBBox = layers && layers.length ? layers.reduce((sumBBox, l) => {
            var layerData = l.getData();
            var itemCount = layerData.count();
            if (itemCount > 0) {
                var rootBBox = layerData.getBBox();
                if (rootBBox) {
                    sumBBox = mergeBounds(sumBBox, rootBBox)
                } else {
                    for (var i = 0; i < itemCount; i++) {
                        sumBBox = mergeBounds(sumBBox, layerData.getBBox(i))
                    }
                }
            }
            return sumBBox
        }, infinityBounds) : void 0;
        return resultBBox === infinityBounds ? void 0 : resultBBox
    },
    _setControlBarOptions: function() {
        this._controlBar.setOptions(this._getOption("controlBar"))
    },
    _setLegendsOptions: function() {
        this._legendsControl.setOptions(this.option("legends"))
    },
    _setTrackerOptions: function() {
        this._tracker.setOptions({
            touchEnabled: this._getOption("touchEnabled", true),
            wheelEnabled: this._getOption("wheelEnabled", true)
        })
    },
    getLayers() {
        return this._layerCollection.items().map(l => l.proxy)
    },
    getLayerByIndex: function(index) {
        var layer = this._layerCollection.byIndex(index);
        return layer ? layer.proxy : null
    },
    getLayerByName: function(name) {
        var layer = this._layerCollection.byName(name);
        return layer ? layer.proxy : null
    },
    clearSelection: function(_noEvent) {
        var layers = this._layerCollection.items();
        var i;
        var ii = layers.length;
        for (i = 0; i < ii; ++i) {
            layers[i].clearSelection(_noEvent)
        }
        return this
    },
    center: function(value) {
        if (void 0 === value) {
            return this._projection.getCenter()
        } else {
            this._projection.setCenter(value);
            return this
        }
    },
    zoomFactor: function(value) {
        if (void 0 === value) {
            return this._projection.getZoom()
        } else {
            this._projection.setZoom(value);
            return this
        }
    },
    viewport: function(value) {
        if (void 0 === value) {
            return this._projection.getViewport()
        } else {
            this._projection.setViewport(value);
            return this
        }
    },
    convertCoordinates: function(coordinates) {
        coordinates = coordinates && coordinates.length ? coordinates : [arguments[0], arguments[1]];
        return this.convertToGeo(coordinates[0], coordinates[1])
    },
    convertToGeo: function(x, y) {
        return this._projection.fromScreenPoint([x, y])
    },
    convertToXY: function(longitude, latitude) {
        return this._projection.toScreenPoint([longitude, latitude])
    }
});
import componentRegistrator from "../../core/component_registrator";
componentRegistrator("dxVectorMap", dxVectorMap);
export default dxVectorMap;
import {
    plugin as ExportPlugin
} from "../core/export";
import {
    plugin as TitlePlugin
} from "../core/title";
import {
    plugin as TooltipPlugin
} from "../core/tooltip";
import {
    plugin as LoadingIndicatorPlugin
} from "../core/loading_indicator";
import {
    plugins as annotationsPlugins
} from "../core/annotations";
dxVectorMap.addPlugin(ExportPlugin);
dxVectorMap.addPlugin(TitlePlugin);
dxVectorMap.addPlugin(TooltipPlugin);
dxVectorMap.addPlugin(LoadingIndicatorPlugin);
dxVectorMap.addPlugin(annotationsPlugins.core);
dxVectorMap.addPlugin(annotationsPlugins.vectorMap);
