/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
define([
    "require",
    "hbs!tmpl/search/tree/GlossaryTreeLayoutView_tmpl",
    "utils/Utils",
    'utils/Messages',
    "utils/Globals",
    "utils/UrlLinks",
    "utils/CommonViewFunction",
    "collection/VSearchList",
    "collection/VGlossaryList",
    "jstree"
], function(require, GlossaryTreeLayoutView_tmpl, Utils, Messages, Globals, UrlLinks, CommonViewFunction, VSearchList, VGlossaryList) {
    "use strict";

    var GlossaryTreeLayoutView = Marionette.LayoutView.extend({
        template: GlossaryTreeLayoutView_tmpl,

        regions: {},
        ui: {
            refreshTree: '[data-id="refreshTree"]',
            termSearchTree: '[data-id="termSearchTree"]',
            createGlossary: '[data-id="createGlossary"]',
            showGlossaryType: '[data-id="showGlossaryType"]'
        },
        templateHelpers: function() {
            return {
                apiBaseUrl: UrlLinks.apiBaseUrl
            };
        },
        events: function() {
            var events = {},
                that = this;
            events["click " + this.ui.refreshTree] = function(e) {
                var type = $(e.currentTarget).data("type");
                e.stopPropagation();
                that.refresh({ type: type });

            };

            events["click " + this.ui.createGlossary] = function(e) {
                var that = this;
                CommonViewFunction.createEditGlossaryCategoryTerm({
                    isGlossaryView: true,
                    collection: that.glossaryCollection,
                    callback: function(rModel) {
                        that.glossaryCollection.fullCollection.add(rModel);
                    },
                    onModalClose: function() {}
                })
            };

            events["click " + this.ui.showGlossaryType] = function(e) {
                var getTreeData, displayText;
                e.stopPropagation();
                this.isTermView = !this.isTermView;
                this.glossarySwitchBtnUpdate();
            };
            return events;
        },
        bindEvents: function() {
            var that = this;
            this.listenTo(
                this.glossaryCollection.fullCollection, "reset add change",
                function(skip) {
                    if (this.ui.termSearchTree.jstree(true)) {
                        this.ui.termSearchTree.jstree(true).refresh();
                    } else {
                        this.renderGlossaryTree();
                    }
                },
                this
            );
            if (this.options.categoryEvent) {
                this.options.categoryEvent.on("Success:TermRename", function(options) {
                    that.refresh();
                })
            }

            $('body').on('click', '.termPopoverOptions li, .categoryPopoverOptions li', function(e) {
                that.$('.termPopover,.categoryPopover').popover('hide');
                that[$(this).find('a').data('fn')](e)
            });
        },
        glossarySwitchBtnUpdate: function() {
            this.ui.showGlossaryType.attr("data-original-title", (this.isTermView ? "Show Category" : "Show Term"));
            this.ui.showGlossaryType.tooltip('hide');
            this.ui.showGlossaryType.find("i").toggleClass("switch-button");
            this.ui.termSearchTree.jstree(true).refresh();
        },
        initialize: function(options) {
            this.options = options;
            _.extend(
                this,
                _.pick(
                    options,
                    "typeHeaders",
                    "searchVent",
                    "entityDefCollection",
                    "enumDefCollection",
                    "classificationDefCollection",
                    "searchTableColumns",
                    "searchTableFilters",
                    "metricCollection",
                    "query",
                    "categoryEvent"
                )
            );
            this.glossaryTermId = this.glossaryId = null;
            this.glossaryCollection = new VGlossaryList([], {
                comparator: function(item) {
                    return item.get("name");
                }
            });
            this.getViewType();
            this.bindEvents();
        },
        onRender: function() {
            this.fetchGlossary();
        },

        onBeforeDestroy: function() {
            this.options.categoryEvent.off("Success:TermRename")
        },
        getViewType: function() {
            if (this.options.value) {
                this.isTermView = this.options.value.viewType ? this.options.value.viewType == "term" ? true : false : true;
            } else {
                this.isTermView = true;
            }
        },
        manualRender: function(options) {
            var that = this;
            _.extend(this.options, options);
            if (this.options.value === undefined) {
                this.options.value = {};
            }
            if (!this.options.value.term && this.options.value.gType != 'category') {
                this.ui.termSearchTree.jstree(true).deselect_all();
                this.glossaryTermId = null;
            } else {
                if (this.options.value.term) {
                    var glossaryName = this.options.value.term.split('@')[1],
                        termName = this.options.value.term.split('@')[0],
                        dataFound = this.glossaryCollection.fullCollection.find(function(obj) {
                            return obj.get("name") === glossaryName;
                        });
                    if (dataFound) {
                        var terms = dataFound.get('terms');
                        var terModel = _.find(terms, function(model) {
                            return model.displayText === termName;
                        });
                        if (terModel) {
                            if ((this.glossaryTermId && this.glossaryTermId !== terModel.termGuid) || this.glossaryTermId === null) {
                                if (this.glossaryTermId) {
                                    this.ui.termSearchTree.jstree(true).deselect_node(this.glossaryTermId);
                                }
                                this.ui.termSearchTree.jstree(true).deselect_all();
                                this.glossaryTermId = terModel.termGuid;
                                this.fromManualRender = true;
                                this.ui.termSearchTree.jstree(true).select_node(terModel.termGuid);
                            }
                        }
                    }
                }
            }
        },
        fetchGlossary: function() {
            this.glossaryCollection.fetch({ reset: true });
        },
        renderGlossaryTree: function() {
            this.generateSearchTree({
                $el: this.ui.termSearchTree

            });
            this.createTermAction();
        },
        onNodeSelect: function(options, showCategory) {
            var name, type, selectedNodeId, that = this,
                glossaryType = options.node.original.gType;
            if (glossaryType == "category") {
                selectedNodeId = options.node.id;
                if (that.glossaryTermId != selectedNodeId) {
                    that.glossaryTermId = selectedNodeId;
                    that.onViewEdit();
                } else {
                    that.glossaryTermId = null;
                    that.showDefaultPage();
                }

            } else if (glossaryType == "term") {
                if (options) {
                    name = _.unescape(options.node.original.name);
                    selectedNodeId = options.node.id;
                }
                var termValue = null,
                    params = {
                        searchType: "basic"
                    };
                if (this.options.value) {
                    if (this.options.value.isCF) {
                        this.options.value.isCF = null;
                    }
                }
                if (that.glossaryTermId != selectedNodeId) {
                    that.glossaryTermId = selectedNodeId;
                    termValue = options ? name + '@' + options.node.original.parent.name : this.options.value.term;
                    params['term'] = termValue;
                    params['gtype'] = 'term';
                    params['viewType'] = 'term';
                    params['guid'] = selectedNodeId;

                } else {
                    that.glossaryTermId = params["term"] = null;
                    that.ui.termSearchTree.jstree(true).deselect_all(true);
                    if (!that.options.value.type && !that.options.value.tag && !that.options.value.query) {
                        that.showDefaultPage();
                        return;
                    }
                }
                that.glossaryId = null;
                var searchParam = _.extend({}, that.options.value, params);

                this.triggerSearch(searchParam);
                if (that.searchVent) {
                    that.searchVent.trigger("Success:Category");
                }
            } else {
                that.glossaryTermId = null;
                if (that.glossaryId != options.node.id) {
                    that.glossaryId = options.node.id;
                } else {
                    that.glossaryId = null;
                    that.ui.termSearchTree.jstree(true).deselect_all(true);
                }
            }
        },
        triggerSearch: function(params, url) {
            var serachUrl = url ? url : '#!/search/searchResult';
            Utils.setUrl({
                url: serachUrl,
                urlParams: params,
                mergeBrowserUrl: false,
                trigger: true,
                updateTabState: true
            });
        },
        showDefaultPage: function() {
            Utils.setUrl({
                url: '!/search',
                mergeBrowserUrl: false,
                trigger: true,
                updateTabState: true
            });
        },
        generateCategoryData: function(options) {
            var that = this,
                isSelected = false;
            return _.map(options.data, function(obj) {
                return {
                    "text": _.escape(obj.displayText),
                    "icon": "fa fa-files-o",
                    "guid": obj.categoryGuid,
                    "id": obj.categoryGuid,
                    "glossaryId": options.node.glossaryId,
                    "glossaryName": options.node.glossaryName,
                    "model": obj,
                    "type": "GlossaryCategory",
                    "gType": "category",
                    "children": true
                }
            });
        },
        getCategory: function(options) {
            var that = this;
            this.glossaryCollection.getCategory({
                "guid": options.node.guid,
                "related": true,
                "ajaxOptions": {
                    success: function(data) {
                        if (data && data.children) {
                            options.callback(that.generateCategoryData(_.extend({}, { "data": data.children }, options)));
                        } else {
                            options.callback([]);
                        }
                    },
                    cust_error: function() {
                        options.callback([]);
                    }
                }
            });
        },
        getGlossaryTree: function(options) {
            var that = this,
                collection = (options && options.collection) || this.glossaryCollection.fullCollection,
                listOfParents = [],
                type = "term";

            return this.glossaryCollection.fullCollection.map(function(model, i) {
                var obj = model.toJSON(),
                    parent = {
                        text: _.escape(obj.name),
                        name: _.escape(obj.name),
                        icon: "fa fa-folder-o",
                        guid: obj.guid,
                        id: obj.guid,
                        model: obj,
                        type: obj.typeName ? obj.typeName : "GLOSSARY",
                        gType: "glossary",
                        children: [],
                        state: { opened: true }
                    },
                    openGlossaryNodesState = function(treeDate) {
                        if (treeDate.length == 1) {
                            _.each(treeDate, function(model) {
                                model.state['opeaned'] = true;
                            })
                        }
                    },
                    generateNode = function(nodeOptions, model, isTermView, parentNode) {
                        var nodeStructure = {
                            text: _.escape(model.displayText),
                            name: _.escape(model.displayText),
                            type: nodeOptions.type,
                            gType: that.isTermView ? "term" : "category",
                            guid: nodeOptions.guid,
                            id: nodeOptions.guid,
                            parent: parentNode ? parentNode : obj,
                            glossaryName: parentNode ? parentNode.name ? parentNode.name : parentNode.displayText : obj.name,
                            glossaryId: parentNode ? parentNode.guid ? parentNode.guid : parentNode.categoryGuid : obj.guid,
                            model: model,
                            icon: "fa fa-file-o"
                        };
                        return nodeStructure;

                    };

                if (!that.isTermView && obj.categories && !that.isTermView) {
                    var isSelected = false,
                        parentGuid = obj.guid,
                        parentCategoryGuid = null,
                        getParentCategory = function() {
                            var parentCategory = _.find(parent.model.categories, function(subCategory) {
                                return subCategory.categoryGuid === parentCategoryGuid;
                            });
                            return parentCategory;
                        };
                    _.each(obj.categories, function(category) {
                        if (that.options.value) {
                            isSelected = that.options.value.guid ? that.options.value.guid == category.categoryGuid : false;
                        }
                        if (category.parentCategoryGuid) {
                            return;
                        }
                        var typeName = category.typeName || "GlossaryCategory",
                            guid = category.categoryGuid,
                            categoryObj = {
                                "text": _.escape(category.displayText),
                                "type": typeName,
                                "gType": "category",
                                "guid": guid,
                                "id": guid,
                                "parent": obj,
                                "glossaryId": obj.guid,
                                "glossaryName": obj.name,
                                "model": category,
                                "children": true,
                                "icon": "fa fa-files-o"
                            };
                        parent.children.push(categoryObj)
                    });
                }
                if (that.isTermView && obj.terms) {
                    var isSelected = false;
                    _.each(obj.terms, function(term) {
                        if (that.options.value) {
                            isSelected = that.options.value.term ? that.options.value.term.split('@')[0] == term.displayText : false;
                        }
                        var parentNodeDetails = {
                                type: term.typeName || "GlossaryTerm",
                                guid: term.termGuid
                            },
                            parentNodeProperties = {},
                            getParentNodeDetails = generateNode(parentNodeDetails, term, that.isTermView),
                            termParentNode = (_.extend(parentNodeProperties, getParentNodeDetails));
                        parent.children.push(termParentNode);
                    });
                }
                openGlossaryNodesState(parent);
                return parent;
            });
        },
        createTermAction: function() {
            var that = this;
            Utils.generatePopover({
                el: this.$el,
                contentClass: 'termPopoverOptions',
                popoverOptions: {
                    selector: '.termPopover',
                    content: function() {
                        var type = $(this).data('detail'),
                            liString = "";
                        if (type == "glossary") {
                            liString = "<li data-type=" + type + " class='listTerm'><i class='fa fa-plus'></i> <a href='javascript:void(0)' data-fn='createSubNode'>Create Term</a></li>" +
                                "<li data-type=" + type + " class='listTerm'><i class='fa fa-list-alt'></i><a href='javascript:void(0)' data-fn='onViewEdit'>View/Edit Glossary</a></li>" +
                                "<li data-type=" + type + " class='listTerm'><i class='fa fa-trash-o'></i><a href='javascript:void(0)' data-fn='deleteNode'>Delete Glossary</a></li>"
                        } else {
                            liString = "<li data-type=" + type + " class='listTerm'><i class='fa fa-list-alt'></i><a href='javascript:void(0)' data-fn='onViewEdit'>View/Edit Term</a></li>" +
                                "<li data-type=" + type + " class='listTerm'><i class='fa fa-search'></i><a href='javascript:void(0)' data-fn='searchSelectedTerm'>Search</a></li>" +
                                "<li data-type=" + type + " class='listTerm'><i class='fa fa-trash-o'></i><a href='javascript:void(0)' data-fn='deleteNode'>Delete Term</a></li>"
                        }
                        return "<ul>" + liString + "</ul>";
                    }
                }
            });
        },
        createCategoryAction: function() {
            var that = this;
            Utils.generatePopover({
                el: this.$('.categoryPopover'),
                contentClass: 'categoryPopoverOptions',
                popoverOptions: {
                    content: function() {
                        var type = $(this).data('detail'),
                            liString = "";
                        if (type == "glossary") {
                            liString = "<li data-type=" + type + " class='listTerm'><i class='fa fa-plus'></i> <a href='javascript:void(0)' data-fn='createSubNode'>Create Category</a></li>";
                        } else {
                            liString = "<li data-type=" + type + " class='listTerm'><i class='fa fa-list-alt'></i><a href='javascript:void(0)' data-fn='createSubNode'>Create Sub-Category</a></li>";
                        }
                        return "<ul>" + liString + "</ul>";
                    },
                    viewFixedPopover: true,
                }
            });
        },
        createSubNode: function(opt) {
            var that = this,
                selectednode = that.ui.termSearchTree.jstree("get_selected", true);
            if ((selectednode[0].original.type == "GLOSSARY" || selectednode[0].original.type == "GlossaryCategory") && !this.isTermView) {
                CommonViewFunction.createEditGlossaryCategoryTerm({
                    "isCategoryView": true,
                    "collection": that.glossaryCollection,
                    "callback": function() {
                        that.ui.termSearchTree.jstree(true).refresh();
                    },
                    "node": selectednode[0].original
                })
            } else {
                CommonViewFunction.createEditGlossaryCategoryTerm({
                    "isTermView": true,
                    "callback": function() {
                        that.fetchGlossary();
                        that.options.categoryEvent.trigger("Success:Term", true);
                    },
                    "collection": that.glossaryCollection,
                    "node": selectednode[0].original
                })
            }
        },
        searchSelectedTerm: function() {
            var params = {
                searchType: "basic",
                dslChecked: false,
                term: this.options.value.term
            };
            this.triggerSearch(params);
        },
        deleteNode: function(opt) {
            var that = this,
                messageType = "",
                selectednode = this.ui.termSearchTree.jstree("get_selected", true),
                type = selectednode[0].original.type,
                guid = selectednode[0].original.guid,
                gId = selectednode[0].original.parent && selectednode[0].original.parent.guid,
                options = {
                    success: function(rModel, response) {
                        var searchParam = null;
                        if (!gId) {
                            gId = guid;
                        }
                        var glossary = that.glossaryCollection.fullCollection.get(gId);
                        if (type == "GlossaryTerm") {
                            glossary.set('terms', _.reject(glossary.get('terms'), function(obj) {
                                return obj.termGuid == guid;
                            }), { silent: true });
                        }

                        Utils.notifySuccess({
                            content: messageType + Messages.getAbbreviationMsg(false, 'deleteSuccessMessage')
                        });
                        that.ui.termSearchTree.jstree(true).refresh();
                        var params = {
                            searchType: "basic",
                            term: null
                        };
                        that.glossaryTermId = null;
                        if (that.options.value.gType == "category") {
                            that.showDefaultPage();
                        } else {
                            searchParam = _.extend({}, that.options.value, params);
                            that.triggerSearch(searchParam);
                        }
                    }
                },
                notifyObj = {
                    modal: true,
                    ok: function(argument) {
                        if (type == "Glossary" || type == "GLOSSARY") {
                            that.glossaryCollection.fullCollection.get(guid).destroy(options, { silent: true, reset: false });

                        } else if (type == "GlossaryCategory") {
                            new that.glossaryCollection.model().deleteCategory(guid, options);

                        } else if (type == "GlossaryTerm") {
                            new that.glossaryCollection.model().deleteTerm(guid, options);

                        }

                    },
                    cancel: function(argument) {}
                };
            if (type == "Glossary" || type == "GLOSSARY") {
                messageType = "Glossary";
            } else if (type == "GlossaryCategory") {
                messageType = "Category"
            } else if (type == "GlossaryTerm") {
                messageType = "Term";
            }
            notifyObj['text'] = "Are you sure you want to delete the " + messageType;;
            Utils.notifyConfirm(notifyObj);
        },
        onViewEdit: function() {
            var that = this,
                selectednode = this.ui.termSearchTree.jstree("get_selected", true),
                type = selectednode[0].original.type,
                guid = selectednode[0].original.guid,
                gId = selectednode[0].original.parent && selectednode[0].original.parent.guid,
                isGlossaryView = (type == 'GlossaryTerm' || type == 'GlossaryCategory') ? false : true,
                model = this.glossaryCollection.fullCollection.get(guid),
                termModel = this.glossaryCollection.fullCollection.get(gId);;
            if (isGlossaryView) {
                CommonViewFunction.createEditGlossaryCategoryTerm({
                    "model": model,
                    "isGlossaryView": true,
                    "collection": this.glossaryCollection,
                    "callback": function(sModel) {
                        var data = sModel.toJSON();
                        model.set(data, { silent: true }); // update glossaryCollection
                        that.ui.termSearchTree.jstree(true).refresh();
                    }
                });
            } else {
                var glossaryId = selectednode[0].original.glossaryId,
                    getSelectedParent = null,
                    params = null;
                if (selectednode[0].parents.length > 2) {
                    getSelectedParent = selectednode[0].parents[selectednode[0].parents.length - 3];
                } else {
                    getSelectedParent = selectednode[0].id;
                }

                params = {
                    gId: glossaryId,
                    guid: getSelectedParent,
                    gType: that.isTermView ? 'term' : 'category',
                    viewType: that.isTermView ? 'term' : 'category'
                }
                var serachUrl = '#!/glossary/' + guid;
                this.triggerSearch(params, serachUrl);
                if (!this.isTermView && this.options.categoryEvent) {
                    that.options.categoryEvent.trigger("Success:Category", true);
                }
            }
        },
        generateSearchTree: function(options) {
            var $el = options && options.$el,
                data = options && options.data,
                type = options && options.type,
                that = this,
                createAction = function(options) {
                    that.isTermView ? that.createTermAction() : that.createCategoryAction();
                },
                getEntityTreeConfig = function(opt) {
                    return {
                        plugins: ["search", "core", "sort", "conditionalselect", "changed", "wholerow", "node_customize"],

                        state: { opened: true },
                        search: {
                            show_only_matches: true,
                            case_sensitive: false
                        },
                        node_customize: {
                            default: function(el, node) {
                                var aTerm = $(el).find(">a.jstree-anchor");
                                aTerm.append("<span class='tree-tooltip'>" + _.escape(aTerm.text()) + "</span>");
                                var popoverClass = that.isTermView ? "fa fa-ellipsis-h termPopover " : "fa fa-ellipsis-h categoryPopover";
                                $(el).append('<div class="tools" data-type=' + node.original.gType + '><i class="' + popoverClass + '"rel="popover" data-detail=' + node.original.gType + '></i></div>');
                            }
                        },
                        core: {
                            data: function(node, cb) {
                                if (node.id === "#") {
                                    cb(that.getGlossaryTree());
                                } else {
                                    that.getCategory({ "node": node.original, "callback": cb });
                                }
                            },
                            multiple: false
                        }
                    };
                };

            $el.jstree(
                    getEntityTreeConfig({
                        type: ""
                    })
                ).on("load_node.jstree", function(e, data) {}).on("open_node.jstree", function(e, data) {}).on("select_node.jstree", function(e, data) {
                    if (that.fromManualRender !== true) {
                        that.onNodeSelect(data);
                    } else {
                        that.fromManualRender = false;
                    }
                    createAction(_.extend({}, options, data));
                })
                .on("open_node.jstree", function(e, data) {
                    createAction(_.extend({}, options, data));
                })
                .on("search.jstree", function(nodes, str, res) {
                    if (str.nodes.length === 0) {
                        $el.jstree(true).hide_all();
                        $el.parents(".panel").addClass("hide");
                    } else {
                        $el.parents(".panel").removeClass("hide");
                    }
                }).on('loaded.jstree', function() {
                    if (that.options.value) {
                        if (that.options.value.term) {
                            that.selectDefaultNode();
                        }
                        if (!that.isTermView) {
                            that.selectDefaultNode();
                            that.options.categoryEvent.trigger("Success:Category", true);
                        }
                    }

                }).on("hover_node.jstree", function(nodes, str, res) {
                    var aTerm = that.$("#" + str.node.a_attr.id),
                        termOffset = aTerm.find(">.jstree-icon").offset();
                    that.$(".tree-tooltip").removeClass("show");
                    if (termOffset.top && termOffset.left) {
                        aTerm.find(">span.tree-tooltip").css({
                            top: "calc(" + termOffset.top + "px - 45px)",
                            left: "24px"
                        }).addClass("show");
                    }
                }).on("dehover_node.jstree", function(nodes, str, res) {
                    that.$(".tree-tooltip").removeClass("show");
                });
        },
        selectDefaultNode: function() {
            this.ui.termSearchTree.jstree(true).select_node(this.options.value.guid);
        },
        refresh: function(options) {
            this.glossaryTermId = null;
            this.fetchGlossary();
        }
    });
    return GlossaryTreeLayoutView;
});