<commit_before>/*
 * Copyright 2016 Hewlett-Packard Development Company, L.P.
 * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
 */
define([
    'backbone',
    'jquery',
    'underscore',
    'find/app/page/search/abstract-section-view',
    'find/app/page/search/filters/date/dates-filter-view',
    'find/app/page/search/filters/parametric/parametric-view',
    'find/app/page/search/filters/parametric/numeric-parametric-field-view',
    'find/app/util/text-input',
    'find/app/util/collapsible',
    'find/app/util/filtering-collection',
    'parametric-refinement/prettify-field-name',
    'parametric-refinement/display-collection',
    'find/app/configuration',
    'i18n!find/nls/bundle',
    'i18n!find/nls/indexes',
    'find/app/util/merge-collection'
], function(Backbone, $, _, AbstractSectionView, DateView, ParametricView, NumericParametricFieldView,
            TextInput, Collapsible, FilteringCollection, prettifyFieldName, ParametricDisplayCollection, configuration, i18n, i18nIndexes, MergeCollection) {
    'use strict';

    var datesTitle = i18n['search.dates'];

    var createFilteringCollection = function (baseCollection, filterModel) {
        return new FilteringCollection([], {
            collection: baseCollection,
            filterModel: filterModel,
            predicate: filterPredicate,
            resetOnFilter: false
        });
    };

    function filterPredicate(model, filterModel) {
        var searchText = filterModel && filterModel.get('text');
        return searchText ? searchMatches(prettifyFieldName(model.id), filterModel.get('text')) : true;
    }

    function searchMatches(text, search) {
        return text.toLowerCase().indexOf(search.toLowerCase()) > -1;
    }

    return AbstractSectionView.extend({
        initialize: function(options) {
            AbstractSectionView.prototype.initialize.apply(this, arguments);

            const IndexesView = options.IndexesView;
            this.collapsed = {};

            var views = [{
                shown: configuration().enableMetaFilter,
                initialize: function() {
                    this.filterModel = new Backbone.Model();

                    this.filterInput = new TextInput({
                        model: this.filterModel,
                        modelAttribute: 'text',
                        templateOptions: {
                            placeholder: i18n['search.filters.filter']
                        }
                    });

                    this.$emptyMessage = $('<p class="hide">' + i18n['search.filters.empty'] + '</p>');

                    //noinspection JSUnresolvedFunction
                    this.listenTo(this.filterModel, 'change', function () {
                        this.updateDatesVisibility();
                        this.updateParametricVisibility();
                        this.updateEmptyMessage();
                    });
                }.bind(this),
                get$els: function() {
                    return [this.filterInput.$el, this.$emptyMessage];
                }.bind(this),
                render: function() {
                    this.filterInput.render();
                }.bind(this),
                postRender: function() {
                    this.updateParametricVisibility();
                    this.updateDatesVisibility();
                    this.updateIndexesVisibility();
                    this.updateEmptyMessage();
                }.bind(this),
                remove: function() {
                    this.filterInput.remove();
                }.bind(this)
            }, {
                shown: true,
                initialize: function() {
                    this.indexesEmpty = false;
                    this.collapsed.indexes = false;

                    //noinspection JSUnresolvedFunction
                    var indexesView = new IndexesView({
                        delayedSelection: options.delayedIndexesSelection,
                        filterModel: this.filterModel,
                        indexesCollection: options.indexesCollection,
                        queryModel: options.queryModel,
                        selectedDatabasesCollection: options.queryState.selectedIndexes,
                        visibleIndexesCallback: _.bind(function (indexes) {
                            this.indexesEmpty = indexes.length === 0;
                            this.updateIndexesVisibility();
                            this.updateEmptyMessage();
                        }, this)
                    });

                    this.indexesViewWrapper = new Collapsible({
                        view: indexesView,
                        collapsed: this.collapsed.indexes,
                        title: i18nIndexes['search.indexes']
                    });

                    // only track user triggered changes, not automatic ones
                    //noinspection JSUnresolvedFunction
                    this.listenTo(this.indexesViewWrapper, 'toggle', function (newState) {
                        this.collapsed.indexes = newState;
                    });
                }.bind(this),
                get$els: function() {
                    return [this.indexesViewWrapper.$el];
                }.bind(this),
                render: function() {
                    this.indexesViewWrapper.render();
                }.bind(this),
                postRender: $.noop,
                remove: function() {
                    this.indexesViewWrapper.remove();
                }.bind(this)
            }, {
                shown: true,
                initialize: function() {
                    this.collapsed.dates = false;

                    var dateView = new DateView({
                        datesFilterModel: options.queryState.datesFilterModel,
                        savedSearchModel: options.savedSearchModel
                    });

                    this.dateViewWrapper = new Collapsible({
                        view: dateView,
                        collapsed: this.collapsed.dates,
                        title: datesTitle
                    });

                    //noinspection JSUnresolvedFunction
                    this.listenTo(this.dateViewWrapper, 'toggle', function (newState) {
                        this.collapsed.dates = newState;
                    });
                }.bind(this),
                get$els: function() {
                    return [this.dateViewWrapper.$el];
                }.bind(this),
                render: function() {
                    this.dateViewWrapper.render();
                }.bind(this),
                postRender: $.noop,
                remove: function() {
                    this.dateViewWrapper.remove();
                }.bind(this)
            }, {
                shown: true,
                initialize: function () {
                    this.filteredNumericParametricFieldsCollection = createFilteringCollection(options.numericParametricFieldsCollection, this.filterModel);
                    this.filteredDateParametricFieldsCollection = createFilteringCollection(options.dateParametricFieldsCollection, this.filterModel);
                    this.parametricDisplayCollection = new ParametricDisplayCollection([], {
                        parametricCollection: options.parametricCollection,
                        restrictedParametricCollection: options.restrictedParametricCollection,
                        selectedParametricValues: options.queryState.selectedParametricValues,
                        filterModel: this.filterModel
                    });
                    this.mergedParametricCollection = new MergeCollection([], {
                        comparator: function(model) {
                            return model.get('displayName');
                        },
                        collections: [this.filteredNumericParametricFieldsCollection, this.filteredDateParametricFieldsCollection, this.parametricDisplayCollection],
                        typeAttribute: 'dataType'
                    });

                    if(this.filterModel) {
                        //noinspection JSUnresolvedFunction
                        this.listenTo(this.mergedParametricCollection, 'update reset', function () {
                            this.updateParametricVisibility();
                            this.updateEmptyMessage();
                        });
                    }

                    this.parametricView = new ParametricView({
                        filterModel: this.filterModel,
                        queryModel: options.queryModel,
                        queryState: options.queryState,
                        timeBarModel: options.timeBarModel,
                        collection: this.mergedParametricCollection,
                        inputTemplate: NumericParametricFieldView.dateInputTemplate,
                        formatting: NumericParametricFieldView.dateFormatting,
                        indexesCollection: options.indexesCollection,<commit_msg>[FIND-216] Add a comparator method to the merge collection<commit_after>/*
 * Copyright 2016 <NAME> Company, L.P.
 * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
 */
define([
    'backbone',
    'jquery',
    'underscore',
    'find/app/page/search/abstract-section-view',
    'find/app/page/search/filters/date/dates-filter-view',
    'find/app/page/search/filters/parametric/parametric-view',
    'find/app/page/search/filters/parametric/numeric-parametric-field-view',
    'find/app/util/text-input',
    'find/app/util/collapsible',
    'find/app/util/filtering-collection',
    'parametric-refinement/prettify-field-name',
    'parametric-refinement/display-collection',
    'find/app/configuration',
    'i18n!find/nls/bundle',
    'i18n!find/nls/indexes',
    'find/app/util/merge-collection'
], function(Backbone, $, _, AbstractSectionView, DateView, ParametricView, NumericParametricFieldView,
            TextInput, Collapsible, FilteringCollection, prettifyFieldName, ParametricDisplayCollection, configuration, i18n, i18nIndexes, MergeCollection) {
    'use strict';

    var datesTitle = i18n['search.dates'];

    var createFilteringCollection = function (baseCollection, filterModel) {
        return new FilteringCollection([], {
            collection: baseCollection,
            filterModel: filterModel,
            predicate: filterPredicate,
            resetOnFilter: false
        });
    };

    function filterPredicate(model, filterModel) {
        var searchText = filterModel && filterModel.get('text');
        return searchText ? searchMatches(prettifyFieldName(model.id), filterModel.get('text')) : true;
    }

    function searchMatches(text, search) {
        return text.toLowerCase().indexOf(search.toLowerCase()) > -1;
    }

    return AbstractSectionView.extend({
        initialize: function(options) {
            AbstractSectionView.prototype.initialize.apply(this, arguments);

            const IndexesView = options.IndexesView;
            this.collapsed = {};

            var views = [{
                shown: configuration().enableMetaFilter,
                initialize: function() {
                    this.filterModel = new Backbone.Model();

                    this.filterInput = new TextInput({
                        model: this.filterModel,
                        modelAttribute: 'text',
                        templateOptions: {
                            placeholder: i18n['search.filters.filter']
                        }
                    });

                    this.$emptyMessage = $('<p class="hide">' + i18n['search.filters.empty'] + '</p>');

                    //noinspection JSUnresolvedFunction
                    this.listenTo(this.filterModel, 'change', function () {
                        this.updateDatesVisibility();
                        this.updateParametricVisibility();
                        this.updateEmptyMessage();
                    });
                }.bind(this),
                get$els: function() {
                    return [this.filterInput.$el, this.$emptyMessage];
                }.bind(this),
                render: function() {
                    this.filterInput.render();
                }.bind(this),
                postRender: function() {
                    this.updateParametricVisibility();
                    this.updateDatesVisibility();
                    this.updateIndexesVisibility();
                    this.updateEmptyMessage();
                }.bind(this),
                remove: function() {
                    this.filterInput.remove();
                }.bind(this)
            }, {
                shown: true,
                initialize: function() {
                    this.indexesEmpty = false;
                    this.collapsed.indexes = false;

                    //noinspection JSUnresolvedFunction
                    var indexesView = new IndexesView({
                        delayedSelection: options.delayedIndexesSelection,
                        filterModel: this.filterModel,
                        indexesCollection: options.indexesCollection,
                        queryModel: options.queryModel,
                        selectedDatabasesCollection: options.queryState.selectedIndexes,
                        visibleIndexesCallback: _.bind(function (indexes) {
                            this.indexesEmpty = indexes.length === 0;
                            this.updateIndexesVisibility();
                            this.updateEmptyMessage();
                        }, this)
                    });

                    this.indexesViewWrapper = new Collapsible({
                        view: indexesView,
                        collapsed: this.collapsed.indexes,
                        title: i18nIndexes['search.indexes']
                    });

                    // only track user triggered changes, not automatic ones
                    //noinspection JSUnresolvedFunction
                    this.listenTo(this.indexesViewWrapper, 'toggle', function (newState) {
                        this.collapsed.indexes = newState;
                    });
                }.bind(this),
                get$els: function() {
                    return [this.indexesViewWrapper.$el];
                }.bind(this),
                render: function() {
                    this.indexesViewWrapper.render();
                }.bind(this),
                postRender: $.noop,
                remove: function() {
                    this.indexesViewWrapper.remove();
                }.bind(this)
            }, {
                shown: true,
                initialize: function() {
                    this.collapsed.dates = false;

                    var dateView = new DateView({
                        datesFilterModel: options.queryState.datesFilterModel,
                        savedSearchModel: options.savedSearchModel
                    });

                    this.dateViewWrapper = new Collapsible({
                        view: dateView,
                        collapsed: this.collapsed.dates,
                        title: datesTitle
                    });

                    //noinspection JSUnresolvedFunction
                    this.listenTo(this.dateViewWrapper, 'toggle', function (newState) {
                        this.collapsed.dates = newState;
                    });
                }.bind(this),
                get$els: function() {
                    return [this.dateViewWrapper.$el];
                }.bind(this),
                render: function() {
                    this.dateViewWrapper.render();
                }.bind(this),
                postRender: $.noop,
                remove: function() {
                    this.dateViewWrapper.remove();
                }.bind(this)
            }, {
                shown: true,
                initialize: function () {
                    this.filteredNumericParametricFieldsCollection = createFilteringCollection(options.numericParametricFieldsCollection, this.filterModel);
                    this.filteredDateParametricFieldsCollection = createFilteringCollection(options.dateParametricFieldsCollection, this.filterModel);
                    this.parametricDisplayCollection = new ParametricDisplayCollection([], {
                        parametricCollection: options.parametricCollection,
                        restrictedParametricCollection: options.restrictedParametricCollection,
                        selectedParametricValues: options.queryState.selectedParametricValues,
                        filterModel: this.filterModel
                    });
                    this.mergedParametricCollection = new MergeCollection([], {
                        comparator: function (aModel, bModel) {
                            var configArray = [];
                            var aIndex = configArray.indexOf(aModel.id);
                            var bIndex = configArray.indexOf(bModel.id);

                            // Sort initially to match the parametric order as defined in the config
                            if (aIndex > bIndex) {
                                if (bIndex < 0) {
                                    return -1;
                                }
                                return 1;
                            }
                            if (aIndex < bIndex) {
                                if (aIndex < 0) {
                                    return 1;
                                }
                                return -1;
                            }

                            // And any fields not given a predefined order then sort lexicographically
                            var aDisplayName = aModel.get('displayName').toLowerCase();
                            var bDisplayName = bModel.get('displayName').toLowerCase();
                            return aDisplayName < bDisplayName ? -1 : aDisplayName > bDisplayName ? 1 : 0;
                        },
                        collections: [this.filteredNumericParametricFieldsCollection, this.filteredDateParametricFieldsCollection, this.parametricDisplayCollection],
                        typeAttribute: 'dataType'
                    });

                    if(this.filterModel) {
                        //noinspection JSUnresolvedFunction
                        this.listenTo(this.mergedParametricCollection, 'update reset', function () {
                            this.updateParametricVisibility();
                            this.updateEmptyMessage();
                        });
                    }

                    this.parametricView = new ParametricView({
                        filterModel: this.filterModel,
                        queryModel: options.queryModel,
                        queryState: options.queryState,
                        timeBarModel: options.timeBarModel,
                        collection: this.mergedParametricCollection,
                        inputTemplate: NumericParametricFieldView.dateInputTemplate,
                        formatting: NumericParametricFieldView.dateFormatting,
                        indexesCollection: options.indexesCollection,
{'fraction_non_alphanumeric': 0.08883956225480075, 'fraction_numerical': 0.0028907701837703904, 'mean_word_length': 1.4086783538480667, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7662233', 'n_tokens_mistral': 4477, 'n_tokens_neox': 4094, 'n_words': 757}