# Source: src/js/views/EditCollectionView.js

    define(['underscore',
            'jquery',
            'backbone',
            "models/Map",
            "models/CollectionModel",
            "models/Search",
            "views/DataCatalogViewWithFilters",
            "views/queryBuilder/QueryBuilderView",
            "text!templates/editCollection.html"],
    function(_, $, Backbone, Map, CollectionModel, Search, DataCatalogViewWithFilters,
              QueryBuilder, Template){

      /**
      * @class EditCollectionView
      * @classdesc A view that allows the user to edit the search filters that define their dataset collection
      * @classcategory Views
      * @extends Backbone.View
      * @constructor
      */
      var EditCollectionView = Backbone.View.extend(
        /** @lends EditCollectionView.prototype */{

        /**
        * The type of View this is
        * @type {string}
        */
        type: "EditCollection",

        /**
         * A reference to the parent editor view, if there is one
         * @type {PortalEditorView}
         */
        editorView: undefined,

        /**
        * The HTML tag name to use for this view's element
        * @type {string}
        */
        tagName: "div",

        /**
        * The HTML classes to use for this view's element
        * @type {string}
        */
        className: "edit-collection",

        /**
        * The Collection model that is being edited
        * @type {CollectionModel}
        */
        model: undefined,

        /**
        * The template for this view. An HTML file is converted to an Underscore.js template
        */
        template: _.template(Template),

        /**
        * A jQuery selector for the element that the DataCatalogViewWithFilters should be inserted into
        * @type {string}
        */
        dataCatalogViewContainer: ".data-catalog-view-container",
        /**
        * A jQuery selector for the element that the Save and Cancel buttons should be inserted into
        * @type {string}
        */
        collectionControlsContainer: ".applied-filters-container",
        /**
        * A jQuery selector for the element that the QueryBuilder should be inserted into
        * @type {string}
        */
        queryBuilderViewContainer: ".query-builder-view-container",
        /**
        * A jQuery selector for the element that contains the filter help text
        * @type {string}
        */
        helpTextContainer: "#filter-help-text",

        /**
         * An array of hex color codes used to help distinguish between different rules
         * @type {string[]}
         */
         ruleColorPalette: ["#44AA99", "#137733", "#c9a538", "#CC6677", "#882355", "#AA4499","#332288"],

        /**
         * Query fields to exclude in the metadata field selector of each Query Rule. This
         * is a list of field names that exist in the query service index (i.e. Solr), but
         * which should be hidden in the Query Builder
         * @type {string[]}
         */
        queryBuilderExcludeFields: MetacatUI.appModel.get("collectionQueryExcludeFields"),

        /**
         * Query fields to exclude in the metadata field selector for any Query Rules that are
         * in nested Query Builders (i.e. in nested Filter Groups). This is a list of field
         * names that exist in the query service index (i.e. Solr), but which should be hidden
         * in nested Query Builders
         * @type {string[]}
         */
        queryBuilderNestedExcludeFields: _.union(
          MetacatUI.appModel.get("collectionQueryExcludeFields"),
          MetacatUI.appModel.get("queryIdentifierFields")
        ),

        /**
         * Query fields that do not exist in the query service index, but which we would
         * like to show as options in the Query Builder field input.
         * @type {SpecialField[]}
         * @since 2.15.0
         */
        queryBuilderSpecialFields: MetacatUI.appModel.get("collectionQuerySpecialFields"),

        /**
        * The events this view will listen to and the associated function to call.
        * @type {Object}
        */
        events: {
        },

        /**
        * Is exexcuted when a new EditCollectionView is created
        * @param {Object} options - A literal object with options to pass to the view
        * @property {CollectionModel} options.model - The collection whose search results will be displayed and edited in this view
        */
        initialize: function(options){

          if( typeof options == "object" ){
            this.model = options.model || undefined;
          }

        },

        /**
        * Renders this view
        */
        render: function(){

          var title = "Change the data in your collection"
          if(this.model.isNew()){
            title = "Add data to your collection"
          }

          var helpText = "",
              email = MetacatUI.appModel.get("emailContact");

          if (email) {
            helpText = 'Need help building your data collection? <a href="maito:' + email + '">Get in touch.</a>'
          }

          this.$el.html(this.template({
            title: title,
            description: "Your collection can include any of the datasets that are available on the network. " +
              "Build rules based on metadata to define which datasets should be included in your collection. " +
              "Data added to the network in the future that match these rules will also be added to your collection. " +
              "Click the save button when you're happy with the results.",
            helpText: helpText
          }));

          // Remove this when the Query Builder is no longer new:
          this.$el
            .find(".edit-collection-title")
            .append($('<span class="new-icon" style="margin-left:10px; font-size:1rem; line-height: 25px;"><i class="icon icon-star icon-on-right"></i> NEW </span>'));
            // .append($('<span class="badge badge-info d1_pill d1_pill--primary" style="margin-left:10px">NEW!</span>'));

          // Make sure that we have a series ID before we render the Data Catalog
          // View With Filters. For new portals, we generate and reserve a series ID
          // and use it to add an isPartOf filter to the portal model. This takes time,
          // and influences the search results shown in the data catalog.
          if( this.model.get("seriesId") || this.model.get("latestVersion") ){
            //Render the DataCatalog
            this.renderDataCatalog();
          } else {
            //When the seriesId or latest pid version is found, render the DataCatalog
            this.listenToOnce(this.model, "change:seriesId",    this.renderDataCatalog);
            this.listenToOnce(this.model, "latestVersionFound", this.renderDataCatalog);
          }

          //this.renderCollectionControls();

        },

        /**
         * renderQueryBuilder - Render the QueryBuilder and insert it into this view
         */
        renderQueryBuilder: function(){

          // If the isPartOf filter is hidden, then don't allow users to build
          // a Query Rule using the isPartOf field. If they do, that rule will
          // be hidden the next time they open the portal in the editor. Also,
          // the filter they create will overwrite the isPartOf filter created by
          // default.
          if(MetacatUI.appModel.get("hideIsPartOfFilter") === true ? true : false){
            this.queryBuilderExcludeFields.push("isPartOf")
          }

          var queryBuilder = new QueryBuilder({
            filterGroup: this.model.get("definition"),
            ruleColorPalette: this.ruleColorPalette,
            excludeFields: this.queryBuilderExcludeFields,
            nestedExcludeFields: this.queryBuilderNestedExcludeFields,
            specialFields: this.queryBuilderSpecialFields,
          });

          // Render the Query Builder and insert it into this view
          this.$(this.queryBuilderViewContainer).html(queryBuilder.el);
          queryBuilder.render();
        },

        /**
         * Render the DataCatalogViewWithFilters
         */
        renderDataCatalog: function(){

          this.renderQueryBuilder();

          var searchModel = this.model.get("searchModel");

          searchModel.set("useGeohash", false);

          // Create a DataCatalog view
          var dataCatalogView = new DataCatalogViewWithFilters({
            searchModel: searchModel,
            searchResults: this.model.get("searchResults"),
            mapModel: this.model.get("mapModel") || new Map(),
            isSubView: true,
            mode: "map",
            filters: false,
            solrError500Message: "There may be a problem with one of the rules you created." +
              " Try undoing the last change you made.",
            solrErrorTitle: "Something went wrong searching for datasets that match your query",
            // Override the function that creates filter groups on the left of the
            // data catalog view. With the Query Builder view, they are not needed.
            // Otherwise, the defaultFilterGroups will be added to the Query Builder
            createFilterGroups: function(){ return },
            addAnnotationFilter: function(){ return },
            editorView: this.editorView
          });

          //Render the view and insert it into the page
          this.$(this.dataCatalogViewContainer).html(dataCatalogView.el);
          dataCatalogView.render();

          this.listenTo(this.model.get("searchResults"), "reset", this.toggleHelpText);

        },

        /**
        * Renders the edit collection controls - e.g. a Save and Cancel buttton
        */
        renderCollectionControls: function(){

          //Create a Save button
          var saveButton   = $(document.createElement("a"))
                            .addClass("save btn btn-primary")
                            .text("Save"),
          //Create a Cancel button
              cancelButton = $(document.createElement("a"))
                            .addClass("cancel btn")
                            .text("Cancel"),
          //Create a container for the buttons
              buttons      = $(document.createElement("div"))
                            .addClass("collection-controls")
                            .append(saveButton, cancelButton);

          //Add the buttons to the view
          this.$(this.collectionControlsContainer).append(buttons);

        },

        /**
         * Either hides or shows the help message that lets the user know
         * they can add filters when the collection is empty.
         */
        toggleHelpText: function() {

          //Get the list of filters currently applied to the collection definition
          var currentFilters = this.model.get("definitionFilters"),
              msg = "";

          // If there are no filters set at all, the entire repository catalog will be listed as
          // search results, so display a helpful message
          if ( currentFilters.length == 0 && this.model.get("searchResults").length ) {
            msg = "<h5>Your dataset collection hasn't been created yet.</h5>" +
                  "<p>The datasets listed here are totally unfiltered. To specify which datasets belong to your collection, " +
                  "add rules in the Query Builder above.</p>";
          }
          //If there is only an isPartOf filter, but no datasets have been marked as part of this collection
          else if( currentFilters.length == 1 &&
                   currentFilters.models[0].get("fields")[0] == "isPartOf" &&
                   !this.model.get("searchResults").length){

             msg = "<h5>Your dataset collection is empty.</h5> " +
                   "<p>To add datasets to your collection, " +
                   "add rules in query builder above.</p>";

            //TODO: When the ability to add datasets to collection via the "isPartOf" relationship is added to MetacatUI
            // then update this message with details on how to add datasets to the collection
          }

          //If a message string was created, display it
          if( msg ){
            //Show the message
            MetacatUI.appView.showAlert(msg, "alert-warning", this.$(this.helpTextContainer));
          }
          else{
            //Remove the message
            this.$(this.helpTextContainer).empty();
            //Remove validation messaging, too
            this.$(".notification.error[data-category='definition']").removeClass("error").empty();
          }

        }

      });

      return EditCollectionView;

    });