"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Legend = exports.GroupNode = exports.LayerNode = void 0;
var tslib_1 = require("tslib");
var React = tslib_1.__importStar(require("react"));
var context_1 = require("./context");
var base_layer_switcher_1 = require("./base-layer-switcher");
var type_guards_1 = require("../utils/type-guards");
var icon_1 = require("./icon");
var core_1 = require("@blueprintjs/core");
var number_1 = require("../utils/number");
var i18n_1 = require("../api/i18n");
var constants_1 = require("../constants");
var string_1 = require("../utils/string");
var context_2 = require("./map-providers/context");
var map_1 = require("../actions/map");
var dompurify_1 = require("dompurify");
var ICON_LEGEND_LAYER = "layer";
var ICON_SELECT = "select";
var ICON_LC_UNSELECT = "disable";
var ICON_LEGEND_THEME = "multi-select";
var ICON_LEGEND_TOGGLE = "chevron-down";
var ICON_LEGEND_TOGGLE_EXPAND = "chevron-right";
var ICON_LEGEND_RASTER = "media";
var ICON_FOLDER_HORIZONTAL = "folder-close";
var ICON_CLEAR = "cross";
var ICON_SEARCH = "search";
var UL_LIST_STYLE = function (baseSize) { return ({ listStyle: "none", paddingLeft: baseSize + 4, marginTop: 2, marginBottom: 2 }); };
var LI_LIST_STYLE = { listStyle: "none", marginTop: 2, marginBottom: 2 };
var ROW_ITEM_ELEMENT_STYLE = { verticalAlign: "middle" };
var CHK_STYLE = function (baseSize) { return ({ margin: 0, width: "".concat(baseSize - 2, "px"), height: "".concat(baseSize - 2, "px"), padding: 1, verticalAlign: "middle" }); };
var EMPTY_STYLE = function (baseSize) { return ({ display: "inline-block", margin: 0, width: "".concat(baseSize, "px"), height: "".concat(baseSize, "px"), verticalAlign: "middle" }); };
var EXTRAS_STYLE = function (baseSize) { return ({ display: "inline-block", margin: 0, width: "".concat(baseSize, "px"), height: "".concat(baseSize, "px"), verticalAlign: "middle" }); };
var LegendLabel = function (props) {
    var _a;
    var legendCtx = React.useContext(context_1.LegendContext);
    var inner;
    var ft = (_a = legendCtx.getFilterText()) === null || _a === void 0 ? void 0 : _a.toLocaleLowerCase();
    if (legendCtx.isFiltering() && !(0, string_1.strIsNullOrEmpty)(ft)) {
        var idx = props.text.toLocaleLowerCase().indexOf(ft);
        if (idx >= 0) {
            inner = props.text.substring(0, idx);
            inner += "<span class='legend-label-highlight-text'>".concat(props.text.substring(idx, idx + ft.length), "</span>");
            inner += props.text.substring(idx + ft.length, props.text.length);
        }
        else {
            inner = props.text;
        }
    }
    else {
        inner = props.text;
    }
    return React.createElement("span", { className: "legend-label", style: { lineHeight: "".concat(props.baseSize, "px"), verticalAlign: "middle" }, dangerouslySetInnerHTML: { __html: (0, dompurify_1.sanitize)(inner) } });
};
function getIconUri(iconMimeType, iconBase64) {
    if (iconMimeType && iconBase64) {
        return "data:".concat(iconMimeType, ";base64,").concat(iconBase64);
    }
    else {
        return undefined;
    }
}
var EmptyNode = function (props) {
    return React.createElement("div", { style: EMPTY_STYLE(props.baseSize) }, constants_1.NBSP);
};
var RuleNode = function (props) {
    var icon = getIconUri(props.iconMimeType, props.rule.Icon);
    var label = (props.rule.LegendLabel ? props.rule.LegendLabel : "");
    return React.createElement("li", { className: "layer-rule-node", style: LI_LIST_STYLE },
        React.createElement(EmptyNode, { baseSize: props.baseSize }),
        " ",
        React.createElement("img", { style: ROW_ITEM_ELEMENT_STYLE, src: icon }),
        " ",
        React.createElement(LegendLabel, { baseSize: props.baseSize, text: label }));
};
var LayerNode = function (props) {
    var _a, _b;
    var layer = props.layer;
    var legendCtx = React.useContext(context_1.LegendContext);
    var _c = React.useState(legendCtx.getLayerVisibility(props.layer)), layerVisible = _c[0], setLayerVisible = _c[1];
    var label = layer.LegendLabel ? layer.LegendLabel : "";
    var iconMimeType = legendCtx.getIconMimeType();
    var onVisibilityChanged = function (e) {
        setLayerVisible(e.target.checked);
        legendCtx.setLayerVisibility(layer.ObjectId, e.target.checked);
    };
    var onToggleSelectability = function (e) {
        var selectable = getLayerSelectability(layer.ObjectId);
        legendCtx.setLayerSelectability(layer.ObjectId, !selectable);
    };
    var getExpanded = function () {
        var expanded = legendCtx.getLayerExpanded(layer.ObjectId);
        if (expanded == null)
            expanded = layer.ExpandInLegend;
        return expanded;
    };
    var onToggleExpansion = function (e) {
        var expanded = getExpanded();
        legendCtx.setLayerExpanded(layer.ObjectId, !expanded);
    };
    var getLayerSelectability = function (layerId) {
        var selectable = legendCtx.getLayerSelectability(layerId);
        if (selectable == null) {
            selectable = layer.Selectable;
        }
        return selectable;
    };
    var text = label;
    var icon = React.createElement(icon_1.Icon, { baseSize: legendCtx.getBaseIconSize(), style: ROW_ITEM_ELEMENT_STYLE }, function (bs) { return React.createElement(core_1.Icon, { icon: ICON_LEGEND_LAYER, iconSize: bs }); });
    var selectable;
    if (layer.Selectable === true) {
        //NOTE: As we've intercepted the BP icons package, we've re-appropriated the "disable" icon for
        //disabling selection
        selectable = React.createElement(icon_1.Icon, { baseSize: legendCtx.getBaseIconSize(), style: ROW_ITEM_ELEMENT_STYLE, onClick: onToggleSelectability }, function (bs) { return React.createElement(core_1.Icon, { icon: getLayerSelectability(layer.ObjectId) ? ICON_SELECT : ICON_LC_UNSELECT, iconSize: bs }); });
    }
    var chkbox;
    if (layer.Type == 1) { //Dynamic
        chkbox = React.createElement("input", { type: 'checkbox', className: 'layer-checkbox', style: CHK_STYLE(legendCtx.getBaseIconSize()), value: layer.ObjectId, onChange: onVisibilityChanged, checked: (layerVisible) });
    }
    var tooltip = label;
    var nodeClassName = "layer-node";
    var nodeStyle = tslib_1.__assign({ whiteSpace: "nowrap", overflow: "hidden" }, LI_LIST_STYLE);
    if (layer.ScaleRange) {
        var _loop_1 = function (scaleRange) {
            if (scaleRange.FeatureStyle && scaleRange.FeatureStyle.length > 0) {
                var ruleElements = [];
                //if (debug)
                //    text = label + " (" + scaleRange.MinScale + " - " + scaleRange.MaxScale + ")";
                var body = void 0;
                var isExpanded_1 = getExpanded();
                var totalRuleCount = 0;
                for (var _e = 0, _f = scaleRange.FeatureStyle; _e < _f.length; _e++) {
                    var fts = _f[_e];
                    totalRuleCount += fts.Rule.length;
                }
                if (isExpanded_1 && totalRuleCount > 1) {
                    icon = React.createElement(icon_1.Icon, { baseSize: legendCtx.getBaseIconSize(), style: ROW_ITEM_ELEMENT_STYLE }, function (bs) { return React.createElement(core_1.Icon, { icon: ICON_LEGEND_THEME, iconSize: bs }); });
                    for (var fi = 0; fi < scaleRange.FeatureStyle.length; fi++) {
                        var fts = scaleRange.FeatureStyle[fi];
                        var ftsRuleCount = fts.Rule.length;
                        //Test compression
                        var bCompressed = false;
                        if (ftsRuleCount > 3) {
                            bCompressed = !(fts.Rule[1].Icon);
                        }
                        if (bCompressed) {
                            ruleElements.push(React.createElement(RuleNode, { baseSize: legendCtx.getBaseIconSize(), key: "layer-".concat(layer.ObjectId, "-style-").concat(fi, "-rule-first"), iconMimeType: iconMimeType, rule: fts.Rule[0] }));
                            ruleElements.push(React.createElement("li", { style: LI_LIST_STYLE, key: "layer-".concat(layer.ObjectId, "-style-").concat(fi, "-rule-compressed") },
                                React.createElement(LegendLabel, { baseSize: legendCtx.getBaseIconSize(), text: (0, i18n_1.tr)("OTHER_THEME_RULE_COUNT", legendCtx.getLocale(), { count: ftsRuleCount - 2 }) })));
                            ruleElements.push(React.createElement(RuleNode, { baseSize: legendCtx.getBaseIconSize(), key: "layer-".concat(layer.ObjectId, "-style-").concat(fi, "-rule-last"), iconMimeType: iconMimeType, rule: fts.Rule[ftsRuleCount - 1] }));
                        }
                        else {
                            for (var i = 0; i < ftsRuleCount; i++) {
                                var rule = fts.Rule[i];
                                ruleElements.push(React.createElement(RuleNode, { baseSize: legendCtx.getBaseIconSize(), key: "layer-".concat(layer.ObjectId, "-style-").concat(fi, "-rule-").concat(i), iconMimeType: iconMimeType, rule: rule }));
                            }
                        }
                    }
                }
                else { //Collapsed
                    if (totalRuleCount > 1) {
                        icon = React.createElement(icon_1.Icon, { style: ROW_ITEM_ELEMENT_STYLE, baseSize: legendCtx.getBaseIconSize() }, function (bs) { return React.createElement(core_1.Icon, { icon: ICON_LEGEND_THEME, iconSize: bs }); });
                    }
                    else {
                        var uri = getIconUri(iconMimeType, scaleRange.FeatureStyle[0].Rule[0].Icon);
                        if (uri) {
                            icon = React.createElement(icon_1.ImageIcon, { style: ROW_ITEM_ELEMENT_STYLE, url: uri });
                        }
                    }
                }
                if (ruleElements.length > 0) {
                    body = React.createElement("ul", { style: UL_LIST_STYLE(legendCtx.getBaseIconSize()) }, ruleElements);
                }
                var expanded = void 0;
                if (totalRuleCount > 1) {
                    expanded = React.createElement(icon_1.Icon, { baseSize: legendCtx.getBaseIconSize(), style: ROW_ITEM_ELEMENT_STYLE, onClick: onToggleExpansion }, function (bs) { return React.createElement(core_1.Icon, { icon: isExpanded_1 ? ICON_LEGEND_TOGGLE : ICON_LEGEND_TOGGLE_EXPAND, iconSize: bs }); });
                }
                else {
                    expanded = React.createElement(EmptyNode, { baseSize: legendCtx.getBaseIconSize() });
                }
                var mapName = legendCtx.getMapName();
                var session = legendCtx.getSessionId();
                var extras = void 0;
                if (mapName && session) {
                    extras = ((_b = (_a = legendCtx.provideExtraLayerIconsHtml) === null || _a === void 0 ? void 0 : _a.call(legendCtx, { item: layer, mapName: mapName, session: session, sanitize: dompurify_1.sanitize, elementSize: legendCtx.getBaseIconSize() })) !== null && _b !== void 0 ? _b : [])
                        .map(function (html, i) { return React.createElement("div", { style: EXTRAS_STYLE(legendCtx.getBaseIconSize()), key: "layer-".concat(layer.ObjectId, "-extras-").concat(i), dangerouslySetInnerHTML: { __html: html } }); });
                }
                return { value: React.createElement("li", { title: tooltip, style: nodeStyle, className: nodeClassName },
                        expanded,
                        " ",
                        chkbox,
                        " ",
                        selectable,
                        " ",
                        extras,
                        " ",
                        icon,
                        " ",
                        React.createElement(LegendLabel, { baseSize: legendCtx.getBaseIconSize(), text: text }),
                        " ",
                        body) };
            }
            else { //This is generally a raster
                icon = React.createElement(icon_1.Icon, { baseSize: legendCtx.getBaseIconSize(), style: ROW_ITEM_ELEMENT_STYLE }, function (bs) { return React.createElement(core_1.Icon, { icon: ICON_LEGEND_RASTER, iconSize: bs }); });
            }
        };
        for (var _i = 0, _d = layer.ScaleRange; _i < _d.length; _i++) {
            var scaleRange = _d[_i];
            var state_1 = _loop_1(scaleRange);
            if (typeof state_1 === "object")
                return state_1.value;
        }
    }
    return React.createElement("li", { title: tooltip, style: nodeStyle, className: nodeClassName },
        React.createElement(EmptyNode, { baseSize: legendCtx.getBaseIconSize() }),
        " ",
        chkbox,
        " ",
        selectable,
        " ",
        icon,
        " ",
        label);
};
exports.LayerNode = LayerNode;
var ExternalLayerNode = function (_a) {
    var layer = _a.layer;
    var legendCtx = React.useContext(context_1.LegendContext);
    var nodeClassName = "layer-node";
    var nodeStyle = tslib_1.__assign({ whiteSpace: "nowrap", overflow: "hidden" }, LI_LIST_STYLE);
    var dispatch = (0, context_2.useReduxDispatch)();
    var onVisibilityChanged = function (visible) {
        var activeMapName = legendCtx.getMapName();
        if (activeMapName) {
            dispatch((0, map_1.setMapLayerVisibility)(activeMapName, layer.name, visible));
        }
    };
    var chkbox = React.createElement("input", { type: 'checkbox', className: 'layer-checkbox', style: CHK_STYLE(legendCtx.getBaseIconSize()), onChange: function (e) { return onVisibilityChanged(e.target.checked); }, checked: layer.visible });
    var iconToUse = ICON_LEGEND_LAYER;
    if (layer.type == "WMS") {
        iconToUse = ICON_LEGEND_RASTER;
    }
    var icon = React.createElement(icon_1.Icon, { baseSize: legendCtx.getBaseIconSize(), style: ROW_ITEM_ELEMENT_STYLE }, function (bs) { return React.createElement(core_1.Icon, { icon: iconToUse, iconSize: bs }); });
    return React.createElement("li", { style: nodeStyle, className: nodeClassName },
        chkbox,
        " ",
        icon,
        " ",
        layer.displayName);
};
var ExternalLayersGroupNode = function (_a) {
    var layers = _a.layers;
    var legendCtx = React.useContext(context_1.LegendContext);
    if (layers.length == 0) {
        return React.createElement(React.Fragment, null);
    }
    else {
        var nodeClassName = "group-node";
        var icon = React.createElement(icon_1.Icon, { baseSize: legendCtx.getBaseIconSize(), style: ROW_ITEM_ELEMENT_STYLE }, function (bs) { return React.createElement(core_1.Icon, { icon: ICON_FOLDER_HORIZONTAL, iconSize: bs }); });
        var nodeStyle = tslib_1.__assign({ whiteSpace: "nowrap", overflow: "hidden" }, LI_LIST_STYLE);
        return React.createElement("li", { style: nodeStyle, className: nodeClassName },
            React.createElement("span", null,
                icon,
                " ",
                React.createElement(LegendLabel, { baseSize: legendCtx.getBaseIconSize(), text: (0, i18n_1.tr)("EXTERNAL_LAYERS", legendCtx.getLocale()) })),
            React.createElement("ul", { style: UL_LIST_STYLE(legendCtx.getBaseIconSize()) }, layers.map(function (layer, i) { return React.createElement(ExternalLayerNode, { key: "external-layer=".concat(layer.name), layer: layer }); })));
    }
};
var GroupNode = function (props) {
    var _a, _b;
    var group = props.group;
    var legendCtx = React.useContext(context_1.LegendContext);
    var getExpanded = function () {
        var expanded = legendCtx.getGroupExpanded(group.ObjectId);
        if (expanded == null)
            expanded = group.ExpandInLegend;
        return expanded;
    };
    var onToggleExpansion = function (e) {
        var expanded = getExpanded();
        legendCtx.setGroupExpanded(group.ObjectId, !expanded);
    };
    var onVisibilityChanged = function (e) {
        legendCtx.setGroupVisibility(group.ObjectId, e.target.checked);
    };
    var currentScale = legendCtx.getCurrentScale();
    var tree = legendCtx.getTree();
    var icon = React.createElement(icon_1.Icon, { baseSize: legendCtx.getBaseIconSize(), style: ROW_ITEM_ELEMENT_STYLE }, function (bs) { return React.createElement(core_1.Icon, { icon: ICON_FOLDER_HORIZONTAL, iconSize: bs }); });
    var isExpanded = getExpanded();
    var expanded = React.createElement(icon_1.Icon, { baseSize: legendCtx.getBaseIconSize(), style: ROW_ITEM_ELEMENT_STYLE, onClick: onToggleExpansion }, function (bs) { return React.createElement(core_1.Icon, { icon: isExpanded ? ICON_LEGEND_TOGGLE : ICON_LEGEND_TOGGLE_EXPAND, iconSize: bs }); });
    var chkbox = React.createElement("input", { type: 'checkbox', className: 'group-checkbox', style: CHK_STYLE(legendCtx.getBaseIconSize()), value: group.ObjectId, onChange: onVisibilityChanged, checked: legendCtx.getGroupVisibility(group) });
    var tooltip = group.LegendLabel;
    var nodeClassName = "group-node";
    var nodeStyle = tslib_1.__assign({ whiteSpace: "nowrap", overflow: "hidden" }, LI_LIST_STYLE);
    var mapName = legendCtx.getMapName();
    var session = legendCtx.getSessionId();
    var extras;
    if (mapName && session) {
        extras = ((_b = (_a = legendCtx.provideExtraGroupIconsHtml) === null || _a === void 0 ? void 0 : _a.call(legendCtx, { item: group, mapName: mapName, session: session, sanitize: dompurify_1.sanitize, elementSize: legendCtx.getBaseIconSize() })) !== null && _b !== void 0 ? _b : [])
            .map(function (html, i) { return React.createElement("div", { style: EXTRAS_STYLE(legendCtx.getBaseIconSize()), key: "group-".concat(group.ObjectId, "-extras-").concat(i), dangerouslySetInnerHTML: { __html: html } }); });
    }
    return React.createElement("li", { title: tooltip, style: nodeStyle, className: nodeClassName },
        React.createElement("span", null,
            expanded,
            " ",
            chkbox,
            " ",
            extras,
            " ",
            icon,
            " ",
            React.createElement(LegendLabel, { baseSize: legendCtx.getBaseIconSize(), text: group.LegendLabel })),
        (function () {
            if (isExpanded && props.childItems.length > 0) {
                return React.createElement("ul", { style: UL_LIST_STYLE(legendCtx.getBaseIconSize()) }, props.childItems.map(function (item) {
                    if (item.DisplayInLegend === true) {
                        if ((0, type_guards_1.isLayer)(item)) {
                            if (isLayerVisibleAtScale(item, currentScale, legendCtx.stateless)) {
                                //console.debug(`isLayerVisibleAtScale(${item.Name}, ${currentScale}) = true`);
                                return React.createElement(exports.LayerNode, { key: item.ObjectId, layer: item });
                            }
                        }
                        else {
                            if (isGroupVisibleAtScale(item, tree, currentScale, legendCtx.stateless)) {
                                //console.debug(`isGroupVisibleAtScale(${item.Name}, ${currentScale}) = true`);
                                var children = tree.groupChildren[item.ObjectId] || [];
                                return React.createElement(exports.GroupNode, { key: item.ObjectId, group: item, childItems: children });
                            }
                        }
                    }
                }));
            }
        })());
};
exports.GroupNode = GroupNode;
function isLayerVisibleAtScale(layer, scale, stateless) {
    if (layer.ScaleRange) {
        for (var _i = 0, _a = layer.ScaleRange; _i < _a.length; _i++) {
            var sr = _a[_i];
            if ((0, number_1.scaleRangeBetween)(scale, sr.MinScale, sr.MaxScale)) {
                return true;
            }
        }
    }
    else {
        // In stateless mode, it is potentially expensive to fetch all the required layer defs to get the scale range information,
        // so we must operate under the assumption that such information just doesn't exist, so in such cases assume the layer is
        // visible (in the legend), even if it is not visible (in the map)
        if (stateless) {
            return true;
        }
    }
    return false;
}
function isGroupVisibleAtScale(group, tree, scale, stateless) {
    var children = tree.groupChildren[group.ObjectId] || [];
    for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {
        var child = children_1[_i];
        if ((0, type_guards_1.isLayer)(child)) {
            if (isLayerVisibleAtScale(child, scale, stateless)) {
                return true;
            }
        }
        else {
            if (isGroupVisibleAtScale(child, tree, scale, stateless)) {
                return true;
            }
        }
    }
    if (stateless) {
        return true;
    }
    return false;
}
function itemTextFilter(items, text) {
    var filtered = items.map(function (i) {
        if ((0, type_guards_1.isLayer)(i)) {
            if (i.LegendLabel.toLocaleLowerCase().indexOf(text) < 0) {
                return null;
            }
            return i;
        }
        else {
            return i;
        }
    }).filter(function (i) { return i != null; });
    return filtered;
}
function buildFilteredTree(tree, text) {
    var filtered = {
        root: itemTextFilter(tree.root, text),
        groupChildren: {}
    };
    var keys = Object.keys(tree.groupChildren);
    for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
        var oid = keys_1[_i];
        filtered.groupChildren[oid] = itemTextFilter(tree.groupChildren[oid], text);
    }
    return filtered;
}
function setupTree(map) {
    var _a, _b;
    var state = {
        Layers: (_a = map === null || map === void 0 ? void 0 : map.Layer) !== null && _a !== void 0 ? _a : [],
        Groups: (_b = map === null || map === void 0 ? void 0 : map.Group) !== null && _b !== void 0 ? _b : [],
        LayerMap: {},
        GroupMap: {},
        tree: {
            root: [],
            groupChildren: {}
        }
    };
    if (map === null || map === void 0 ? void 0 : map.Layer) {
        for (var _i = 0, _c = map.Layer; _i < _c.length; _i++) {
            var layer = _c[_i];
            state.LayerMap[layer.ObjectId] = layer;
        }
    }
    if (map === null || map === void 0 ? void 0 : map.Group) {
        for (var _d = 0, _e = map.Group; _d < _e.length; _d++) {
            var group_1 = _e[_d];
            state.GroupMap[group_1.ObjectId] = group_1;
        }
    }
    var Layers = state.Layers, Groups = state.Groups, LayerMap = state.LayerMap, GroupMap = state.GroupMap;
    var _f = state.tree, root = _f.root, groupChildren = _f.groupChildren;
    if (Groups) {
        var remainingGroups = {};
        //1st pass, un-parented groups
        for (var _g = 0, Groups_1 = Groups; _g < Groups_1.length; _g++) {
            var group_2 = Groups_1[_g];
            groupChildren[group_2.ObjectId] = [];
            if (group_2.ParentId) {
                remainingGroups[group_2.ObjectId] = group_2;
                continue;
            }
            root.push(group_2);
        }
        //2nd pass, parented groups
        var itemCount = 0;
        for (var objId in remainingGroups) {
            itemCount++;
        }
        //Whittle down
        while (itemCount > 0) {
            var removeIds = [];
            for (var objId in remainingGroups) {
                var group = remainingGroups[objId];
                //Do we have a parent?
                if (typeof (groupChildren[group.ParentId]) != 'undefined') {
                    if (typeof (groupChildren[group.ObjectId]) != 'undefined') {
                        groupChildren[group.ObjectId] = [];
                    }
                    groupChildren[group.ParentId].push(group);
                    removeIds.push(group.ObjectId);
                }
            }
            for (var _h = 0, removeIds_1 = removeIds; _h < removeIds_1.length; _h++) {
                var id = removeIds_1[_h];
                delete remainingGroups[id];
            }
            itemCount = 0;
            for (var objId in remainingGroups) {
                itemCount++;
            }
        }
    }
    if (Layers) {
        for (var _j = 0, Layers_1 = Layers; _j < Layers_1.length; _j++) {
            var layer = Layers_1[_j];
            if (layer.ParentId) {
                //Do we have a parent?
                if (typeof (groupChildren[layer.ParentId]) === 'undefined') {
                    groupChildren[layer.ParentId] = [];
                }
                groupChildren[layer.ParentId].push(layer);
            }
            else {
                root.push(layer);
            }
        }
    }
    return state;
}
var DEFAULT_ICON_SIZE = 16;
var FILTER_BUTTON_STYLE = { position: "absolute", right: 0, top: 0 };
/**
 * The Legend component provides a component to view the layer structure, its styles and thematics and
 * the ability to toggle the group/layer visibility of the current map
 * @param props
 */
var Legend = function (props) {
    var _a, _b;
    var showGroups = props.showGroups, hideGroups = props.hideGroups, showLayers = props.showLayers, hideLayers = props.hideLayers, currentScale = props.currentScale, externalBaseLayers = props.externalBaseLayers, onBaseLayerChanged = props.onBaseLayerChanged, maxHeight = props.maxHeight, map = props.map;
    var _c = React.useState(setupTree(map)), state = _c[0], setState = _c[1];
    var _tree = state.tree;
    var _d = React.useState(false), isFiltering = _d[0], setIsFiltering = _d[1];
    var _e = React.useState(""), filterText = _e[0], setFilterText = _e[1];
    var _f = React.useState(undefined), filteredTree = _f[0], setFilteredTree = _f[1];
    React.useEffect(function () {
        onExitFilterMode();
        var tree = setupTree(map);
        setState(tree);
    }, [map]);
    var onEnterFilterMode = React.useCallback(function () {
        setIsFiltering(true);
        setFilterText("");
        setFilteredTree(_tree);
    }, []);
    var onExitFilterMode = React.useCallback(function () {
        setIsFiltering(false);
        setFilterText("");
        setFilteredTree(undefined);
    }, []);
    var onFilterUpdate = React.useCallback(function (text) {
        setFilterText(text);
        if ((0, string_1.strIsNullOrEmpty)(text)) {
            setFilteredTree(_tree);
        }
        else {
            setFilteredTree(buildFilteredTree(_tree, text.toLocaleLowerCase()));
        }
    }, [_tree]);
    var getLayerSelectability = React.useCallback(function (layerId) {
        var _a;
        var items = (_a = props.overrideSelectableLayers) !== null && _a !== void 0 ? _a : {};
        return items[layerId];
    }, [props.overrideSelectableLayers]);
    var setLayerSelectability = React.useCallback(function (layerId, selectable) {
        var _a;
        (_a = props.onLayerSelectabilityChanged) === null || _a === void 0 ? void 0 : _a.call(props, layerId, selectable);
    }, [props.onLayerSelectabilityChanged]);
    var getGroupExpanded = React.useCallback(function (groupId) {
        var _a;
        var items = (_a = props.overrideExpandedItems) !== null && _a !== void 0 ? _a : {};
        return items[groupId];
    }, [props.overrideExpandedItems]);
    var setGroupExpanded = React.useCallback(function (groupId, expanded) {
        var _a;
        (_a = props.onGroupExpansionChanged) === null || _a === void 0 ? void 0 : _a.call(props, groupId, expanded);
    }, [props.onGroupExpansionChanged]);
    var getLayerExpanded = React.useCallback(function (layerId) {
        var _a;
        var items = (_a = props.overrideExpandedItems) !== null && _a !== void 0 ? _a : {};
        return items[layerId];
    }, [props.overrideExpandedItems]);
    var setLayerExpanded = React.useCallback(function (layerId, expanded) {
        var _a;
        (_a = props.onGroupExpansionChanged) === null || _a === void 0 ? void 0 : _a.call(props, layerId, expanded);
    }, [props.onGroupExpansionChanged]);
    var getGroupVisibility = React.useCallback(function (group) {
        var visible = group.Visible;
        if (showGroups && showGroups.indexOf(group.ObjectId) >= 0) {
            visible = true;
        }
        else if (hideGroups && hideGroups.indexOf(group.ObjectId) >= 0) {
            visible = false;
        }
        return visible;
    }, [showGroups, hideGroups]);
    var getLayerVisibility = React.useCallback(function (layer) {
        var visible = layer.Visible;
        if (showLayers && showLayers.indexOf(layer.ObjectId) >= 0) {
            visible = true;
        }
        else if (hideLayers && hideLayers.indexOf(layer.ObjectId) >= 0) {
            visible = false;
        }
        return visible;
    }, [showLayers, hideLayers]);
    var setGroupVisibility = React.useCallback(function (groupId, visible) {
        var _a;
        (_a = props.onGroupVisibilityChanged) === null || _a === void 0 ? void 0 : _a.call(props, groupId, visible);
    }, [props.onGroupVisibilityChanged]);
    var setLayerVisibility = React.useCallback(function (layerId, visible) {
        var _a;
        (_a = props.onLayerVisibilityChanged) === null || _a === void 0 ? void 0 : _a.call(props, layerId, visible);
    }, [props.onLayerVisibilityChanged]);
    var getIconMimeType = React.useCallback(function () {
        var _a;
        return ((_a = props.map) === null || _a === void 0 ? void 0 : _a.IconMimeType)
            ? "".concat(props.map.IconMimeType)
            : undefined;
    }, [(_a = props.map) === null || _a === void 0 ? void 0 : _a.IconMimeType]);
    var getChildren = React.useCallback(function (objectId) {
        var _a;
        return (_a = _tree.groupChildren[objectId]) !== null && _a !== void 0 ? _a : [];
    }, [_tree]);
    var rootStyle = {
        position: "relative"
    };
    if (maxHeight) {
        rootStyle.maxHeight = maxHeight;
    }
    var providerImpl = {
        stateless: props.stateless,
        isFiltering: function () { return isFiltering; },
        getFilterText: function () { return filterText; },
        getLocale: function () { return props.locale; },
        getMapName: function () { return props.activeMapName; },
        getSessionId: function () { var _a; return (_a = props.map) === null || _a === void 0 ? void 0 : _a.SessionId; },
        getBaseIconSize: function () { var _a; return (_a = props.baseIconSize) !== null && _a !== void 0 ? _a : DEFAULT_ICON_SIZE; },
        getIconMimeType: getIconMimeType,
        getChildren: getChildren,
        getCurrentScale: function () { return props.currentScale; },
        getTree: function () { return isFiltering && filteredTree ? filteredTree : state.tree; },
        getGroupVisibility: getGroupVisibility,
        getLayerVisibility: getLayerVisibility,
        setGroupVisibility: setGroupVisibility,
        setLayerVisibility: setLayerVisibility,
        getLayerSelectability: getLayerSelectability,
        setLayerSelectability: setLayerSelectability,
        getGroupExpanded: getGroupExpanded,
        setGroupExpanded: setGroupExpanded,
        getLayerExpanded: getLayerExpanded,
        setLayerExpanded: setLayerExpanded,
        provideExtraGroupIconsHtml: props.provideExtraGroupIconsHtml,
        provideExtraLayerIconsHtml: props.provideExtraLayerIconsHtml
    };
    var daTree = providerImpl.getTree();
    var rootItems = daTree.root;
    return React.createElement(context_1.LegendContext.Provider, { value: providerImpl },
        React.createElement("div", { style: rootStyle },
            (function () {
                if (externalBaseLayers != null &&
                    externalBaseLayers.length > 0 &&
                    props.inlineBaseLayerSwitcher) {
                    return React.createElement(core_1.Card, { style: { marginBottom: 10 } },
                        React.createElement("h5", { className: "bp3-heading" },
                            React.createElement("a", { href: "#" }, (0, i18n_1.tr)("EXTERNAL_BASE_LAYERS", props.locale))),
                        React.createElement(base_layer_switcher_1.BaseLayerSwitcher, { locale: props.locale, externalBaseLayers: externalBaseLayers, onBaseLayerChanged: onBaseLayerChanged }));
                }
            })(),
            (function () {
                if (isFiltering) {
                    return React.createElement(core_1.InputGroup, { round: true, autoFocus: true, leftIcon: ICON_SEARCH, placeholder: (0, i18n_1.tr)("LEGEND_FILTER_LAYERS", props.locale), onChange: function (e) { return onFilterUpdate(e.target.value); }, rightElement: React.createElement(core_1.Button, { minimal: true, icon: ICON_CLEAR, onClick: onExitFilterMode }) });
                }
                else {
                    return React.createElement(core_1.Button, { onClick: onEnterFilterMode, title: (0, i18n_1.tr)("LEGEND_FILTER_LAYERS", props.locale), icon: ICON_SEARCH, style: FILTER_BUTTON_STYLE });
                }
            })(),
            React.createElement("ul", { style: UL_LIST_STYLE((_b = props.baseIconSize) !== null && _b !== void 0 ? _b : DEFAULT_ICON_SIZE) },
                rootItems.map(function (item) {
                    if (item.DisplayInLegend === true) {
                        if ((0, type_guards_1.isLayer)(item)) {
                            if (isLayerVisibleAtScale(item, currentScale, props.stateless)) {
                                //console.debug(`isLayerVisibleAtScale(${item.Name}, ${currentScale}) = true`);
                                return React.createElement(exports.LayerNode, { key: item.ObjectId, layer: item });
                            }
                        }
                        else {
                            var bGroupVisAtScale = isGroupVisibleAtScale(item, daTree, currentScale, props.stateless);
                            var bGroupVisFilter = false;
                            if (providerImpl.isFiltering()) {
                                var bInFilter = item.LegendLabel.toLocaleLowerCase().indexOf(providerImpl.getFilterText().toLocaleLowerCase()) >= 0;
                                //console.log(`'${item.LegendLabel}' - '${providerImpl.getFilterText()}': ${bInFilter ? "true" : "false"}`);
                                if (bInFilter) {
                                    bGroupVisFilter = true;
                                }
                            }
                            if (bGroupVisAtScale || bGroupVisFilter) {
                                //console.debug(`isGroupVisibleAtScale(${item.Name}, ${currentScale}) = true`);
                                var children = daTree.groupChildren[item.ObjectId] || [];
                                return React.createElement(exports.GroupNode, { key: item.ObjectId, group: item, childItems: children });
                            }
                        }
                    }
                }),
                props.externalLayers && React.createElement(ExternalLayersGroupNode, { layers: props.externalLayers }))));
}; /*, (a, b) => {
    const equals = [];
    equals.push(a.activeMapName === b.activeMapName);
    equals.push(a.baseIconSize === b.baseIconSize);
    equals.push(a.currentScale === b.currentScale);
    equals.push(a.externalBaseLayers === b.externalBaseLayers);
    equals.push(a.externalLayers === b.externalLayers);
    equals.push(a.hideGroups === b.hideGroups);
    equals.push(a.hideLayers === b.hideLayers);
    //equals.push(!areArraysDifferent(a.externalBaseLayers, b.externalBaseLayers));
    //equals.push(!areArraysDifferent(a.externalLayers, b.externalLayers));
    //equals.push(!areArraysDifferent(a.hideGroups, b.hideGroups));
    //equals.push(!areArraysDifferent(a.hideLayers, b.hideLayers));
    equals.push(a.inlineBaseLayerSwitcher === b.inlineBaseLayerSwitcher);
    equals.push(a.locale === b.locale);
    equals.push(a.map == b.map);
    equals.push(a.maxHeight === b.maxHeight);
    equals.push(a.onBaseLayerChanged === b.onBaseLayerChanged);
    equals.push(a.onGroupExpansionChanged === b.onGroupExpansionChanged);
    equals.push(a.onGroupVisibilityChanged === b.onGroupVisibilityChanged);
    equals.push(a.onLayerSelectabilityChanged === b.onLayerSelectabilityChanged);
    equals.push(a.onLayerVisibilityChanged === b.onLayerVisibilityChanged);
    equals.push(a.overrideExpandedItems === b.overrideExpandedItems);
    equals.push(a.overrideSelectableLayers === b.overrideSelectableLayers);
    equals.push(a.provideExtraGroupIconsHtml === b.provideExtraGroupIconsHtml);
    equals.push(a.provideExtraLayerIconsHtml === b.provideExtraLayerIconsHtml);
    equals.push(a.showGroups === b.showGroups);
    equals.push(a.showLayers === b.showLayers);
    //equals.push(!areArraysDifferent(a.showGroups, b.showGroups));
    //equals.push(!areArraysDifferent(a.showLayers, b.showLayers));
    equals.push(a.stateless === b.stateless);
    const bChanged = equals.some(s => !s);
    if (bChanged) {
        console.log("Legend changed", equals);
    }
    return bChanged;
});*/
exports.Legend = Legend;
//# sourceMappingURL=legend.js.map