"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LayerManager = exports.getLayerInfo = void 0;
var tslib_1 = require("tslib");
var common_1 = require("./common");
var Vector_1 = tslib_1.__importDefault(require("ol/source/Vector"));
var ol_style_helpers_1 = require("./ol-style-helpers");
var Tile_1 = tslib_1.__importDefault(require("ol/layer/Tile"));
var Image_1 = tslib_1.__importDefault(require("ol/layer/Image"));
var ImageWMS_1 = tslib_1.__importDefault(require("ol/source/ImageWMS"));
var TileWMS_1 = tslib_1.__importDefault(require("ol/source/TileWMS"));
var Vector_2 = tslib_1.__importDefault(require("ol/layer/Vector"));
var Heatmap_1 = tslib_1.__importDefault(require("ol/layer/Heatmap"));
var driver_registry_1 = require("./layer-manager/driver-registry");
var i18n_1 = require("./i18n");
var ol_style_contracts_1 = require("./ol-style-contracts");
var external_layer_factory_1 = require("../components/external-layer-factory");
var colorbrewer_1 = tslib_1.__importDefault(require("colorbrewer"));
var string_1 = require("../utils/string");
var color_brewer_1 = require("../components/layer-manager/color-brewer");
function cloneObject(obj) {
    return JSON.parse(JSON.stringify(obj));
}
function clonePointWithFill(baseTemplate, fillColor) {
    if (!baseTemplate) {
        return undefined;
    }
    var clone = cloneObject(baseTemplate);
    switch (clone.type) {
        case "Circle":
            clone.fill.color = fillColor;
            break;
    }
    return clone;
}
function cloneLineWithFill(baseTemplate, fillColor) {
    if (!baseTemplate) {
        return undefined;
    }
    var clone = cloneObject(baseTemplate);
    clone.color = fillColor;
    return clone;
}
function clonePolyWithFill(baseTemplate, fillColor) {
    if (!baseTemplate) {
        return undefined;
    }
    var clone = cloneObject(baseTemplate);
    clone.fill.color = fillColor;
    return clone;
}
function ensureLabelText(style, expr, isLine) {
    if (isLine === void 0) { isLine = false; }
    if (!style.label) {
        style.label = {
            text: expr,
            textAlign: "left",
            offsetX: 15,
            fill: {
                color: "#000000",
                alpha: 255
            },
            stroke: {
                color: "#ffffff",
                alpha: 255,
                width: 3
            }
        };
        if (isLine) {
            style.label.placement = "line";
        }
    }
    else {
        style.label.text = expr;
    }
}
function ensureLabelTextForStyle(fstyle, expr) {
    if (fstyle.line) {
        ensureLabelText(fstyle.line, expr, true);
    }
    if (fstyle.point) {
        ensureLabelText(fstyle.point, expr);
    }
    if (fstyle.polygon) {
        ensureLabelText(fstyle.polygon, expr);
    }
}
function getLayerInfo(layer, isExternal) {
    var _a, _b;
    var vectorStyle;
    var cs;
    var ext;
    var hs;
    if (layer instanceof Image_1.default || layer instanceof Tile_1.default) {
        var source_1 = layer.getSource();
        if (layer.get(common_1.LayerProperty.HAS_WMS_LEGEND) == true && (source_1 instanceof ImageWMS_1.default || source_1 instanceof TileWMS_1.default)) {
            ext = {
                type: "WMS",
                getLegendUrl: function (res) { return source_1.getLegendUrl(res); }
            };
        }
    }
    if (layer instanceof Vector_2.default) {
        var vs = layer.get(common_1.LayerProperty.VECTOR_STYLE);
        if (vs) {
            vectorStyle = vs.toVectorLayerStyle();
            cs = vs.toClusterSettings();
        }
    }
    if (layer instanceof Heatmap_1.default) {
        hs = {
            blur: layer.getBlur(),
            radius: layer.getRadius()
        };
    }
    return {
        visible: layer.getVisible(),
        selectable: layer.get(common_1.LayerProperty.IS_SELECTABLE) == true,
        name: layer.get(common_1.LayerProperty.LAYER_NAME),
        displayName: (_a = layer.get(common_1.LayerProperty.LAYER_DISPLAY_NAME)) !== null && _a !== void 0 ? _a : layer.get(common_1.LayerProperty.LAYER_NAME),
        description: layer.get(common_1.LayerProperty.LAYER_DESCRIPTION),
        type: layer.get(common_1.LayerProperty.LAYER_TYPE),
        opacity: layer.getOpacity(),
        isExternal: isExternal,
        extensions: ext,
        vectorStyle: vectorStyle,
        cluster: cs,
        heatmap: hs,
        busyWorkerCount: (_b = layer.get(common_1.LayerProperty.BUSY_WORKER_COUNT)) !== null && _b !== void 0 ? _b : 0,
        metadata: layer.get(common_1.LayerProperty.LAYER_METADATA)
    };
}
exports.getLayerInfo = getLayerInfo;
var LayerManager = /** @class */ (function () {
    function LayerManager(map, layerSet) {
        this.map = map;
        this.layerSet = layerSet;
        this._olFormats = (0, driver_registry_1.getFormatDrivers)();
    }
    LayerManager.prototype.tryGetSubjectLayer = function () {
        return this.layerSet.tryGetSubjectLayer();
    };
    /**
     * INTERNAL API
     * @param {IInitialExternalLayer} extLayer
     * @returns
     * @memberof LayerManager
     */
    LayerManager.prototype.addExternalLayer = function (extLayer, onlyAddIfNotExists, appSettings) {
        if (onlyAddIfNotExists && this.hasLayer(extLayer.name)) {
            return undefined;
        }
        return this.layerSet.addExternalLayer(this.map, extLayer, appSettings);
    };
    LayerManager.prototype.getLayers = function () {
        return this.layerSet.getCustomLayers(this.map);
    };
    LayerManager.prototype.hasLayer = function (name) {
        return this.layerSet.hasLayer(name);
    };
    LayerManager.prototype.addLayer = function (name, layer, allowReplace) {
        return this.layerSet.addLayer(this.map, name, layer, allowReplace);
    };
    LayerManager.prototype.removeLayer = function (name) {
        return this.layerSet.removeLayer(this.map, name);
    };
    LayerManager.prototype.getLayer = function (name) {
        return this.layerSet.getLayer(name);
    };
    LayerManager.prototype.apply = function (layers) {
        this.layerSet.apply(this.map, layers);
    };
    LayerManager.prototype.parseFeaturesFromFile = function (options) {
        var file = options.file, layerName = options.name, locale = options.locale;
        var that = this;
        return new Promise(function (resolve, reject) {
            var reader = new FileReader();
            var handler = function (e) {
                var _a;
                return tslib_1.__awaiter(this, void 0, void 0, function () {
                    var result, formats, loadedType, bLoaded, i, ii, format, e_1;
                    return tslib_1.__generator(this, function (_b) {
                        switch (_b.label) {
                            case 0:
                                result = (_a = e.target) === null || _a === void 0 ? void 0 : _a.result;
                                if (!(result && typeof (result) == 'string')) return [3 /*break*/, 8];
                                formats = that._olFormats;
                                if (formats.length == 0) {
                                    reject(new Error((0, i18n_1.tr)("ADD_LOCAL_FILE_LAYER_FAILURE_NO_FORMATS", locale)));
                                }
                                loadedType = void 0;
                                bLoaded = false;
                                i = 0, ii = formats.length;
                                _b.label = 1;
                            case 1:
                                if (!(i < ii)) return [3 /*break*/, 7];
                                format = formats[i];
                                _b.label = 2;
                            case 2:
                                _b.trys.push([2, 4, , 5]);
                                return [4 /*yield*/, format.tryParse(file.size, result)];
                            case 3:
                                loadedType = _b.sent();
                                return [3 /*break*/, 5];
                            case 4:
                                e_1 = _b.sent();
                                return [3 /*break*/, 5];
                            case 5:
                                if (loadedType && loadedType.hasFeatures()) {
                                    loadedType.name = layerName;
                                    bLoaded = true;
                                    return [3 /*break*/, 7];
                                }
                                _b.label = 6;
                            case 6:
                                ++i;
                                return [3 /*break*/, 1];
                            case 7:
                                if (bLoaded && loadedType) {
                                    resolve(loadedType);
                                }
                                else {
                                    reject(new Error((0, i18n_1.tr)("ADD_LOCAL_FILE_LAYER_FAILURE", locale)));
                                }
                                return [3 /*break*/, 9];
                            case 8:
                                reject(new Error((0, i18n_1.tr)("ADD_LOCAL_FILE_LAYER_FAILURE_NOT_TEXT", locale)));
                                _b.label = 9;
                            case 9: return [2 /*return*/];
                        }
                    });
                });
            };
            reader.addEventListener("load", handler);
            reader.readAsText(file);
        });
    };
    LayerManager.prototype.addLayerFromParsedFeatures = function (options) {
        var _a, _b, _c;
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var features, projection, defaultStyle, extraOptions, labelOnProperty, selectedPopupTemplate, metadata, defn, proj, view, source, csArgs, layer, clusterSettings, k, bStyle, values, baseTemplatePoint, baseTemplateLine, baseTemplatePoly, th, ramp, chosenRamp, ruleCount, palette, i, v, filter, style, layerInfo;
            return tslib_1.__generator(this, function (_d) {
                switch (_d.label) {
                    case 0:
                        features = options.features, projection = options.projection, defaultStyle = options.defaultStyle, extraOptions = options.extraOptions, labelOnProperty = options.labelOnProperty, selectedPopupTemplate = options.selectedPopupTemplate, metadata = options.metadata, defn = options.defn;
                        proj = projection;
                        if (!proj) {
                            view = this.map.getView();
                            proj = view.getProjection();
                        }
                        source = new Vector_1.default();
                        source.set(common_1.SourceProperty.SUPPRESS_LOAD_EVENTS, true);
                        if ((extraOptions === null || extraOptions === void 0 ? void 0 : extraOptions.kind) == "Cluster") {
                            csArgs = {
                                distance: extraOptions.clusterDistance
                            };
                        }
                        if ((extraOptions === null || extraOptions === void 0 ? void 0 : extraOptions.kind) == "Heatmap") {
                            layer = new Heatmap_1.default({
                                source: source,
                                weight: extraOptions.weightProperty
                            });
                        }
                        else {
                            layer = new Vector_2.default({
                                source: (0, external_layer_factory_1.clusterSourceIfRequired)(source, { cluster: csArgs }),
                                className: "external-vector-layer",
                                declutter: true
                            });
                        }
                        return [4 /*yield*/, features.addTo(source, this.map.getView().getProjection(), proj)];
                    case 1:
                        _d.sent();
                        layer.set(common_1.LayerProperty.LAYER_NAME, features.name);
                        layer.set(common_1.LayerProperty.LAYER_DISPLAY_NAME, features.name);
                        layer.set(common_1.LayerProperty.LAYER_TYPE, features.type);
                        layer.set(common_1.LayerProperty.LAYER_DEFN, defn);
                        if ((extraOptions === null || extraOptions === void 0 ? void 0 : extraOptions.kind) == "Heatmap") {
                            layer.set(common_1.LayerProperty.IS_HEATMAP, true);
                        }
                        else {
                            layer.set(common_1.LayerProperty.IS_SELECTABLE, true);
                        }
                        layer.set(common_1.LayerProperty.IS_EXTERNAL, true);
                        layer.set(common_1.LayerProperty.IS_GROUP, false);
                        if (metadata) {
                            layer.set(common_1.LayerProperty.LAYER_METADATA, metadata);
                        }
                        if (selectedPopupTemplate) {
                            layer.set(common_1.LayerProperty.SELECTED_POPUP_CONFIGURATION, selectedPopupTemplate);
                        }
                        if ((extraOptions === null || extraOptions === void 0 ? void 0 : extraOptions.kind) == "Cluster") {
                            clusterSettings = {
                                distance: extraOptions.clusterDistance,
                                onClick: (_a = extraOptions.onClusterClickAction) !== null && _a !== void 0 ? _a : ol_style_contracts_1.ClusterClickAction.ShowPopup,
                                style: cloneObject((_c = (_b = extraOptions.clusterStyle) !== null && _b !== void 0 ? _b : defaultStyle) !== null && _c !== void 0 ? _c : ol_style_contracts_1.DEFAULT_CLUSTERED_LAYER_STYLE)
                            };
                            if (!(0, string_1.strIsNullOrEmpty)(labelOnProperty)) {
                                for (k in clusterSettings.style) {
                                    ensureLabelTextForStyle(clusterSettings.style[k], { expr: "if (arr_size(features) == 1, feat_property(features[0], '".concat(labelOnProperty, "'), '')") });
                                }
                            }
                        }
                        bStyle = defaultStyle !== null && defaultStyle !== void 0 ? defaultStyle : cloneObject(ol_style_contracts_1.DEFAULT_VECTOR_LAYER_STYLE);
                        if (!features.geometryTypes.includes("Point")) {
                            delete bStyle.default.point;
                            clusterSettings === null || clusterSettings === void 0 ? true : delete clusterSettings.style.default.point;
                        }
                        if (!features.geometryTypes.includes("LineString")) {
                            delete bStyle.default.line;
                            clusterSettings === null || clusterSettings === void 0 ? true : delete clusterSettings.style.default.line;
                        }
                        if (!features.geometryTypes.includes("Polygon")) {
                            delete bStyle.default.polygon;
                            clusterSettings === null || clusterSettings === void 0 ? true : delete clusterSettings.style.default.polygon;
                        }
                        if (!(0, string_1.strIsNullOrEmpty)(labelOnProperty)) {
                            ensureLabelTextForStyle(bStyle.default, { expr: labelOnProperty });
                        }
                        if (!((extraOptions === null || extraOptions === void 0 ? void 0 : extraOptions.kind) == "Theme")) return [3 /*break*/, 3];
                        return [4 /*yield*/, features.getDistinctValues(extraOptions.themeOnProperty)];
                    case 2:
                        values = _d.sent();
                        baseTemplatePoint = bStyle.default.point;
                        baseTemplateLine = bStyle.default.line;
                        baseTemplatePoly = bStyle.default.polygon;
                        th = extraOptions.colorBrewerTheme;
                        ramp = colorbrewer_1.default[th];
                        if (!ramp) {
                            ramp = colorbrewer_1.default.Blues;
                        }
                        chosenRamp = (0, color_brewer_1.getMaxRamp)(ramp);
                        ruleCount = Math.min(values.length, chosenRamp.length);
                        palette = ramp[ruleCount];
                        for (i = 0; i < ruleCount; i++) {
                            v = values[i];
                            filter = "".concat(extraOptions.themeOnProperty, " == '").concat(v, "'");
                            style = {
                                label: v,
                                point: clonePointWithFill(baseTemplatePoint, palette[i]),
                                line: cloneLineWithFill(baseTemplateLine, palette[i]),
                                polygon: clonePolyWithFill(baseTemplatePoly, palette[i]),
                            };
                            if (!(0, string_1.strIsNullOrEmpty)(labelOnProperty)) {
                                ensureLabelTextForStyle(style, { expr: labelOnProperty });
                            }
                            bStyle[filter] = style;
                        }
                        _d.label = 3;
                    case 3:
                        if (layer instanceof Vector_2.default) {
                            (0, ol_style_helpers_1.setOLVectorLayerStyle)(layer, bStyle, clusterSettings);
                        }
                        layerInfo = this.addLayer(features.name, layer);
                        return [2 /*return*/, layerInfo];
                }
            });
        });
    };
    return LayerManager;
}());
exports.LayerManager = LayerManager;
//# sourceMappingURL=layer-manager.js.map