(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/common'), require('@wm/components/base'), require('@wm/core'), require('lodash-es')) :
    typeof define === 'function' && define.amd ? define(['exports', '@angular/core', '@angular/common', '@wm/components/base', '@wm/core', 'lodash-es'], factory) :
    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.wm = global.wm || {}, global.wm.components = global.wm.components || {}, global.wm.components.basic = global.wm.components.basic || {}, global.wm.components.basic.tree = {}), global.ng.core, global.ng.common, global.wm.components.base, global.wm.core, global._));
})(this, (function (exports, i0, common, base, core, lodashEs) { 'use strict';

    function _interopNamespaceDefault(e) {
        var n = Object.create(null);
        if (e) {
            Object.keys(e).forEach(function (k) {
                if (k !== 'default') {
                    var d = Object.getOwnPropertyDescriptor(e, k);
                    Object.defineProperty(n, k, d.get ? d : {
                        enumerable: true,
                        get: function () { return e[k]; }
                    });
                }
            });
        }
        n.default = e;
        return Object.freeze(n);
    }

    var i0__namespace = /*#__PURE__*/_interopNamespaceDefault(i0);

    const registerProps = () => {
        base.register('wm-tree', new Map([
            ['class', base.PROP_STRING],
            ['dataset', { value: 'node1, node2, node3', ...base.PROP_ANY }],
            ['datavalue', base.PROP_STRING],
            ['levels', { value: 0, ...base.PROP_NUMBER }],
            ['name', base.PROP_STRING],
            ['nodeaction', base.PROP_STRING],
            ['nodechildren', base.PROP_STRING],
            ['nodeclick', { value: 'none', ...base.PROP_STRING }],
            ['nodeicon', base.PROP_STRING],
            ['nodeid', base.PROP_STRING],
            ['nodelabel', base.PROP_STRING],
            ['orderby', base.PROP_STRING],
            ['show', { value: true, ...base.PROP_BOOLEAN }],
            ['tabindex', { value: 0, ...base.PROP_NUMBER }],
            ['treeicons', base.PROP_STRING]
        ]));
    };

    const _c0 = ["wmTree", ""];
    const WIDGET_INFO = { widgetType: 'wm-tree', hostClass: 'app-tree' };
    const defaultTreeIconClass = 'plus-minus';
    class TreeComponent extends base.StylableComponent {
        static { this.initializeProps = registerProps(); }
        constructor(inj, binddatavalue, bindnodelabel, bindnodeicon, bindnodechildren, bindnodeid, explicitContext) {
            super(inj, WIDGET_INFO, explicitContext);
            this.binddatavalue = binddatavalue;
            this.bindnodelabel = bindnodelabel;
            this.bindnodeicon = bindnodeicon;
            this.bindnodechildren = bindnodechildren;
            this.bindnodeid = bindnodeid;
            this.setting = {
                data: {
                    simpleData: {
                        enable: false
                    }
                },
                view: {
                    dblClickExpand: false,
                    fontCss: {
                        'font-awesome': true
                    },
                    switchIcon: {},
                },
                check: {},
                callback: {}
            };
            base.styler(this.nativeElement, this, base.APPLY_STYLES_TYPE.CONTAINER);
            this.setting.view['nodeClasses'] = this.setNodeClasses;
            this.setting.callback["onClick"] = this.onClick.bind(this);
            this.setting.callback["onExpand"] = this.onExpand.bind(this);
            this.setting.callback["onCollapse"] = this.onCollapse.bind(this);
        }
        onPropertyChange(key, nv, ov) {
            switch (key) {
                case 'dataset':
                    this.nodes = this.getNodes(nv);
                    this.renderTree();
                    break;
                case 'levels':
                    this.level = nv;
                    this.renderTree();
                    break;
                case 'nodeicon':
                    this.nodeicon = nv;
                    this.renderTree();
                    break;
                case 'nodelabel':
                    this.nodelabel = nv;
                    this.renderTree();
                    break;
                case 'nodechildren':
                    this.nodechildren = nv;
                    this.renderTree();
                    break;
                case 'orderby':
                    this.orderby = nv;
                    this.renderTree();
                    break;
                case 'treeicons':
                    this.treeicons = nv;
                    this.renderTree();
                    break;
                case 'class':
                    this.treeClass = nv;
                    this.setTreeTemplate(this.treeClass);
                    this.renderTree();
                default:
                    super.onPropertyChange(key, nv, ov);
                    break;
            }
        }
        // expands the tree nodes if the property is selected.
        expandTree(level, node, childLevel) {
            node.map(childNode => {
                const children = childNode.children;
                if (children && childLevel < level) {
                    childNode.open = true;
                    this.expandTree(level, children, childLevel + 1);
                }
                else {
                    childLevel = 0;
                    return;
                }
            });
        }
        // sets the template for the tree based on the property selected.
        setTreeTemplate(value) {
            const classList = value.split(" ");
            if (classList.includes('Classic')) {
                this.setting.check["enable"] = false;
            }
            else if (classList.includes('Checkbox')) {
                this.setting.check["enable"] = true;
                this.setting.check["chkStyle"] = 'checkbox';
            }
            else if (classList.includes('Radio')) {
                this.setting.check["enable"] = true;
                this.setting.check["chkStyle"] = 'radio';
                this.setting.check["radioType"] = "all";
            }
        }
        // extracts nodes from string format
        getNodesFromString(value) {
            return value.split(',').map((item) => {
                return {
                    'label': item && item.trim()
                };
            });
        }
        // gets the nodes and orders the nodes if required
        getNodes(newVal) {
            let nodes;
            if (lodashEs.isArray(newVal)) {
                nodes = base.getOrderedDataset(newVal, this.orderby);
            }
            else if (lodashEs.isObject(newVal)) {
                nodes = [newVal];
            }
            else if (lodashEs.isString(newVal) && !lodashEs.isEmpty(newVal)) {
                newVal = newVal.trim();
                if (newVal) {
                    nodes = this.getNodesFromString(newVal);
                }
            }
            return nodes;
        }
        // adds class to the nodes inorder to add icons to respective node.
        setNodeClasses(treeId, treeNode) {
            return treeNode.icon ? { add: [`${treeNode.icon}`] } : '';
        }
        ;
        // adds tree icons to the nodes on load of the tree
        changeTreeIcons(nv) {
            let eleClose = $('ul[name="' + this.name + '"] li span.button.switch');
            $(eleClose).map((idx, ele) => {
                $(ele).addClass(nv);
                $(ele).on("click", function (e) {
                    setTimeout(() => {
                        $(ele).addClass(nv);
                    }, 0);
                });
            });
        }
        // Returns the node path
        getPath(treeNode, path) {
            if (treeNode.getParentNode() === null) {
                path = "/" + treeNode.name + path;
            }
            else {
                path = this.getPath(treeNode.getParentNode(), path) + "/" + treeNode.name;
            }
            return path;
        }
        // binds the click event to all nodes to open the child nodes
        onClick(event, treeId, treeNode, clickFlag) {
            if (this.nodeclick === "expand") {
                var nodes = this.zTree.getSelectedNodes();
                if (nodes.length > 0) {
                    this.expandNode(nodes[0], !nodes[0].open, true);
                }
            }
            this.selectNode(event, treeNode);
        }
        // Adds tree icon classes to child nodes when expanded
        onExpand(event, treeId, treeNode) {
            let self = this;
            let path = this.getPath(treeNode, "");
            const eventParams = {
                '$event': event,
                "$item": core.getClonedObject(treeNode.data),
                "$path": path
            };
            this.invokeEventCallback('expand', eventParams);
            const children = treeNode.children;
            children?.map((el) => {
                if (el.isParent) {
                    let ele = $(`#${el.tId}_switch`);
                    $(ele).addClass(self.treeicons || defaultTreeIconClass);
                    $(ele).on("click", function (e) {
                        setTimeout(() => {
                            $(ele).addClass(self.treeicons || defaultTreeIconClass);
                        }, 0);
                    });
                }
            });
        }
        onCollapse(event, treeId, treeNode) {
            let path = this.getPath(treeNode, "");
            const eventParams = {
                '$event': event,
                "$item": core.getClonedObject(treeNode.data),
                "$path": path
            };
            this.invokeEventCallback('collapse', eventParams);
        }
        // function to support backward compatibility of objects
        constructZTreeData(data, zTreeData) {
            data.forEach(node => {
                const zNode = {};
                const name = base.getEvaluatedData(node, { field: this.nodelabel, bindExpression: this.bindnodelabel }, this.viewParent) || node.label;
                const icon = base.getEvaluatedData(node, { field: this.nodeicon, bindExpression: this.bindnodeicon }, this.viewParent) || node.icon;
                const nodeId = base.getEvaluatedData(node, { field: this.nodeid, bindExpression: this.bindnodeid }, this.viewParent);
                const children = base.getEvaluatedData(node, { field: this.nodechildren, bindExpression: this.bindnodechildren }, this.viewParent) || node.children;
                zNode['name'] = name;
                zNode['icon'] = icon;
                zNode['nodeId'] = nodeId;
                zNode['data'] = core.getClonedObject(node);
                if (lodashEs.isArray(children) && children.length) {
                    zNode['children'] = [];
                    this.constructZTreeData(children, zNode['children']);
                }
                zTreeData.push(zNode);
            });
        }
        // Renders the tree on to the dom
        renderTree() {
            this.zTreeNodes = [];
            if (this.nodes?.length) {
                this.nativeElement.setAttribute('id', this.name);
                this.constructZTreeData(this.nodes, this.zTreeNodes);
                if (this.level > 0) {
                    this.expandTree(this.level, this.zTreeNodes, 0);
                }
            }
            this.zTree = $.fn.zTree.init($('ul[name="' + this.name + '"]'), this.setting, this.zTreeNodes);
            $.fn.zTreeKeyboardNavigation(this.zTree, $('ul[name="' + this.name + '"]'), null, this.treeicons || defaultTreeIconClass);
            this.postRenderTree();
        }
        setChecked(zNode, node) {
            node.checked = zNode.checked;
            const children = base.getEvaluatedData(node, { field: this.nodechildren, bindExpression: this.bindnodechildren }, this.viewParent) || node.children;
            if (children?.length) {
                children.forEach((node, index) => {
                    this.setChecked(zNode.children[index], node);
                });
            }
        }
        selectNode(event, node) {
            const deSelectElm = $(`.app-tree[name=${this.name}] li[treenode].selected`);
            deSelectElm.removeClass('selected');
            if (!node) {
                return;
            }
            const selectElm = $(`#${node.tId}:has(.curSelectedNode)`);
            selectElm.addClass('selected');
            const classList = (this.treeClass || "").split(" ");
            if (classList.includes('Checkbox') || classList.includes('Radio')) {
                this.setChecked(node, node.data);
            }
            const path = this.getPath(node, "");
            this.selecteditem = core.getClonedObject(node.data) || {};
            this.selecteditem.path = path;
            const eventParams = {
                '$event': event,
                "$item": core.getClonedObject(node.data),
                "$path": path
            };
            //[Todo-CSP]: this data will be dynamic, can not generate function upfront
            const nodeAction = node.data[this.nodeaction || 'action'];
            if (nodeAction) {
                core.$parseEvent(nodeAction)(this);
            }
            this.invokeEventCallback('select', eventParams);
        }
        expandNode(node, expand, eventFlag) {
            this.zTree.expandNode(node, expand, false, false, eventFlag);
            const el = $(`#${node.tId}_switch`);
            $(el).addClass(this.treeicons || defaultTreeIconClass);
        }
        postRenderTree() {
            setTimeout(() => {
                this.changeTreeIcons(this.treeicons || defaultTreeIconClass);
                if (this.datavalue && !this.selecteditem) {
                    const nodes = this.zTree.getNodes();
                    let node;
                    if (nodes.length) {
                        if (this.datavalue === 'FirstNode') {
                            node = nodes[0];
                        }
                        if (this.datavalue === 'LastNode') {
                            node = nodes[nodes.length - 1];
                        }
                    }
                    if (node) {
                        this.zTree.selectNode(node, false);
                        this.selectNode(undefined, node);
                        this.expandNode(node, true, false);
                    }
                }
            }, 200);
        }
        selectById(value) {
            const simpleNodes = this.zTree?.transformToArray(this.zTree.getNodes());
            const node = simpleNodes?.find(node => value === node.nodeId);
            if (node) {
                this.zTree.selectNode(node, false);
                this.selectNode(undefined, node);
            }
        }
        deselectById(value) {
            this.selecteditem = {};
            this.selectById();
        }
        static { this.ɵfac = function TreeComponent_Factory(t) { return new (t || TreeComponent)(i0__namespace.ɵɵdirectiveInject(i0__namespace.Injector), i0__namespace.ɵɵinjectAttribute('datavalue.bind'), i0__namespace.ɵɵinjectAttribute('nodelabel.bind'), i0__namespace.ɵɵinjectAttribute('nodeicon.bind'), i0__namespace.ɵɵinjectAttribute('nodechildren.bind'), i0__namespace.ɵɵinjectAttribute('nodeid.bind'), i0__namespace.ɵɵdirectiveInject('EXPLICIT_CONTEXT', 8)); }; }
        static { this.ɵcmp = /*@__PURE__*/ i0__namespace.ɵɵdefineComponent({ type: TreeComponent, selectors: [["ul", "wmTree", ""]], features: [i0__namespace.ɵɵProvidersFeature([
                    base.provideAsWidgetRef(TreeComponent)
                ]), i0__namespace.ɵɵInheritDefinitionFeature], attrs: _c0, decls: 2, vars: 0, consts: [["wmTree", ""], ["id", "ztree", 1, "ztree"]], template: function TreeComponent_Template(rf, ctx) { if (rf & 1) {
                i0__namespace.ɵɵelement(0, "ul", 1, 0);
            } }, encapsulation: 2 }); }
    }
    (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0__namespace.ɵsetClassMetadata(TreeComponent, [{
            type: i0.Component,
            args: [{ selector: 'ul[wmTree]', providers: [
                        base.provideAsWidgetRef(TreeComponent)
                    ], encapsulation: i0.ViewEncapsulation.None, template: "<ul #wmTree class=\"ztree\" id=\"ztree\"></ul>  " }]
        }], () => [{ type: i0__namespace.Injector }, { type: undefined, decorators: [{
                    type: i0.Attribute,
                    args: ['datavalue.bind']
                }] }, { type: undefined, decorators: [{
                    type: i0.Attribute,
                    args: ['nodelabel.bind']
                }] }, { type: undefined, decorators: [{
                    type: i0.Attribute,
                    args: ['nodeicon.bind']
                }] }, { type: undefined, decorators: [{
                    type: i0.Attribute,
                    args: ['nodechildren.bind']
                }] }, { type: undefined, decorators: [{
                    type: i0.Attribute,
                    args: ['nodeid.bind']
                }] }, { type: undefined, decorators: [{
                    type: i0.Inject,
                    args: ['EXPLICIT_CONTEXT']
                }, {
                    type: i0.Optional
                }] }], null); })();
    (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0__namespace.ɵsetClassDebugInfo(TreeComponent, { className: "TreeComponent", filePath: "tree.component.ts", lineNumber: 20 }); })();

    const components = [
        TreeComponent
    ];
    class TreeModule {
        static { this.ɵfac = function TreeModule_Factory(t) { return new (t || TreeModule)(); }; }
        static { this.ɵmod = /*@__PURE__*/ i0__namespace.ɵɵdefineNgModule({ type: TreeModule }); }
        static { this.ɵinj = /*@__PURE__*/ i0__namespace.ɵɵdefineInjector({ imports: [common.CommonModule,
                base.WmComponentsModule] }); }
    }
    (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0__namespace.ɵsetClassMetadata(TreeModule, [{
            type: i0.NgModule,
            args: [{
                    imports: [
                        common.CommonModule,
                        base.WmComponentsModule
                    ],
                    declarations: [...components],
                    exports: [...components]
                }]
        }], null, null); })();
    (function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0__namespace.ɵɵsetNgModuleScope(TreeModule, { declarations: [TreeComponent], imports: [common.CommonModule,
            base.WmComponentsModule], exports: [TreeComponent] }); })();

    exports.TreeComponent = TreeComponent;
    exports.TreeModule = TreeModule;

}));
