'use strict';

define(
    [
        'jquery',
        'underscore',
        'oro/translator',
        'backbone',
        'pim/form/common/edit-form',
        'webkuldam/template/asset/categories',
        'pim/template/product/tab/catalog-switcher',
        'pim/template/product/tab/jstree-locked-item',
        'pim/user-context',
        'routing',
        'pim/tree/associate',
        'oro/mediator'
    ],
    function (
        $,
        _,
        __,
        Backbone,
        BaseEditForm,
        formTemplate,
        switcherTemplate,
        lockedTemplate,
        UserContext,
        Routing,
        TreeAssociate,
        mediator
    ) {
        return BaseEditForm.extend({
            template: _.template(formTemplate),
            switcherTemplate: _.template(switcherTemplate),
            lockedTemplate: _.template(lockedTemplate),
            className: 'tab-pane active',
            id: 'product-categories',
            treeLinkSelector: 'tree-link-',
            treeHasItemClass: 'tree-has-item',
            events: {
                'click .nav-tabs li': 'changeTree',
                'change #hidden-tree-input': 'updateModel'
            },
            treeAssociate: null,
            cache: {},
            trees: [],
            onLoadedEvent: null,
            completeLoad: false,

            /**
             * Associates the tree code to the number of selected categories
             * Example: { master: 1, sales: 12 }
             */
            categoriesCount: {},

            /**
             * {@inheritdoc}
             */
            initialize: function (config) {
              
                this.state = new Backbone.Model();
                this.state.set('selectedCategories', []);
                if (undefined !== config) {
                    this.config = config.config;
                }

                BaseEditForm.prototype.initialize.apply(this, arguments);
            },

            /**
             * {@inheritdoc}
             */
            configure: function () {
                this.trigger('tab:register', {
                    code: (undefined === this.config.tabCode) ? this.code : this.config.tabCode,
                    isVisible: this.isVisible.bind(this),
                    label: __('pim_enrich.form.product.tab.categories.title')
                });

                this.listenTo(this.getRoot(), 'pim_enrich:form:locale_switcher:change', function (localeEvent) {
                    if ('base_product' === localeEvent.context) {
                        this.render();
                    }
                }.bind(this));

                this.listenTo(this.getRoot(), this.getRoot().postUpdateEventName, function (updateEvent) {
                    this.state.set('selectedCategories', []);
                    this.initCategoryCount();
                    this.render();
                }.bind(this));

                return BaseEditForm.prototype.configure.apply(this, arguments);
            },

            /**
             * {@inheritdoc}
             */
            render: function () {
                
                    var self = this;
                    
                        self.loadTrees().done(function (trees) {
                            self.trees = trees;
                            self.state.set('currentTree', _.first(self.trees).code);
                            
                            self.state.set('currentTreeId', _.first(self.trees).id);
                            self.$el.html(
                                self.template({
                                    product: self.getFormData(),
                                    locale: UserContext.get('catalogLocale'),
                                    state: self.state.toJSON(),
                                    trees: self.trees
                                })
                            );
        
                            self.treeAssociate = new TreeAssociate('#trees', '#hidden-tree-input', {
                                list_categories: self.config.itemCategoryListRoute,
                                children:        'webkul_dam_categorytree_children'
                            });
        
                            self.delegateEvents();
        
                            self.onLoadedEvent = self.lockCategories.bind(self);
                            mediator.on('jstree:loaded', self.onLoadedEvent);
        
                            self.initCategoryCount();
                            self.renderCategorySwitcher();
                            
                        }.bind(self));

                    return self;   
                
            },

            /**
             * {@inheritdoc}
             */
            shutdown: function () {
                mediator.off('jstree:loaded', this.onLoadedEvent);

                BaseEditForm.prototype.shutdown.apply(this, arguments);
            },

            /**
             * Locks a set of categories
             */
            lockCategories: function() {
                const lockedCategoryIds = this.getFormData().ascendant_category_ids;
                if(typeof lockedCategoryIds != 'undefined') {
                    lockedCategoryIds.forEach((categoryId) => {
                        const node = $('#node_' + categoryId);
                        node.find('> a').replaceWith(this.lockedTemplate({
                            label: node.find('> a').text().trim()
                        }));
                    });
                }
            },

            /**
             * Renders the category switcher in the main template
             */
            renderCategorySwitcher: function () {
                this.$el.find('.catalog-switcher:first').html(this.switcherTemplate({
                    state: this.state.toJSON(),
                    trees: this.trees,
                    categoriesCount: this.categoriesCount,
                    treeLinkSelector: this.treeLinkSelector,
                    currentCategory: _.result(_.findWhere(
                        this.trees,
                        {code: this.state.toJSON().currentTree}),
                        'label'
                    )
                }));
            },

            /**
             * Load category trees
             *
             * @returns {promise}
             */
            loadTrees: function () {
                
                return $.getJSON(
                    Routing.generate(this.config.itemCategoryTreeRoute, { id: this.getFormData().id, async: false})
                ).then(function (data) {
                    _.each(data.categories, function (category) {
                        this.cache[category.id] = category;
                    }.bind(this));

                    if (_.isEmpty(this.state.get('selectedCategories'))) {
                        this.state.set('selectedCategories', _.pluck(data.categories, 'id'));
                    }

                    return data.trees;
                }.bind(this));
            },

            /**
             * Displays the current tree when the user choose another one
             *
             * @param {Event} event
             */
            changeTree: function (event) {
                this.state.set('currentTree', event.currentTarget.dataset.tree);
                this.state.set('currentTreeId', event.currentTarget.dataset.treeId);
                this.treeAssociate.switchTree(event.currentTarget.dataset.treeId);
                this.renderCategorySwitcher();
            },

            /**
             * Change the current model when categories are checked/unchecked
             *
             * @param {Event} event
             */
            updateModel: function (event) {
                var selectedIds = _.filter(event.currentTarget.value.split(','), _.identity);

                this.state.set('selectedCategories', selectedIds);
                var rootTreeCode = this.state.get('currentTree');
                this.categoriesCount[rootTreeCode] =
                this.$('li[data-code=' + rootTreeCode +  '] .jstree-checked').length;
                this.renderCategorySwitcher();
                var categoryCodes = _.map(selectedIds, this.getCategoryCode.bind(this));
                
                this.getFormModel().set('categories', categoryCodes);
                
                mediator.trigger('pim_enrich:form:entity:update_state');
               
            },

            /**
             * Initialize category count with hidden values
             */
            initCategoryCount: function () {
                _.each(this.trees, function (tree) {
                    var selectedCategories = [];
                    var hiddenSelection = this.$('#hidden-tree-input').val();
                    hiddenSelection = hiddenSelection.length > 0 ? hiddenSelection.split(',') : [];
                    _.each(hiddenSelection, function (categoryId) {
                        selectedCategories.push(this.cache[categoryId]);
                    }.bind(this));

                    this.categoriesCount[tree.code] = _.where(selectedCategories, {rootId: tree.id}).length;
                }.bind(this));
            },

            /**
             * Fetch category code from cache
             *
             * @param {integer} id
             *
             * @returns {string}
             */
            getCategoryCode: function (id) {
                if (!this.cache[id]) {
                    var $categoryElement = this.$('#node_' + id);
                    var $rootElement     = $categoryElement.closest('.root-unselectable');
                    this.cache[id] = {
                        code: String($categoryElement.data('code')),
                        rootId: $rootElement.data('tree-id')
                    };
                }

                return this.cache[id].code;
            },

            /**
             * Check if this extension is visible
             *
             * @returns {boolean}
             */
            isVisible: function () {
                return true;
            }
        });
    }
);
