"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseMapProviderContext = exports.useViewerSideEffects = exports.isMiddleMouseDownEvent = exports.recursiveFindLayer = exports.inflateBoundsByMeters = void 0;
var tslib_1 = require("tslib");
var React = tslib_1.__importStar(require("react"));
var ReactDOM = tslib_1.__importStar(require("react-dom"));
var common_1 = require("../../api/common");
var mouse_1 = require("../tooltips/mouse");
var Map_1 = tslib_1.__importDefault(require("ol/Map"));
var OverviewMap_1 = tslib_1.__importDefault(require("ol/control/OverviewMap"));
var DragBox_1 = tslib_1.__importDefault(require("ol/interaction/DragBox"));
var Select_1 = tslib_1.__importDefault(require("ol/interaction/Select"));
var Draw_1 = tslib_1.__importDefault(require("ol/interaction/Draw"));
var selected_features_1 = require("../tooltips/selected-features");
var Feature_1 = tslib_1.__importDefault(require("ol/Feature"));
var Polygon_1 = tslib_1.__importDefault(require("ol/geom/Polygon"));
var Attribution_1 = tslib_1.__importDefault(require("ol/control/Attribution"));
var Rotate_1 = tslib_1.__importDefault(require("ol/control/Rotate"));
var DragRotate_1 = tslib_1.__importDefault(require("ol/interaction/DragRotate"));
var DragPan_1 = tslib_1.__importDefault(require("ol/interaction/DragPan"));
var PinchRotate_1 = tslib_1.__importDefault(require("ol/interaction/PinchRotate"));
var PinchZoom_1 = tslib_1.__importDefault(require("ol/interaction/PinchZoom"));
var KeyboardPan_1 = tslib_1.__importDefault(require("ol/interaction/KeyboardPan"));
var KeyboardZoom_1 = tslib_1.__importDefault(require("ol/interaction/KeyboardZoom"));
var MouseWheelZoom_1 = tslib_1.__importDefault(require("ol/interaction/MouseWheelZoom"));
var View_1 = tslib_1.__importDefault(require("ol/View"));
var proj_1 = require("ol/proj");
var layer_manager_1 = require("../../api/layer-manager");
var olExtent = tslib_1.__importStar(require("ol/extent"));
var olEasing = tslib_1.__importStar(require("ol/easing"));
var i18n_1 = require("../../api/i18n");
var assert_1 = require("../../utils/assert");
var logger_1 = require("../../utils/logger");
var map_1 = require("../../actions/map");
var core_1 = require("@blueprintjs/core");
var ol_factory_1 = require("../../api/ol-factory");
var ismobilejs_1 = tslib_1.__importDefault(require("ismobilejs"));
var Group_1 = tslib_1.__importDefault(require("ol/layer/Group"));
var ol_style_contracts_1 = require("../../api/ol-style-contracts");
var ol_style_helpers_1 = require("../../api/ol-style-helpers");
var runtime_1 = require("../../api/runtime");
var client_1 = require("../../api/client");
var context_1 = require("./context");
function isValidView(view) {
    if (view.resolution) {
        return !isNaN(view.x)
            && !isNaN(view.y)
            && !isNaN(view.scale)
            && !isNaN(view.resolution);
    }
    else {
        return !isNaN(view.x)
            && !isNaN(view.y)
            && !isNaN(view.scale);
    }
}
function inflateBoundsByMeters(thisProj, extent, meters) {
    // We need to inflate this bbox by a known unit of measure (meters), so re-project this extent to a meter's based coordinate system (EPSG:3857)
    var webmBounds = (0, proj_1.transformExtent)(extent, thisProj, "EPSG:3857");
    // Inflate the box by specified amount
    var webmBounds2 = olExtent.buffer(webmBounds, meters);
    // Re-project this extent back to the original projection
    var inflatedBounds = (0, proj_1.transformExtent)(webmBounds2, "EPSG:3857", thisProj);
    return inflatedBounds;
}
exports.inflateBoundsByMeters = inflateBoundsByMeters;
function recursiveFindLayer(layers, predicate) {
    for (var i = 0; i < layers.getLength(); i++) {
        var layer = layers.item(i);
        if (layer instanceof Group_1.default) {
            var match = recursiveFindLayer(layer.getLayers(), predicate);
            if (match) {
                return match;
            }
        }
        else {
            if (predicate(layer)) {
                return layer;
            }
        }
    }
    return undefined;
}
exports.recursiveFindLayer = recursiveFindLayer;
function isMiddleMouseDownEvent(e) {
    return (e && (e.which == 2 || e.button == 4));
}
exports.isMiddleMouseDownEvent = isMiddleMouseDownEvent;
function useViewerSideEffects(context, appSettings, isReady, mapName, layers, initialExternalLayers, agentUri, agentKind, selection) {
    if (agentUri === void 0) { agentUri = undefined; }
    if (agentKind === void 0) { agentKind = undefined; }
    if (selection === void 0) { selection = null; }
    var dispatch = (0, context_1.useReduxDispatch)();
    // Side-effect to pre-load external layers. Should only happen once per map name
    React.useEffect(function () {
        if (isReady) {
            if (mapName && !layers) {
                (0, logger_1.debug)("React.useEffect - Change of initial external layers for [".concat(mapName, "] (change should only happen once per mapName!)"));
                if (initialExternalLayers && initialExternalLayers.length > 0) {
                    (0, logger_1.debug)("React.useEffect - First-time loading of external layers for [".concat(mapName, "]"));
                    var layerManager = context.getLayerManager(mapName);
                    for (var _i = 0, initialExternalLayers_1 = initialExternalLayers; _i < initialExternalLayers_1.length; _i++) {
                        var extLayer = initialExternalLayers_1[_i];
                        var added = layerManager.addExternalLayer(extLayer, true, appSettings);
                        if (added) {
                            dispatch((0, map_1.mapLayerAdded)(mapName, added));
                        }
                    }
                }
                else {
                    //Even if no initial external layers were loaded, the layers state still needs to be set
                    //otherwise components that depend on this state (eg. External Layer Manager) will assume
                    //this is still not ready yet
                    (0, logger_1.debug)("React.useEffect - Signal that external layers are ready for [".concat(mapName, "]"));
                    dispatch((0, map_1.externalLayersReady)(mapName));
                }
            }
        }
    }, [context, mapName, initialExternalLayers, layers, isReady]);
    // Side-effect to apply the current external layer list
    React.useEffect(function () {
        (0, logger_1.debug)("React.useEffect - Change of external layers");
        if (context.isReady() && layers) {
            var layerManager = context.getLayerManager(mapName);
            layerManager.apply(layers);
        }
    }, [context, mapName, layers]);
    // Side-effect to set the viewer "instance" once the MapViewerBase component has been mounted.
    // Should only happen once.
    React.useEffect(function () {
        (0, logger_1.debug)("React.useEffect - Change of context and/or agent URI/kind");
        (0, runtime_1.setViewer)(context);
        var browserWindow = window;
        browserWindow.getViewer = browserWindow.getViewer || runtime_1.getViewer;
        if (agentUri && agentKind) {
            browserWindow.getClient = browserWindow.getClient || (function () { return new client_1.Client(agentUri, agentKind); });
        }
        (0, logger_1.debug)("React.useEffect - Attached runtime viewer instance and installed browser global APIs");
    }, [context, agentUri, agentKind]);
    // Side-effect to imperatively refresh the map upon selection change
    React.useEffect(function () {
        (0, logger_1.debug)("React.useEffect - Change of selection");
        context.refreshMap(common_1.RefreshMode.SelectionOnly);
    }, [context, selection]);
}
exports.useViewerSideEffects = useViewerSideEffects;
var BaseMapProviderContext = /** @class */ (function () {
    function BaseMapProviderContext(olFactory) {
        if (olFactory === void 0) { olFactory = new ol_factory_1.OLFactory(); }
        var _this = this;
        this.olFactory = olFactory;
        this.onBeginDigitization = function (callback) {
            var _a;
            (_a = _this._comp) === null || _a === void 0 ? void 0 : _a.onDispatch((0, map_1.setActiveTool)(common_1.ActiveMapTool.None));
            //Could be a small timing issue here, but the active tool should generally
            //be "None" before the user clicks their first digitizing vertex/point
            callback(false);
        };
        this.onResize = function (e) {
            var _a;
            if (_this._map) {
                var size = _this._map.getSize();
                if (size) {
                    var w = size[0], h = size[1];
                    (_a = _this._comp) === null || _a === void 0 ? void 0 : _a.onDispatch((0, map_1.mapResized)(w, h));
                }
            }
        };
        this._busyWorkers = 0;
        this._layerSetGroups = {};
        this._tileSourceLoaders = {};
        this._imageSourceLoaders = {};
        this._wmsQueryAugmentations = {};
        this._triggerZoomRequestOnMoveEnd = true;
        var ism = (0, ismobilejs_1.default)(navigator.userAgent);
        this._supportsTouch = ism.phone || ism.tablet;
        var baseInitialState = {
            activeTool: common_1.ActiveMapTool.None,
            view: undefined,
            viewRotation: 0,
            viewRotationEnabled: true,
            locale: i18n_1.DEFAULT_LOCALE,
            cancelDigitizationKey: common_1.KC_ESCAPE,
            undoLastPointKey: common_1.KC_U,
            busyWorkers: 0,
            mapName: undefined,
            externalBaseLayers: undefined,
            initialExternalLayers: []
        };
        this._state = tslib_1.__assign(tslib_1.__assign({}, baseInitialState), this.getInitialProviderState());
    }
    /**
     * Exports an image of the current map view
     *
     * @param {IMapImageExportOptions} options
     * @memberof IMapViewer
     * @since 0.14
     */
    BaseMapProviderContext.prototype.exportImage = function (options) {
        if (this._map) {
            var map_2 = this._map;
            map_2.once('rendercomplete', function () {
                var mapCanvas = document.createElement('canvas');
                if (options.size) {
                    var _a = options.size, w = _a[0], h = _a[1];
                    mapCanvas.width = w;
                    mapCanvas.height = h;
                }
                else {
                    var size = map_2.getSize();
                    if (size) {
                        mapCanvas.width = size[0];
                        mapCanvas.height = size[1];
                    }
                }
                var mapContext = mapCanvas.getContext('2d');
                if (mapContext) {
                    var canvasSelector = '.ol-layer canvas, .external-vector-layer canvas';
                    Array.prototype.forEach.call(document.querySelectorAll(canvasSelector), function (canvas) {
                        var _a, _b, _c, _d, _e;
                        if (canvas.width > 0) {
                            var parentNode = canvas.parentNode;
                            var opacity = (_b = (_a = parentNode === null || parentNode === void 0 ? void 0 : parentNode.style) === null || _a === void 0 ? void 0 : _a.opacity) !== null && _b !== void 0 ? _b : "";
                            mapContext.globalAlpha = opacity === '' ? 1 : Number(opacity);
                            var transform = canvas.style.transform;
                            // Get the transform parameters from the style's transform matrix
                            var matrix = (_e = (_d = (_c = transform.match(/^matrix\(([^\(]*)\)$/)) === null || _c === void 0 ? void 0 : _c[1]) === null || _d === void 0 ? void 0 : _d.split(',')) === null || _e === void 0 ? void 0 : _e.map(Number);
                            if (matrix) {
                                // Apply the transform to the export map context
                                CanvasRenderingContext2D.prototype.setTransform.apply(mapContext, matrix);
                                mapContext.drawImage(canvas, 0, 0);
                            }
                        }
                    });
                    options.callback(mapCanvas.toDataURL(options.exportMimeType));
                }
            });
            map_2.renderSync();
        }
    };
    /**
     * Adds a custom tile load function for a given base image tile layer.
     *
     * NOTE: Unlike other load function registrations this must be done before the viewer is mounted. New load functions added at runtime will not be recognized
     * @param mapName
     * @param layerName The base layer this function should apply for
     * @param func The custom tile load function
     * @since 0.14
     */
    BaseMapProviderContext.prototype.addBaseTileLoadFunction = function (mapName, layerName, func) {
        if (!this._baseTileSourceLoaders) {
            this._baseTileSourceLoaders = {};
        }
        if (!this._baseTileSourceLoaders[mapName]) {
            this._baseTileSourceLoaders[mapName] = {};
        }
        this._baseTileSourceLoaders[mapName][layerName] = func;
    };
    /**
     * Adds a custom tile load function for a given overlay image tile layer
     * @param mapName
     * @param layerName The layer this function should apply for
     * @param func The custom tile load function
     * @since 0.14
     */
    BaseMapProviderContext.prototype.addTileLoadFunction = function (mapName, layerName, func) {
        if (!this._tileSourceLoaders) {
            this._tileSourceLoaders = {};
        }
        if (!this._tileSourceLoaders[mapName]) {
            this._tileSourceLoaders[mapName] = {};
        }
        this._tileSourceLoaders[mapName][layerName] = func;
    };
    /**
     * Adds a custom image load function for a given overlay image layer
     * @param mapName
     * @param layerName The layer this function should apply for
     * @param func The custom tile load function
     * @since 0.14
     */
    BaseMapProviderContext.prototype.addImageLoadFunction = function (mapName, layerName, func) {
        if (!this._imageSourceLoaders) {
            this._imageSourceLoaders = {};
        }
        if (!this._imageSourceLoaders[mapName]) {
            this._imageSourceLoaders[mapName] = {};
        }
        this._imageSourceLoaders[mapName][layerName] = func;
    };
    /**
     * Adds a WMS query augmentation for the given WMS overlay layer
     * @param mapName
     * @param layerName The layer this function should apply for
     * @param func The WMS query augmentation
     * @since 0.14
     */
    BaseMapProviderContext.prototype.addWmsQueryAugmentation = function (mapName, layerName, func) {
        if (!this._wmsQueryAugmentations) {
            this._wmsQueryAugmentations = {};
        }
        if (!this._wmsQueryAugmentations[mapName]) {
            this._wmsQueryAugmentations[mapName] = {};
        }
        this._wmsQueryAugmentations[mapName][layerName] = func;
    };
    BaseMapProviderContext.prototype.addCustomSelectionPopupRenderer = function (mapName, layerName, renderer) {
        if (mapName && layerName) {
            if (!this._customSelectionPopupRenderers) {
                this._customSelectionPopupRenderers = {};
            }
            if (!this._customSelectionPopupRenderers[mapName]) {
                this._customSelectionPopupRenderers[mapName] = {};
            }
            this._customSelectionPopupRenderers[mapName][layerName] = renderer;
        }
        else {
            this._globalCustomSelectionPopupRenderer = renderer;
        }
    };
    BaseMapProviderContext.prototype.getSelectionPopupRenderer = function (layerName) {
        if (!this._customSelectionPopupRenderers) {
            this._customSelectionPopupRenderers = {};
        }
        var mapName = this._state.mapName;
        if (mapName) {
            if (!this._customSelectionPopupRenderers[mapName]) {
                this._customSelectionPopupRenderers[mapName] = {};
            }
            var r = this._customSelectionPopupRenderers[mapName][layerName];
            if (r) {
                return r;
            }
        }
        if (this._globalCustomSelectionPopupRenderer) {
            return this._globalCustomSelectionPopupRenderer;
        }
        return undefined;
    };
    /**
     * @virtual
     */
    BaseMapProviderContext.prototype.hideAllPopups = function () {
        var _a, _b;
        (_a = this._mouseTooltip) === null || _a === void 0 ? void 0 : _a.clear();
        (_b = this._selectTooltip) === null || _b === void 0 ? void 0 : _b.hide();
    };
    BaseMapProviderContext.prototype.isReady = function () { return !!(this._map && this._comp); };
    //#region IMapViewer
    /**
     * @virtual
     * @returns {(IMapGuideViewerSupport | undefined)}
     * @memberof BaseMapProviderContext
     */
    BaseMapProviderContext.prototype.mapguideSupport = function () {
        return undefined;
    };
    BaseMapProviderContext.prototype.setActiveTool = function (tool) {
        var _a;
        (_a = this._comp) === null || _a === void 0 ? void 0 : _a.onDispatch((0, map_1.setActiveTool)(tool));
    };
    BaseMapProviderContext.prototype.getOLFactory = function () {
        return this.olFactory;
    };
    BaseMapProviderContext.prototype.getMapName = function () {
        return this._state.mapName;
    };
    BaseMapProviderContext.prototype.setViewRotation = function (rotation) {
        var _a;
        (_a = this._comp) === null || _a === void 0 ? void 0 : _a.onDispatch((0, map_1.setViewRotation)(rotation));
    };
    BaseMapProviderContext.prototype.getViewRotation = function () {
        return this._state.viewRotation;
    };
    BaseMapProviderContext.prototype.isViewRotationEnabled = function () {
        return this._state.viewRotationEnabled;
    };
    BaseMapProviderContext.prototype.setViewRotationEnabled = function (enabled) {
        var _a;
        (_a = this._comp) === null || _a === void 0 ? void 0 : _a.onDispatch((0, map_1.setViewRotationEnabled)(enabled));
    };
    BaseMapProviderContext.prototype.toastSuccess = function (iconName, message) {
        var _a, _b;
        return (_b = (_a = this._toasterRef) === null || _a === void 0 ? void 0 : _a.current) === null || _b === void 0 ? void 0 : _b.show({ icon: iconName, message: message, intent: core_1.Intent.SUCCESS });
    };
    BaseMapProviderContext.prototype.toastWarning = function (iconName, message) {
        var _a, _b;
        return (_b = (_a = this._toasterRef) === null || _a === void 0 ? void 0 : _a.current) === null || _b === void 0 ? void 0 : _b.show({ icon: iconName, message: message, intent: core_1.Intent.WARNING });
    };
    BaseMapProviderContext.prototype.toastError = function (iconName, message) {
        var _a, _b;
        return (_b = (_a = this._toasterRef) === null || _a === void 0 ? void 0 : _a.current) === null || _b === void 0 ? void 0 : _b.show({ icon: iconName, message: message, intent: core_1.Intent.DANGER });
    };
    BaseMapProviderContext.prototype.toastPrimary = function (iconName, message) {
        var _a, _b;
        return (_b = (_a = this._toasterRef) === null || _a === void 0 ? void 0 : _a.current) === null || _b === void 0 ? void 0 : _b.show({ icon: iconName, message: message, intent: core_1.Intent.PRIMARY });
    };
    BaseMapProviderContext.prototype.dismissToast = function (key) {
        var _a, _b;
        (_b = (_a = this._toasterRef) === null || _a === void 0 ? void 0 : _a.current) === null || _b === void 0 ? void 0 : _b.dismiss(key);
    };
    BaseMapProviderContext.prototype.addImageLoading = function () {
        var _a;
        (_a = this._comp) === null || _a === void 0 ? void 0 : _a.addImageLoading();
    };
    BaseMapProviderContext.prototype.addImageLoaded = function () {
        var _a;
        (_a = this._comp) === null || _a === void 0 ? void 0 : _a.addImageLoaded();
    };
    BaseMapProviderContext.prototype.addSubscribers = function (props) {
        var _a, _b;
        return (_b = (_a = this._comp) === null || _a === void 0 ? void 0 : _a.addSubscribers(props)) !== null && _b !== void 0 ? _b : [];
    };
    BaseMapProviderContext.prototype.removeSubscribers = function (names) {
        var _a, _b;
        return (_b = (_a = this._comp) === null || _a === void 0 ? void 0 : _a.removeSubscribers(names)) !== null && _b !== void 0 ? _b : false;
    };
    BaseMapProviderContext.prototype.getSubscribers = function () {
        var _a, _b;
        return (_b = (_a = this._comp) === null || _a === void 0 ? void 0 : _a.getSubscribers()) !== null && _b !== void 0 ? _b : [];
    };
    BaseMapProviderContext.prototype.dispatch = function (action) {
        var _a;
        (_a = this._comp) === null || _a === void 0 ? void 0 : _a.onDispatch(action);
    };
    BaseMapProviderContext.prototype.getDefaultPointCircleStyle = function () {
        return tslib_1.__assign({}, ol_style_contracts_1.DEFAULT_POINT_CIRCLE_STYLE);
    };
    BaseMapProviderContext.prototype.getDefaultPointIconStyle = function () {
        return tslib_1.__assign({}, ol_style_contracts_1.DEFAULT_POINT_ICON_STYLE);
    };
    BaseMapProviderContext.prototype.getDefaultLineStyle = function () {
        return tslib_1.__assign({}, ol_style_contracts_1.DEFAULT_LINE_STYLE);
    };
    BaseMapProviderContext.prototype.getDefaultPolygonStyle = function () {
        return tslib_1.__assign({}, ol_style_contracts_1.DEFAULT_POLY_STYLE);
    };
    BaseMapProviderContext.prototype.getBaseTileSourceLoaders = function (mapName) {
        var _a, _b;
        return (_b = (_a = this._baseTileSourceLoaders) === null || _a === void 0 ? void 0 : _a[mapName]) !== null && _b !== void 0 ? _b : {};
    };
    BaseMapProviderContext.prototype.getTileSourceLoaders = function (mapName) {
        var _a, _b;
        return (_b = (_a = this._tileSourceLoaders) === null || _a === void 0 ? void 0 : _a[mapName]) !== null && _b !== void 0 ? _b : {};
    };
    BaseMapProviderContext.prototype.getImageSourceLoaders = function (mapName) {
        var _a, _b;
        return (_b = (_a = this._imageSourceLoaders) === null || _a === void 0 ? void 0 : _a[mapName]) !== null && _b !== void 0 ? _b : {};
    };
    //#region IMapViewerContextCallback
    BaseMapProviderContext.prototype.getMockMode = function () { return undefined; };
    BaseMapProviderContext.prototype.addFeatureToHighlight = function (feat, bAppend) {
        var _a;
        if (this._state.mapName) {
            // Features have to belong to layer in order to be visible and have the highlight style, 
            // so in addition to adding this new feature to the OL select observable collection, we 
            // need to also add the feature to a scratch vector layer dedicated for this purpose
            var layerSet = this.getLayerSetGroup(this._state.mapName);
            if (layerSet) {
                var sf = (_a = this._select) === null || _a === void 0 ? void 0 : _a.getFeatures();
                if (sf) {
                    if (!bAppend) {
                        sf.clear();
                    }
                    if (feat) {
                        sf.push(feat);
                    }
                }
            }
        }
    };
    //#endregion
    //#region Map Context
    BaseMapProviderContext.prototype.getScaleForExtent = function (bounds) {
        (0, assert_1.assertIsDefined)(this._map);
        (0, assert_1.assertIsDefined)(this._state.mapName);
        var activeLayerSet = this.getLayerSetGroup(this._state.mapName);
        (0, assert_1.assertIsDefined)(activeLayerSet);
        var size = this._map.getSize();
        (0, assert_1.assertIsDefined)(size);
        var mcsW = olExtent.getWidth(bounds);
        var mcsH = olExtent.getHeight(bounds);
        var devW = size[0];
        var devH = size[1];
        var metersPerPixel = 0.0254 / activeLayerSet.getDpi();
        var metersPerUnit = activeLayerSet.getMetersPerUnit();
        //Scale calculation code from AJAX viewer
        var mapScale;
        if (devH * mcsW > devW * mcsH)
            mapScale = mcsW * metersPerUnit / (devW * metersPerPixel); // width-limited
        else
            mapScale = mcsH * metersPerUnit / (devH * metersPerPixel); // height-limited
        return mapScale;
    };
    BaseMapProviderContext.prototype.getViewForExtent = function (extent) {
        (0, assert_1.assertIsDefined)(this._map);
        var scale, center;
        // If this is a zero-width/height extent, we need to "inflate" it to something small
        // so that we do not enter an infinite loop due to attempting to get a x/y/scale from
        // a zero-width/height extent.
        //
        // This generally happens if we want to zoom to the bounds of a selected point
        if (olExtent.getWidth(extent) == 0 || olExtent.getHeight(extent) == 0) {
            var thisProj = this.getProjection();
            // Inflate the box by 20 meters
            var inflatedBounds = inflateBoundsByMeters(thisProj, extent, 20);
            // Now we can safely extract the scale/center
            scale = this.getScaleForExtent(inflatedBounds);
            center = olExtent.getCenter(inflatedBounds);
        }
        else {
            scale = this.getScaleForExtent(extent);
            center = olExtent.getCenter(extent);
        }
        return {
            x: center[0],
            y: center[1],
            scale: scale,
            resolution: this._map.getView().getResolution()
        };
    };
    BaseMapProviderContext.prototype.onZoomSelectBox = function (e) {
        var _a;
        if (this._comp) {
            var extent = (_a = this._zoomSelectBox) === null || _a === void 0 ? void 0 : _a.getGeometry();
            if (!extent) {
                return;
            }
            switch (this._state.activeTool) {
                case common_1.ActiveMapTool.Zoom:
                    {
                        var ext = extent.getExtent();
                        this._comp.onDispatch((0, map_1.setCurrentView)(this.getViewForExtent(ext)));
                    }
                    break;
                case common_1.ActiveMapTool.Select:
                    {
                        this.selectFeaturesByExtent(extent);
                    }
                    break;
            }
        }
    };
    /**
     * @virtual
     * @protected
     * @param {GenericEvent} e
     * @returns
     * @memberof BaseMapProviderContext
     */
    BaseMapProviderContext.prototype.onMouseMove = function (e) {
        if (this._comp) {
            this.handleMouseTooltipMouseMove(e);
            this.handleHighlightHover(e);
            if (this._comp.isContextMenuOpen()) {
                return;
            }
            if (this._state.mapName) {
                this._comp.onDispatch((0, map_1.setMouseCoordinates)(this._state.mapName, e.coord));
            }
        }
    };
    BaseMapProviderContext.prototype.incrementBusyWorker = function () {
        var _a;
        this._busyWorkers++;
        (_a = this._comp) === null || _a === void 0 ? void 0 : _a.onDispatch((0, map_1.setBusyCount)(this._busyWorkers));
    };
    BaseMapProviderContext.prototype.decrementBusyWorker = function () {
        var _a;
        this._busyWorkers--;
        (_a = this._comp) === null || _a === void 0 ? void 0 : _a.onDispatch((0, map_1.setBusyCount)(this._busyWorkers));
    };
    BaseMapProviderContext.prototype.applyView = function (layerSet, vw) {
        this._triggerZoomRequestOnMoveEnd = false;
        layerSet.getView().setCenter([vw.x, vw.y]);
        //Don't use this.scaleToResolution() as that uses this.props to determine
        //applicable layer set, but we already have that here
        var res = layerSet.scaleToResolution(vw.scale);
        layerSet.getView().setResolution(res);
        this._triggerZoomRequestOnMoveEnd = true;
    };
    BaseMapProviderContext.prototype.removeActiveDrawInteraction = function () {
        if (this._activeDrawInteraction && this._map && this._comp) {
            this._map.removeInteraction(this._activeDrawInteraction);
            this._activeDrawInteraction = null;
            this._comp.setDigitizingType(undefined);
        }
    };
    BaseMapProviderContext.prototype.getActiveTool = function () { return this._state.activeTool; };
    BaseMapProviderContext.prototype.cancelDigitization = function () {
        if (this.isDigitizing()) {
            this.removeActiveDrawInteraction();
            this.clearMouseTooltip();
            //this._mouseTooltip.clear();
        }
    };
    BaseMapProviderContext.prototype.pushDrawInteraction = function (digitizingType, draw, handler, prompt) {
        var _this = this;
        (0, assert_1.assertIsDefined)(this._comp);
        this.onBeginDigitization(function (cancel) {
            if (!cancel) {
                (0, assert_1.assertIsDefined)(_this._map);
                (0, assert_1.assertIsDefined)(_this._comp);
                _this.removeActiveDrawInteraction();
                //this._mouseTooltip.clear();
                _this.clearMouseTooltip();
                if (prompt) {
                    //this._mouseTooltip.setText(prompt);
                    _this.setMouseTooltip(prompt);
                }
                _this._activeDrawInteraction = draw;
                _this._activeDrawInteraction.once("drawend", function (e) {
                    var drawnFeature = e.feature;
                    var geom = drawnFeature.getGeometry();
                    _this.cancelDigitization();
                    handler(geom);
                });
                _this._map.addInteraction(_this._activeDrawInteraction);
                _this._comp.setDigitizingType(digitizingType);
            }
        });
    };
    /**
     * @virtual
     * @protected
     * @param {Polygon} geom
     * @memberof BaseMapProviderContext
     */
    BaseMapProviderContext.prototype.selectFeaturesByExtent = function (geom) { };
    BaseMapProviderContext.prototype.zoomByDelta = function (delta) {
        (0, assert_1.assertIsDefined)(this._map);
        var view = this._map.getView();
        if (!view) {
            return;
        }
        var currentZoom = view.getZoom();
        if (currentZoom !== undefined) {
            var newZoom = view.getConstrainedZoom(currentZoom + delta);
            if (view.getAnimating()) {
                view.cancelAnimations();
            }
            view.animate({
                zoom: newZoom,
                duration: 250,
                easing: olEasing.easeOut
            });
        }
    };
    BaseMapProviderContext.prototype.ensureAndGetLayerSetGroup = function (nextState) {
        (0, assert_1.assertIsDefined)(nextState.mapName);
        var layerSet = this._layerSetGroups[nextState.mapName];
        if (!layerSet) {
            layerSet = this.initLayerSet(nextState);
            this._layerSetGroups[nextState.mapName] = layerSet;
        }
        return layerSet;
    };
    //public getLayerSet(name: string, bCreate: boolean = false, props?: IMapViewerContextProps): MgLayerSet {
    BaseMapProviderContext.prototype.getLayerSetGroup = function (name) {
        var layerSet;
        if (name) {
            layerSet = this._layerSetGroups[name];
            /*
            if (!layerSet && props && bCreate) {
                layerSet = this.initLayerSet(props);
                this._layerSets[props.map.Name] = layerSet;
                this._activeMapName = props.map.Name;
            }
            */
        }
        return layerSet;
    };
    /**
     * @virtual
     * @readonly
     * @memberof BaseMapProviderContext
     */
    BaseMapProviderContext.prototype.isMouseOverTooltip = function () { var _a, _b; return (_b = (_a = this._selectTooltip) === null || _a === void 0 ? void 0 : _a.isMouseOver) !== null && _b !== void 0 ? _b : false; };
    BaseMapProviderContext.prototype.clearMouseTooltip = function () {
        var _a;
        (_a = this._mouseTooltip) === null || _a === void 0 ? void 0 : _a.clear();
    };
    BaseMapProviderContext.prototype.setMouseTooltip = function (text) {
        var _a;
        (_a = this._mouseTooltip) === null || _a === void 0 ? void 0 : _a.setText(text);
    };
    BaseMapProviderContext.prototype.handleMouseTooltipMouseMove = function (e) {
        var _a, _b;
        (_b = (_a = this._mouseTooltip) === null || _a === void 0 ? void 0 : _a.onMouseMove) === null || _b === void 0 ? void 0 : _b.call(_a, e);
    };
    BaseMapProviderContext.prototype.isLayerHoverable = function (layer) {
        return !((layer === null || layer === void 0 ? void 0 : layer.get(common_1.LayerProperty.IS_HOVER_HIGHLIGHT)) == true)
            && !((layer === null || layer === void 0 ? void 0 : layer.get(common_1.LayerProperty.IS_WMS_SELECTION_OVERLAY)) == true)
            && !((layer === null || layer === void 0 ? void 0 : layer.get(common_1.LayerProperty.IS_HEATMAP)) == true)
            && !((layer === null || layer === void 0 ? void 0 : layer.get(common_1.LayerProperty.IS_MEASURE)) == true)
            && !((layer === null || layer === void 0 ? void 0 : layer.get(common_1.LayerProperty.DISABLE_HOVER)) == true);
    };
    BaseMapProviderContext.prototype.handleHighlightHover = function (e) {
        var _this = this;
        if (e.dragging) {
            return;
        }
        if (this._state.busyWorkers > 0) {
            //console.log("Skip highlight hover due to busyWorkers > 0");
            return;
        }
        if (this._state.mapName && this._map) {
            var activeLayerSet = this.getLayerSetGroup(this._state.mapName);
            if (activeLayerSet) {
                var pixel = this._map.getEventPixel(e.originalEvent);
                if (pixel) {
                    var featureToLayerMap_1 = [];
                    this._map.forEachFeatureAtPixel(pixel, function (feature, layer) {
                        if (_this.isLayerHoverable(layer) && feature instanceof Feature_1.default) {
                            featureToLayerMap_1.push([feature, layer]);
                        }
                    });
                    var feature = featureToLayerMap_1.length ? featureToLayerMap_1[0][0] : undefined;
                    //const featuresAtPixel = this._map?.getFeaturesAtPixel(pixel);
                    //const feature = featuresAtPixel?.length ? featuresAtPixel[0] : undefined;
                    if (feature != this._highlightedFeature && feature instanceof Feature_1.default) {
                        if (this._highlightedFeature) {
                            activeLayerSet.removeHighlightedFeature(this._highlightedFeature);
                        }
                        if (feature) {
                            activeLayerSet.addHighlightedFeature(feature);
                        }
                        this._highlightedFeature = feature;
                    }
                }
            }
        }
    };
    BaseMapProviderContext.prototype.hideSelectedVectorFeaturesTooltip = function () {
        var _a;
        (_a = this._selectTooltip) === null || _a === void 0 ? void 0 : _a.hide();
    };
    BaseMapProviderContext.prototype.showSelectedVectorFeatures = function (features, pixel, featureToLayerMap, locale) {
        var _a;
        (_a = this._selectTooltip) === null || _a === void 0 ? void 0 : _a.showSelectedVectorFeatures(features, pixel, featureToLayerMap, locale);
    };
    BaseMapProviderContext.prototype.queryWmsFeatures = function (mapName, coord, bAppendMode) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var activeLayerSet, layerMgr, res;
            var _this = this;
            return tslib_1.__generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!(mapName && this._map)) return [3 /*break*/, 2];
                        activeLayerSet = this.getLayerSetGroup(mapName);
                        layerMgr = this.getLayerManager(mapName);
                        res = this._map.getView().getResolution();
                        if (!(res && this._selectTooltip)) return [3 /*break*/, 2];
                        return [4 /*yield*/, this._selectTooltip.queryWmsFeatures(activeLayerSet, layerMgr, coord, res, bAppendMode, {
                                getLocale: function () { return _this._state.locale; },
                                addClientSelectedFeature: function (feat, layer) { return _this.addClientSelectedFeature(feat, layer); },
                                addFeatureToHighlight: function (feat, bAppend) { return _this.addFeatureToHighlight(feat, bAppend); },
                                getWmsRequestAugmentations: function () { var _a; return (_a = _this._wmsQueryAugmentations[mapName]) !== null && _a !== void 0 ? _a : {}; }
                            })];
                    case 1: return [2 /*return*/, _a.sent()];
                    case 2: return [2 /*return*/, false];
                }
            });
        });
    };
    /**
     * @virtual
     * @protected
     * @param {GenericEvent} e
     * @memberof BaseMapProviderContext
     */
    BaseMapProviderContext.prototype.onImageError = function (e) { };
    BaseMapProviderContext.prototype.addClientSelectedFeature = function (f, l) {
        var _a;
        if (this._select)
            this._select.getFeatures().push(f);
        if (this._state.mapName) {
            var features = f.get("features");
            var theFeature = void 0;
            //Are we clustered?
            if (Array.isArray(features)) {
                // Only proceeed with dispatch if single item array
                if (features.length == 1) {
                    theFeature = features[0];
                }
                else {
                    return;
                }
            }
            else {
                theFeature = f;
            }
            var p = tslib_1.__assign({}, theFeature.getProperties());
            delete p[theFeature.getGeometryName()];
            var feat = {
                bounds: (_a = theFeature.getGeometry()) === null || _a === void 0 ? void 0 : _a.getExtent(),
                properties: p
            };
            this.dispatch((0, map_1.addClientSelectedFeature)(this._state.mapName, l.get(common_1.LayerProperty.LAYER_NAME), feat));
        }
    };
    BaseMapProviderContext.prototype.clearClientSelectedFeatures = function () {
        if (this._select)
            this._select.getFeatures().clear();
        if (this._state.mapName) {
            this.dispatch((0, map_1.clearClientSelection)(this._state.mapName));
        }
    };
    BaseMapProviderContext.prototype.onMapClick = function (e) {
        var _this = this;
        var _a, _b, _c;
        if (!this._comp || !this._map) {
            return;
        }
        if (this._comp.isContextMenuOpen()) {
            // We're going on the assumption that due to element placement
            // if this event is fired, it meant that the user clicked outside
            // the context menu, otherwise the context menu itself would've handled
            // the event
            (_b = (_a = this._comp).onHideContextMenu) === null || _b === void 0 ? void 0 : _b.call(_a);
        }
        if (this.isDigitizing()) {
            return;
        }
        //TODO: Our selected feature tooltip only shows properties of a single feature
        //and displays upon said feature being selected. As a result, although we can
        //(and should) allow for multiple features to be selected, we need to figure
        //out the proper UI for such a case before we enable multiple selection.
        var bAppendMode = false;
        var featureToLayerMap = [];
        if ((this._state.activeTool == common_1.ActiveMapTool.Select) && this._select) {
            if (!bAppendMode) {
                this.clearClientSelectedFeatures();
            }
            this._map.forEachFeatureAtPixel(e.pixel, function (feature, layer) {
                if (featureToLayerMap.length == 0) { //See TODO above
                    if (layer.get(common_1.LayerProperty.IS_SELECTABLE) == true && feature instanceof Feature_1.default) {
                        featureToLayerMap.push([feature, layer]);
                    }
                }
            });
            if (this._select && featureToLayerMap.length == 1) {
                var _d = featureToLayerMap[0], f = _d[0], l = _d[1];
                if ((0, ol_style_helpers_1.isClusteredFeature)(f) && (0, ol_style_helpers_1.getClusterSubFeatures)(f).length > 1 && ((_c = l.get(common_1.LayerProperty.VECTOR_STYLE)) === null || _c === void 0 ? void 0 : _c.getClusterClickAction()) == ol_style_contracts_1.ClusterClickAction.ZoomToClusterExtents) {
                    var zoomBounds = (0, ol_style_helpers_1.getClusterSubFeatures)(f).reduce(function (bounds, currentFeatures) {
                        var g = currentFeatures.getGeometry();
                        if (g) {
                            return olExtent.extend(bounds, g.getExtent());
                        }
                        else {
                            return bounds;
                        }
                    }, olExtent.createEmpty());
                    // Inflate the bounds by 20 meters so that the new view has some "breathing space" and you don't see points
                    // of the cluster on the edge of the view
                    var inflatedBounds = inflateBoundsByMeters(this.getProjection(), zoomBounds, 20);
                    this.zoomToExtent(inflatedBounds);
                }
                else {
                    this.addClientSelectedFeature(f, l);
                }
            }
        }
        // We'll only fall through the normal map selection query route if no 
        // vector features were selected as part of this click
        var px = e.pixel;
        if (featureToLayerMap.length == 0) {
            this.hideSelectedVectorFeaturesTooltip();
            if (this._state.activeTool == common_1.ActiveMapTool.Select) {
                this.queryWmsFeatures(this._state.mapName, e.coordinate, bAppendMode).then(function (madeSelection) {
                    if (!madeSelection) {
                        _this.onProviderMapClick(px);
                    }
                    else {
                        console.log("Made WMS selection. Skipping provider click event");
                    }
                });
            }
            else {
                this.onProviderMapClick(px);
            }
        }
        else {
            if (this._select) {
                if (!bAppendMode) {
                    if (this._state.mapName) {
                        var activeLayerSet = this.getLayerSetGroup(this._state.mapName);
                        activeLayerSet === null || activeLayerSet === void 0 ? void 0 : activeLayerSet.clearWmsSelectionOverlay();
                    }
                }
                this.showSelectedVectorFeatures(this._select.getFeatures(), px, featureToLayerMap, this._state.locale);
            }
        }
    };
    BaseMapProviderContext.prototype.initContext = function (layerSet, locale, overviewMapElementSelector) {
        if (this._map) {
            // HACK: className property not documented. This needs to be fixed in OL api doc.
            var overviewMapOpts = {
                className: 'ol-overviewmap ol-custom-overviewmap',
                layers: layerSet.getLayersForOverviewMap(),
                view: new View_1.default({
                    projection: layerSet.getProjection()
                }),
                tipLabel: (0, i18n_1.tr)("OL_OVERVIEWMAP_TIP", locale),
                collapseLabel: String.fromCharCode(187),
                label: String.fromCharCode(171) //'\u00AB'
            };
            if (overviewMapElementSelector) {
                var el = overviewMapElementSelector();
                if (el) {
                    overviewMapOpts.target = ReactDOM.findDOMNode(el);
                    overviewMapOpts.collapsed = false;
                    overviewMapOpts.collapsible = false;
                }
            }
            this._ovMap = new OverviewMap_1.default(overviewMapOpts);
            this._map.addControl(this._ovMap);
            this.onBeforeAttachingLayerSetGroup(layerSet);
            layerSet.attach(this._map, this._ovMap, false);
        }
    };
    //#endregion
    /**
     * @virtual
     * @protected
     * @param {TLayerSetGroup} layerSetGroup
     * @memberof BaseMapProviderContext
     */
    BaseMapProviderContext.prototype.onBeforeAttachingLayerSetGroup = function (layerSetGroup) { };
    BaseMapProviderContext.prototype.setToasterRef = function (ref) {
        this._toasterRef = ref;
    };
    BaseMapProviderContext.prototype.onKeyDown = function (e) {
        var _a, _b;
        var cancelKey = (_a = this._state.cancelDigitizationKey) !== null && _a !== void 0 ? _a : common_1.KC_ESCAPE;
        var undoKey = (_b = this._state.undoLastPointKey) !== null && _b !== void 0 ? _b : common_1.KC_U;
        if (e.keyCode == cancelKey) {
            this.cancelDigitization();
        }
        else if (e.keyCode == undoKey && this._activeDrawInteraction) {
            this._activeDrawInteraction.removeLastPoint();
        }
    };
    BaseMapProviderContext.prototype.isDigitizing = function () {
        if (!this._map)
            return false;
        var activeDraw = this._map.getInteractions().getArray().filter(function (inter) { return inter instanceof Draw_1.default; })[0];
        return activeDraw != null;
    };
    BaseMapProviderContext.prototype.detachFromComponent = function () {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
        this._comp = undefined;
        (_a = this._select) === null || _a === void 0 ? void 0 : _a.dispose();
        this._select = undefined;
        if (this._boundZoomSelectBox) {
            (_b = this._zoomSelectBox) === null || _b === void 0 ? void 0 : _b.un("boxend", this._boundZoomSelectBox);
            this._boundZoomSelectBox = undefined;
        }
        if (this._boundClick) {
            (_c = this._map) === null || _c === void 0 ? void 0 : _c.un("click", this._boundClick);
            this._boundClick = undefined;
        }
        if (this._boundMouseMove) {
            (_d = this._map) === null || _d === void 0 ? void 0 : _d.un("pointermove", this._boundMouseMove);
            this._boundMouseMove = undefined;
        }
        if (this._boundResize) {
            (_e = this._map) === null || _e === void 0 ? void 0 : _e.un("change:size", this._boundResize);
            this._boundResize = undefined;
        }
        if (this._boundMoveEnd) {
            (_f = this._map) === null || _f === void 0 ? void 0 : _f.un("moveend", this._boundMoveEnd);
            this._boundMoveEnd = undefined;
        }
        (_g = this._zoomSelectBox) === null || _g === void 0 ? void 0 : _g.dispose();
        this._zoomSelectBox = undefined;
        (_h = this._activeDrawInteraction) === null || _h === void 0 ? void 0 : _h.dispose();
        this._activeDrawInteraction = null;
        (_j = this._selectTooltip) === null || _j === void 0 ? void 0 : _j.dispose();
        this._selectTooltip = undefined;
        (_k = this._mouseTooltip) === null || _k === void 0 ? void 0 : _k.dispose();
        this._mouseTooltip = undefined;
        (_l = this._map) === null || _l === void 0 ? void 0 : _l.setTarget(undefined);
        (_m = this._ovMap) === null || _m === void 0 ? void 0 : _m.setMap(undefined); //HACK: Typings workaround
        this._map = undefined;
        this._ovMap = undefined;
        (0, logger_1.debug)("Map provider context detached from component and reset to initial state");
    };
    BaseMapProviderContext.prototype.onMoveEnd = function (e) {
        var _a, _b;
        //HACK:
        //
        //What we're hoping here is that when the view has been broadcasted back up
        //and flowed back in through new view props, that the resulting zoom/pan
        //operation in componentDidUpdate() is effectively a no-op as the intended
        //zoom/pan location has already been reached by this event right here
        //
        //If we look at this through Redux DevTools, we see 2 entries for Map/SET_VIEW
        //for the initial view (un-desirable), but we still only get one map image request
        //for the initial view (good!). Everything is fine after that.
        if (this._triggerZoomRequestOnMoveEnd) {
            var cv = this.getCurrentView();
            if (isValidView(cv)) {
                (_a = this._comp) === null || _a === void 0 ? void 0 : _a.onDispatch((0, map_1.setCurrentView)(cv));
            }
            else {
                console.warn("Attempt to set invalid view", cv);
            }
        }
        else {
            (0, logger_1.info)("Triggering zoom request on moveend suppresseed");
        }
        if (e.frameState.viewState.rotation != this._state.viewRotation) {
            (_b = this._comp) === null || _b === void 0 ? void 0 : _b.onDispatch((0, map_1.setViewRotation)(e.frameState.viewState.rotation));
        }
    };
    /**
     * @virtual
     * @param {HTMLElement} el
     * @param {IViewerComponent} comp
     * @memberof BaseMapProviderContext
     */
    BaseMapProviderContext.prototype.attachToComponent = function (el, comp) {
        var _this = this;
        this._comp = comp;
        this._select = new Select_1.default({
            condition: function (e) { return false; },
            layers: function (layer) { return layer.get(common_1.LayerProperty.IS_SELECTABLE) == true || layer.get(common_1.LayerProperty.IS_SCRATCH) == true; }
        });
        this._zoomSelectBox = new DragBox_1.default({
            condition: function (e) {
                var _a;
                // DragBox needs to be suppressed if the select tool can drag pan
                if (_this._state.activeTool == common_1.ActiveMapTool.Select && ((_a = _this._comp) === null || _a === void 0 ? void 0 : _a.selectCanDragPan()) === true) {
                    return false;
                }
                var startingMiddleMouseDrag = e.type == "pointerdown" && isMiddleMouseDownEvent(e.originalEvent);
                return !_this.isDigitizing() && !startingMiddleMouseDrag && (_this._state.activeTool === common_1.ActiveMapTool.Select || _this._state.activeTool === common_1.ActiveMapTool.Zoom);
            }
        });
        this._boundZoomSelectBox = this.onZoomSelectBox.bind(this);
        this._boundMouseMove = this.onMouseMove.bind(this);
        this._boundResize = this.onResize.bind(this);
        this._boundClick = this.onMapClick.bind(this);
        this._boundMoveEnd = this.onMoveEnd.bind(this);
        this._zoomSelectBox.on("boxend", this._boundZoomSelectBox);
        var mapOptions = {
            target: el,
            //layers: layers,
            //view: view,
            controls: [
                new Attribution_1.default({
                    tipLabel: (0, i18n_1.tr)("OL_ATTRIBUTION_TIP", this._state.locale)
                }),
                new Rotate_1.default({
                    tipLabel: (0, i18n_1.tr)("OL_RESET_ROTATION_TIP", this._state.locale)
                })
            ],
            interactions: [
                this._select,
                new DragRotate_1.default(),
                new DragPan_1.default({
                    condition: function (e) {
                        var _a;
                        // We'll allow for select tool to pan if instructed from above
                        if (_this._state.activeTool == common_1.ActiveMapTool.Select && ((_a = _this._comp) === null || _a === void 0 ? void 0 : _a.selectCanDragPan()) === true) {
                            return true;
                        }
                        var startingMiddleMouseDrag = e.type == "pointerdown" && isMiddleMouseDownEvent(e.originalEvent);
                        var enabled = (startingMiddleMouseDrag || _this._supportsTouch || _this._state.activeTool === common_1.ActiveMapTool.Pan);
                        //console.log(e);
                        //console.log(`Allow Pan - ${enabled} (middle mouse: ${startingMiddleMouseDrag})`);
                        return enabled;
                    }
                }),
                new PinchRotate_1.default(),
                new PinchZoom_1.default(),
                new KeyboardPan_1.default(),
                new KeyboardZoom_1.default(),
                new MouseWheelZoom_1.default(),
                this._zoomSelectBox
            ]
        };
        this._map = new Map_1.default(mapOptions);
        var activeLayerSet = this.ensureAndGetLayerSetGroup(this._state);
        this.initContext(activeLayerSet, this._state.locale, this._state.overviewMapElementSelector);
        this._mouseTooltip = new mouse_1.MouseTrackingTooltip(this._map, this._comp.isContextMenuOpen);
        this._selectTooltip = new selected_features_1.SelectedFeaturesTooltip(this._map, this);
        this._map.on("pointermove", this._boundMouseMove);
        this._map.on("change:size", this._boundResize);
        this._map.on("click", this._boundClick);
        this._map.on("moveend", this._boundMoveEnd);
        if (this._state.view) {
            var _a = this._state.view, x = _a.x, y = _a.y, scale = _a.scale;
            this.zoomToView(x, y, scale);
        }
        else {
            var extents = activeLayerSet.getExtent();
            this._map.getView().fit(extents);
        }
        this.onResize(this._map.getSize());
    };
    BaseMapProviderContext.prototype.scaleToResolution = function (scale) {
        (0, assert_1.assertIsDefined)(this._state.mapName);
        var activeLayerSet = this.getLayerSetGroup(this._state.mapName);
        (0, assert_1.assertIsDefined)(activeLayerSet);
        return activeLayerSet.scaleToResolution(scale);
    };
    BaseMapProviderContext.prototype.resolutionToScale = function (resolution) {
        (0, assert_1.assertIsDefined)(this._state.mapName);
        var activeLayerSet = this.getLayerSetGroup(this._state.mapName);
        (0, assert_1.assertIsDefined)(activeLayerSet);
        return activeLayerSet.resolutionToScale(resolution);
    };
    BaseMapProviderContext.prototype.getCurrentView = function () {
        var ov = this.getOLView();
        var center = ov.getCenter();
        var resolution = ov.getResolution();
        var scale = this.resolutionToScale(resolution);
        return {
            x: center[0],
            y: center[1],
            scale: scale,
            resolution: resolution
        };
    };
    BaseMapProviderContext.prototype.getCurrentExtent = function () {
        (0, assert_1.assertIsDefined)(this._map);
        return this._map.getView().calculateExtent(this._map.getSize());
    };
    BaseMapProviderContext.prototype.getSize = function () {
        (0, assert_1.assertIsDefined)(this._map);
        return this._map.getSize();
    };
    BaseMapProviderContext.prototype.getOLView = function () {
        (0, assert_1.assertIsDefined)(this._map);
        return this._map.getView();
    };
    BaseMapProviderContext.prototype.zoomToView = function (x, y, scale) {
        if (this._map) {
            var view = this._map.getView();
            view.setCenter([x, y]);
            view.setResolution(this.scaleToResolution(scale));
        }
    };
    /**
     * @virtual
     * @param {RefreshMode} [mode=RefreshMode.LayersOnly | RefreshMode.SelectionOnly]
     * @memberof BaseMapProviderContext
     */
    BaseMapProviderContext.prototype.refreshMap = function (mode) {
        if (mode === void 0) { mode = common_1.RefreshMode.LayersOnly | common_1.RefreshMode.SelectionOnly; }
    };
    BaseMapProviderContext.prototype.getMetersPerUnit = function () {
        (0, assert_1.assertIsDefined)(this._state.mapName);
        var activeLayerSet = this.getLayerSetGroup(this._state.mapName);
        (0, assert_1.assertIsDefined)(activeLayerSet);
        return activeLayerSet.getMetersPerUnit();
    };
    BaseMapProviderContext.prototype.initialView = function () {
        (0, assert_1.assertIsDefined)(this._comp);
        (0, assert_1.assertIsDefined)(this._state.mapName);
        var activeLayerSet = this.getLayerSetGroup(this._state.mapName);
        (0, assert_1.assertIsDefined)(activeLayerSet);
        this._comp.onDispatch((0, map_1.setCurrentView)(this.getViewForExtent(activeLayerSet.getExtent())));
    };
    BaseMapProviderContext.prototype.zoomDelta = function (delta) {
        //TODO: To conform to redux uni-directional data flow, this should
        //broadcast the new desired view back up and flow it back through to this
        //component as new props
        this.zoomByDelta(delta);
    };
    BaseMapProviderContext.prototype.zoomToExtent = function (extent) {
        var _a;
        (_a = this._comp) === null || _a === void 0 ? void 0 : _a.onDispatch((0, map_1.setCurrentView)(this.getViewForExtent(extent)));
    };
    BaseMapProviderContext.prototype.digitizePoint = function (handler, prompt) {
        (0, assert_1.assertIsDefined)(this._comp);
        var draw = new Draw_1.default({
            type: "Point"
        });
        this.pushDrawInteraction("Point", draw, handler, prompt || (0, i18n_1.tr)("DIGITIZE_POINT_PROMPT", this._state.locale));
    };
    BaseMapProviderContext.prototype.digitizeLine = function (handler, prompt) {
        (0, assert_1.assertIsDefined)(this._comp);
        var draw = new Draw_1.default({
            type: "LineString",
            minPoints: 2,
            maxPoints: 2
        });
        this.pushDrawInteraction("Line", draw, handler, prompt || (0, i18n_1.tr)("DIGITIZE_LINE_PROMPT", this._state.locale));
    };
    BaseMapProviderContext.prototype.digitizeLineString = function (handler, prompt) {
        var _a;
        (0, assert_1.assertIsDefined)(this._comp);
        var draw = new Draw_1.default({
            type: "LineString",
            minPoints: 2
        });
        this.pushDrawInteraction("LineString", draw, handler, prompt || (0, i18n_1.tr)("DIGITIZE_LINESTRING_PROMPT", this._state.locale, {
            key: String.fromCharCode((_a = this._state.undoLastPointKey) !== null && _a !== void 0 ? _a : common_1.KC_U) //Pray that a sane (printable) key was bound
        }));
    };
    BaseMapProviderContext.prototype.digitizeCircle = function (handler, prompt) {
        (0, assert_1.assertIsDefined)(this._comp);
        var draw = new Draw_1.default({
            type: "Circle"
        });
        this.pushDrawInteraction("Circle", draw, handler, prompt || (0, i18n_1.tr)("DIGITIZE_CIRCLE_PROMPT", this._state.locale));
    };
    BaseMapProviderContext.prototype.digitizeRectangle = function (handler, prompt) {
        (0, assert_1.assertIsDefined)(this._comp);
        var geomFunc = function (coordinates, geometry) {
            if (!geometry) {
                geometry = new Polygon_1.default([]);
            }
            var start = coordinates[0];
            var end = coordinates[1];
            geometry.setCoordinates([
                [start, [start[0], end[1]], end, [end[0], start[1]], start]
            ]);
            return geometry;
        };
        var draw = new Draw_1.default({
            type: "LineString",
            maxPoints: 2,
            geometryFunction: geomFunc
        });
        this.pushDrawInteraction("Rectangle", draw, handler, prompt || (0, i18n_1.tr)("DIGITIZE_RECT_PROMPT", this._state.locale));
    };
    BaseMapProviderContext.prototype.digitizePolygon = function (handler, prompt) {
        var _a;
        (0, assert_1.assertIsDefined)(this._comp);
        var draw = new Draw_1.default({
            type: "Polygon"
        });
        this.pushDrawInteraction("Polygon", draw, handler, prompt || (0, i18n_1.tr)("DIGITIZE_POLYGON_PROMPT", this._state.locale, {
            key: String.fromCharCode((_a = this._state.undoLastPointKey) !== null && _a !== void 0 ? _a : common_1.KC_U) //Pray that a sane (printable) key was bound
        }));
    };
    BaseMapProviderContext.prototype.addInteraction = function (interaction) {
        (0, assert_1.assertIsDefined)(this._map);
        this._map.addInteraction(interaction);
        return interaction;
    };
    BaseMapProviderContext.prototype.removeInteraction = function (interaction) {
        var _a;
        (_a = this._map) === null || _a === void 0 ? void 0 : _a.removeInteraction(interaction);
    };
    BaseMapProviderContext.prototype.addOverlay = function (overlay) {
        var _a;
        (_a = this._map) === null || _a === void 0 ? void 0 : _a.addOverlay(overlay);
    };
    BaseMapProviderContext.prototype.removeOverlay = function (overlay) {
        var _a;
        (_a = this._map) === null || _a === void 0 ? void 0 : _a.removeOverlay(overlay);
    };
    BaseMapProviderContext.prototype.getProjection = function () {
        (0, assert_1.assertIsDefined)(this._map);
        return this._map.getView().getProjection();
    };
    BaseMapProviderContext.prototype.addHandler = function (eventName, handler) {
        var _a;
        (_a = this._map) === null || _a === void 0 ? void 0 : _a.on(eventName, handler);
    };
    BaseMapProviderContext.prototype.removeHandler = function (eventName, handler) {
        var _a;
        (_a = this._map) === null || _a === void 0 ? void 0 : _a.un(eventName, handler);
    };
    BaseMapProviderContext.prototype.updateSize = function () {
        var _a;
        (_a = this._map) === null || _a === void 0 ? void 0 : _a.updateSize();
    };
    BaseMapProviderContext.prototype.getLayerManagerForLayerSet = function (layerSet) {
        (0, assert_1.assertIsDefined)(this._map);
        return new layer_manager_1.LayerManager(this._map, layerSet);
    };
    BaseMapProviderContext.prototype.getLayerManager = function (mapName) {
        (0, assert_1.assertIsDefined)(this._map);
        (0, assert_1.assertIsDefined)(this._state.mapName);
        var layerSet = this.ensureAndGetLayerSetGroup(this._state); // this.getLayerSet(mapName ?? this._state.mapName, true, this._comp as any);
        return this.getLayerManagerForLayerSet(layerSet);
    };
    BaseMapProviderContext.prototype.screenToMapUnits = function (x, y) {
        var bAllowOutsideWindow = false;
        var _a = this.getSize(), mapDevW = _a[0], mapDevH = _a[1];
        var _b = this.getCurrentExtent(), extX1 = _b[0], extY1 = _b[1], extX2 = _b[2], extY2 = _b[3];
        if (!bAllowOutsideWindow) {
            if (x > mapDevW - 1)
                x = mapDevW - 1;
            else if (x < 0)
                x = 0;
            if (y > mapDevH - 1)
                y = mapDevH - 1;
            else if (y < 0)
                y = 0;
        }
        x = extX1 + (extX2 - extX1) * (x / mapDevW);
        y = extY1 - (extY1 - extY2) * (y / mapDevH);
        return [x, y];
    };
    BaseMapProviderContext.prototype.getSelectedFeatures = function () {
        var _a;
        return (_a = this._select) === null || _a === void 0 ? void 0 : _a.getFeatures();
    };
    BaseMapProviderContext.prototype.getPointSelectionBox = function (point, ptBuffer) {
        (0, assert_1.assertIsDefined)(this._map);
        var ll = this._map.getCoordinateFromPixel([point[0] - ptBuffer, point[1] - ptBuffer]);
        var ur = this._map.getCoordinateFromPixel([point[0] + ptBuffer, point[1] + ptBuffer]);
        return [ll[0], ll[1], ur[0], ur[1]];
    };
    BaseMapProviderContext.prototype.getResolution = function () {
        (0, assert_1.assertIsDefined)(this._map);
        return this._map.getView().getResolution();
    };
    BaseMapProviderContext.prototype.updateOverviewMapElement = function (overviewMapElementSelector) {
        if (this._ovMap) {
            var el = overviewMapElementSelector();
            if (el) {
                this._ovMap.setCollapsed(false);
                this._ovMap.setCollapsible(false);
                this._ovMap.setTarget(ReactDOM.findDOMNode(el));
            }
            else {
                this._ovMap.setCollapsed(true);
                this._ovMap.setCollapsible(true);
                this._ovMap.setTarget(null);
            }
        }
    };
    return BaseMapProviderContext;
}());
exports.BaseMapProviderContext = BaseMapProviderContext;
//# sourceMappingURL=base.js.map