# Source: src/js/views/portals/PortalListView.js

    define(["jquery",
        "underscore",
        "backbone",
        "collections/Filters",
        "collections/SolrResults",
        "views/PagerView",
        "text!templates/portals/portalList.html"],
        function($, _, Backbone, Filters, SearchResults, PagerView, Template){

          /**
          * @class PortalListView
          * @classdesc A view that shows a list of Portals
          * @classcategory Views/Portals
          * @extends Backbone.View
          * @screenshot views/portals/PortalListView.png
          * @constructor
          */
          return Backbone.View.extend(
            /** @lends PortalListView.prototype */{

            /**
            * An array of Filter models  or Filter model JSON to use in the query.
            * If not provided, a default query will be used.
            * @type {Filter[]}
            */
            filters: null,

            /**
            * A SolrResults collection that contains the results of the search for the portals
            * @type {SolrResults}
            */
            searchResults: new SearchResults(),

            /**
            * A comma-separated list of Solr index fields to retrieve when searching for portals
            * @type {string}
            * @default "id,seriesId,title,formatId,label,logo"
            */
            searchFields: "id,seriesId,title,formatId,label,logo,datasource,writePermission,changePermission,rightsHolder,abstract",

            /**
            * The number of portals to dispaly per page
            * @default 10
            * @type {number}
            */
            numPortalsPerPage: 10,

            /**
            * The number of portals to retrieve and render in this view
            * @default 100
            * @type {number}
            */
            numPortals: 100,

            /**
            * An array of additional SolrResult models for portals that will be displayed
            * in this view in addition to the SolrResults found as a result of the search.
            * These could be portals that wouldn't otherwise be found by a search but should be displayed anyway.
            * @type {SolrResult[]}
            */
            additionalPortalsToDisplay: [],

            /**
            * The message to display when there are no portals in this list
            * @type {string}
            */
            noResultsMessage: "You haven't created or have access to any " + MetacatUI.appModel.get("portalTermPlural") + " yet.",

            /**
            * A jQuery selector for the element that the list should be inserted into
            * @type {string}
            */
            listContainer: ".portal-list-container",
            /**
            * A jQuery selector for the element that the Create Portal should be inserted into
            * @type {string}
            */
            createBtnContainer: ".create-btn-container",

            /**
            * References to templates for this view. HTML files are converted to Underscore.js templates
            */
            template: _.template(Template),

            /**
            * Initializes a new view
            */
            initialize: function(){
              //Create a new SearchResults collection
              this.searchResults = new SearchResults();
            },

            /**
            * Renders the list of portals
            */
            render: function(){

              try{

                //If the "my portals" feature is disabled, exit now
                if(MetacatUI.appModel.get("showMyPortals") === false){
                  return;
                }

                //Insert the template
                this.$el.html( this.template() );

                //If there are no given filters, create default ones
                if( !this.filters ){
                  //Create search filters for finding the portals
                  var filters = new Filters();

                  //Filter datasets that the user has ownership of
                  filters.addWritePermissionFilter();

                  this.filters = filters;
                }
                //If the filters set on this view is an array of JSON, add it to a Filters collection
                else if( this.filters.length && !Filters.prototype.isPrototypeOf(this.filters) ){
                  //Create search filters for finding the portals
                  var filters = new Filters();

                  filters.add( this.filters );

                  this.filters = filters;
                }
                //If there is an empty array, create a new Filters collection
                else if( !this.filters.length ){
                  this.filters = new Filters();
                }

                //Get the search results and render them
                this.getSearchResults();

                //Display any additional portals in the list that have been passed to
                // the view directly.
                _.each(this.additionalPortalsToDisplay, function(searchResult){
                  //Get the list container element
                  var listContainer = this.$(this.listContainer);

                  //Remove any 'loading' elements before adding items to the list
                  listContainer.find(".loading").remove();

                  //Create a list item element and add the search result element
                  // to the list container
                  listContainer.append(this.createListItem(searchResult));
                }, this);

                if( this.additionalPortalsToDisplay.length ){
                  //While the search is being sent for the other portals in this list,
                  // show a loading sign underneath the additional portals we just displayed.
                  var loadingListItem = this.createListItem();
                  loadingListItem.html("<td class='loading subtle' colspan='4'>Loading more " +
                                         MetacatUI.appModel.get("portalTermPlural") + "...</td>");
                  this.$(this.listContainer).append(loadingListItem);
                }

              }
              catch(e){
                console.error(e);
              }

            },

            /**
            * Queries for the portal objects using the SearchResults collection
            */
            getSearchResults: function(){

              try{

                //Filter by the portal format ID
                this.filters.add({
                  fields: ["formatId"],
                  values: ["dataone.org/portals"],
                  matchSubstring: true,
                  exclude: false
                });

                //Filter datasets by their ownership
                this.filters.add({
                  fields: ["obsoletedBy"],
                  values: ["*"],
                  matchSubstring: false,
                  exclude: true
                });

                //Get 100 rows
                this.searchResults.rows = this.numPortals;

                //The fields to return
                this.searchResults.fields = this.searchFields;

                //Set the query service URL
                try{
                  if( MetacatUI.appModel.get("defaultAlternateRepositoryId") ){
                    var mnToQuery = _.findWhere( MetacatUI.appModel.get("alternateRepositories"), { identifier: MetacatUI.appModel.get("defaultAlternateRepositoryId") } );
                    if( mnToQuery ){
                      this.searchResults.queryServiceUrl = mnToQuery.queryServiceUrl;
                    }
                  }
                }
                catch(e){
                  console.error("Could not get active alt repo. ", e);
                }

                //Set the query on the SearchResults
                this.searchResults.setQuery( this.filters.getQuery() );

                //Listen to the search results collection and render the results when the search is complete
                this.listenToOnce( this.searchResults, "reset", this.renderList );
                //Listen to the search results collection for errors
                this.listenToOnce( this.searchResults, "error", this.showError );

                //Get the first page of results
                this.searchResults.toPage(0);
              }
              catch(e){
                this.showError();
                console.error("Failed to fetch the SearchResults for the PortalsList: ", e);
              }
            },

            /**
            * Renders each search result from the SolrResults collection
            */
            renderList: function(){

              try{

                //Get the list container element
                var listContainer = this.$(this.listContainer);

                //If no search results were found, display a message
                if( (!this.searchResults || !this.searchResults.length) && !this.additionalPortalsToDisplay.length){
                  var row = this.createListItem();
                  row.html("<div class='no-results'>" + this.noResultsMessage + "</div>");
                  listContainer.html(row);

                  //Add a "Create" button to create a new portal
                  this.renderCreateButton();

                  return;
                }

                //Remove any 'loading' elements before adding items to the list
                listContainer.find(".loading").remove();

                //Iterate over each search result and render it
                this.searchResults.each(function(searchResult){

                  //Create a list item element and add the search result element
                  // to the list container
                  listContainer.append(this.createListItem(searchResult));

                }, this);

                //Add a "Create" button to create a new portal
                this.renderCreateButton();

                // Create a pager for this list if there are many portals
                if( this.$(".portals-list-entry").length > this.numPortalsPerPage ){
                  var pager = new PagerView({
                      pages: this.$(".portals-list-entry"),
                      itemsPerPage: this.numPortalsPerPage
                  });

                  this.$el.append(pager.render().el);
                }

              }
              catch(e){
                console.error(e);

                this.showError();

              }

            },

            /**
            * Creates a table row for the given portal SolrResult model
            * @param {SolrResult} - The SolrResult model that represent the portal
            * @return {Element}
            */
            createListItem: function(searchResult){

              try{
                var listItem = $(document.createElement("div")).addClass("portals-list-entry");

                if( searchResult && typeof searchResult.get == "function" ){

                  //Don't render a list item for a portal that is already there
                  if( this.$("tr[data-seriesId='" + searchResult.get("seriesId") + "']").length ){
                    return listItem;
                  }

                  //Add an id to the list element
                  listItem.attr("data-seriesId", searchResult.get("seriesId"));

                  //Create a logo image
                  var logoImg = "";
                  var logoDiv = "";

                  // Add link to the portal to the list item
                  var link = $(document.createElement("a"))
                              .attr("href", MetacatUI.root + "/" + MetacatUI.appModel.get("portalTermPlural")
                              + "/" + encodeURIComponent((searchResult.get("label") || searchResult.get("seriesId") || searchResult.get("id"))) );

                  if( searchResult.get("logo")) {
                    if( !searchResult.get("logo").startsWith("http") ){

                      var urlBase = "";

                      //If there are alt repos configured, use the datasource obbject service URL
                      if( MetacatUI.appModel.get("alternateRepositories").length && searchResult.get("datasource") ){
                        var sourceMN = _.findWhere(MetacatUI.appModel.get("alternateRepositories"), { identifier: searchResult.get("datasource") });
                        if( sourceMN ){
                          urlBase = sourceMN.objectServiceUrl;
                        }
                      }

                      if( !urlBase ){
                        // use the resolve service if there is no object service url
                        // (e.g. in DataONE theme)
                        urlBase = MetacatUI.appModel.get("objectServiceUrl") ||
                                  MetacatUI.appModel.get("resolveServiceUrl");
                      }

                      searchResult.set("logo", urlBase + searchResult.get("logo") );
                    }

                    var logoImg = $(document.createElement("img"))
                              .attr("src", searchResult.get("logo"))
                              .attr("alt", searchResult.get("title") + " logo");
                    var logoLink = link.clone().append(logoImg);

                    logoDiv = $(document.createElement("div"))
                              .addClass("portal-logo")
                              .append(logoLink);

                  } else {
                    // Create an empty <div>, as no portal image is available.
                    logoDiv = $(document.createElement("div"))
                              .addClass("portal-logo");
                  }

                  var portalTitle = $(document.createElement("h5"))
                                    .addClass("portal-title")
                                    .text(searchResult.get("title"));
                  var titleLink = link.clone().append(portalTitle);

                  var descriptionText = searchResult.get("abstract") || "",
                      maxLength = window.innerWidth < 800 ? 150 : 300;
                  if( descriptionText.length > maxLength ){
                    descriptionText = descriptionText.substr(0, maxLength);
                    descriptionText = descriptionText.substr(0, Math.min(descriptionText.length, descriptionText.lastIndexOf(" ")));
                    descriptionText += "...";
                  }
                  var description = $(document.createElement("div"))
                                    .addClass("portal-description")
                                    .append( $(document.createElement("p"))
                                              .text(descriptionText) );

                  var portalInfo = $(document.createElement("div"))
                                     .addClass("portal-info")
                                     .append(titleLink, description);

                  var editDiv = $(document.createElement("div"))
                                .addClass("portal-edit-link")
                                .addClass("controls");

                  //Add all the elements to the row
                  listItem.append(logoDiv, portalInfo, editDiv);

                  //Construct an array of ownership subjects
                  var wPermission = searchResult.get("writePermission"),
                      cPermission = searchResult.get("changePermission"),
                      rightsHolder = searchResult.get("rightsHolder");
                  var owners = [];

                  [wPermission, cPermission, rightsHolder].forEach( subjects => {
                    if( typeof subjects == "string" ){
                      owners.push(subjects);
                    }
                    else if( Array.isArray(subjects) ){
                      owners = owners.concat(subjects);
                    }
                  });

                  //Render an Edit button
                  if ( MetacatUI.appUserModel.hasIdentityOverlap(owners) ){
                      //Create an Edit buttton
                      var editButton = $(document.createElement("a")).attr("href",
                                   MetacatUI.root + "/edit/"+ MetacatUI.appModel.get("portalTermPlural") +"/" + encodeURIComponent((searchResult.get("label") || searchResult.get("seriesId") || searchResult.get("id"))) )
                                   .text("Edit")
                                   .addClass("btn edit");
                      editDiv.append(editButton);
                  }

                }

                //Return the list item
                return listItem;
              }
              catch(e){
                console.error(e);
                return "";
              }
            },

            /**
            * Renders a "Create" button for the user to create a new portal
            */
            renderCreateButton: function(){
              try{

                //If the authorization hasn't been checked yet
                if( MetacatUI.appUserModel.get("isAuthorizedCreatePortal") !== true &&
                    MetacatUI.appUserModel.get("isAuthorizedCreatePortal") !== false ){
                  //Check is this user is authorized to create a new portal
                  this.listenToOnce( MetacatUI.appUserModel, "change:isAuthorizedCreatePortal", this.renderCreateButton);
                  MetacatUI.appUserModel.isAuthorizedCreatePortal();
                }
                else{

                  //Create a New portal buttton
                  var createButton = $(document.createElement("a"))
                                     .addClass("btn btn-primary")
                                     .append( $(document.createElement("i")).addClass("icon icon-plus icon-on-left"),
                                       "New " + MetacatUI.appModel.get('portalTermSingular'));

                  var isNotAuthorizedNoBookkeeper   = !MetacatUI.appModel.get("enableBookkeeperServices") &&
                                                       MetacatUI.appUserModel.get("isAuthorizedCreatePortal") === false,
                      reachedLimitWithBookkeeper    = MetacatUI.appModel.get("enableBookkeeperServices") &&
                                                      MetacatUI.appUserModel.get("isAuthorizedCreatePortal") === false,
                      reachedLimitWithoutBookkeeper = !MetacatUI.appModel.get("enableBookkeeperServices") &&
                                                       MetacatUI.appModel.get("portalLimit") <= this.searchResults.length;

                  //If creating portals is disabled in the entire app, or is only limited to certain groups,
                  // then don't show the Create button.
                  if( isNotAuthorizedNoBookkeeper ){
                    return;
                  }
                  //If creating portals is enabled, but this person is unauthorized because of Bookkeeper info,
                  // then show the Create button as disabled.
                  else if( reachedLimitWithBookkeeper || reachedLimitWithoutBookkeeper ){

                     //Disable the button
                     createButton.addClass("disabled");

                     //Add the create button to the view
                     this.$(this.createBtnContainer).html(createButton);

                     var message = "You've already reached the " + MetacatUI.appModel.get("portalTermSingular") +
                                   " limit for your ";

                     if( MetacatUI.appModel.get("enableBookkeeperServices") ){
                       message += MetacatUI.appModel.get("dataonePlusName");

                       if( MetacatUI.appModel.get("dataonePlusPreviewMode") ){
                         message += " free preview. ";
                       }
                       else{
                         message += " subscription. ";
                       }

                       var portalQuotas = MetacatUI.appUserModel.getQuotas("portal");
                       if( portalQuotas.length ){
                         message += "(" + portalQuotas[0].get("softLimit") + " " +
                                    ((portalQuotas[0].get("softLimit") > 1)? MetacatUI.appModel.get("portalTermPlural") : MetacatUI.appModel.get("portalTermSingular")) + ")";
                       }

                       message += " Contact us to upgrade your subscription.";

                     }
                     else{
                       message += " account. ";

                       var portalLimit = MetacatUI.appModel.get("portalLimit");
                       if( portalLimit > 0 ){
                         message += "(" + portalLimit + " " +
                                    ((portalLimit > 1)? MetacatUI.appModel.get("portalTermPlural") : MetacatUI.appModel.get("portalTermSingular")) +
                                    ")"
                       }
                     }

                     //Add the tooltip to the button
                     createButton.tooltip({
                       placement: "top",
                       trigger: "hover click focus",
                       delay: {
                         show: 500
                       },
                       title: message
                     });
                  }
                  else{

                    //Add the link URL to the button
                    createButton.attr("href", MetacatUI.root + "/edit/" + MetacatUI.appModel.get("portalTermPlural"))

                    //Add the create button to the view
                    this.$(this.createBtnContainer).html(createButton);
                  }

                  //Reset the isAuthorizedCreatePortal attribute
                  MetacatUI.appUserModel.set("isAuthorizedCreatePortal", null);
                }
              }
              catch(e){
                console.error(e);
              }
            },

            /**
            * Displays an error message when rendering this view has failed.
            */
            showError: function(){

              //Remove the loading elements
              this.$(this.listContainer).find(".loading").remove();

              if( this.$(this.listContainer).children("tr").length == 0 ){

                //Show an error message
                MetacatUI.appView.showAlert(
                  "Something went wrong while getting this list of portals.",
                  "alert-error",
                  this.$(this.listContainer));
              }
            }

          });

        });