# Source: src/js/models/Stats_deprecated.js

    /*global define */
    define(['jquery', 'underscore', 'backbone', 'models/LogsSearch', 'promise'],
    	function($, _, Backbone, LogsSearch, Promise) {
    	'use strict';

    	// Statistics Model
    	// ------------------
    	var Stats = Backbone.Model.extend(
        /** @lends Stats.prototype */{
    		// This model contains all of the statistics in a user's or query's profile
    		defaults: {
    			query: "*:* ", //Show everything
          postQuery: "", //An unencoded version of the query

    			metadataCount: 0,
    			dataCount: 0,
    			totalCount: 0,
    			metadataFormatIDs: [], //Uses same structure as Solr facet counts: ["text/csv", 5]
    			dataFormatIDs: [], //Uses same structure as Solr facet counts: ["text/csv", 5]

    			firstUpload: 0,
    			metadataUploads: null,
    			dataUploads: null,
    			metadataUploadDates: null,
    			dataUploadDates: null,

    			//Number of updates to content for each time period
    			firstUpdate: 0,
    			dataUpdateDates: null,
    			metadataUpdateDates: null,

    			firstBeginDate: 0,
    			temporalCoverage: 0,
    			coverageYears: 0,

          hideMetadataAssessment: false,
          mdqScoresImage: null,

          //HTTP GET requests are typically limited to 2,083 characters. So query lengths
          // should have this maximum before switching over to HTTP POST
          maxQueryLength: 1958,
          usePOST: false
    		},

    		//Some dated used for query creation
    		firstPossibleUpload: "2000-01-01T00:00:00Z", //The first possible date that an object could be uploaded (based on DataONE dates)
    		firstPossibleDataONEDownload: "2012-07-01T00:00:00Z", //The first possible download date from the DataONE CN
    		firstPossibleDataONEDate: "2012-07-01T00:00:00Z", //The first possible download date from the DataONE CN
    		firstPossibleDate: "1800-01-01T00:00:00Z",   //The first possible date that data could have been collected in (based on DataONE dates)

    		initialize: function(){
    			//Add a function to parse ISO date strings for IE8 and other older browsers
    			(function(){
    			    var D= new Date('2011-06-02T09:34:29+02:00');
    			    if(!D || +D!== 1307000069000){
    			        Date.fromISO= function(s){
    			            var day, tz,
    			            rx=/^(\d{4}\-\d\d\-\d\d([tT ][\d:\.]*)?)([zZ]|([+\-])(\d\d):(\d\d))?$/,
    			            p= rx.exec(s) || [];
    			            if(p[1]){
    			                day= p[1].split(/\D/);
    			                for(var i= 0, L= day.length; i<L; i++){
    			                    day[i]= parseInt(day[i], 10) || 0;
    			                };
    			                day[1]-= 1;
    			                day= new Date(Date.UTC.apply(Date, day));
    			                if(!day.getDate()) return NaN;
    			                if(p[5]){
    			                    tz= (parseInt(p[5], 10)*60);
    			                    if(p[6]) tz+= parseInt(p[6], 10);
    			                    if(p[4]== '+') tz*= -1;
    			                    if(tz) day.setUTCMinutes(day.getUTCMinutes()+ tz);
    			                }
    			                return day;
    			            }
    			            return NaN;
    			        }
    			    }
    			    else{
    			        Date.fromISO= function(s){
    			            return new Date(s);
    			        }
    			    }
    			})();

          //Set the request type (GET or POST)
          this.setRequestType();
          this.on("change:query", this.setRequestType);

    		},

    		//This function serves as a shorthand way to get all of the statistics stored in the model
    		getAll: function(options){
    			if (typeof options === "undefined")
    				var options = {};

    			//Listen for our responses back from the server before we send requests that require info from the response
    			this.listenToOnce(this, 'change:firstBeginDate', this.getLastEndDate);
    			this.listenToOnce(this, 'change:lastEndDate', this.getCollectionYearFacets);
    			this.listenToOnce(this, 'change:dataCount', this.getDataFormatIDs);
    			this.listenToOnce(this, 'change:metadataCount', this.getMetadataFormatIDs);
    			this.listenToOnce(this, 'change:firstUpload', this.getUpdateDates);

    			this.getFirstBeginDate();
    			this.getFirstUpload();

    			this.getFormatTypes();

    			// Only get the MetaDIG scores if MetacatUI is configured to display metadata assesments
          // AND this model has them enabled, too.
    			if ( !MetacatUI.appModel.get("hideSummaryMetadataAssessment") && !this.get("hideMetadataAssessment") ){
    				this.getMdqScores();
          }

    		},

        // Send a Solr query to get the earliest beginDate, latest endDate, and facets of data collection years
        getFirstBeginDate: function(){
          var model = this;

          //Define a success callback when the query is successful
          var successCallback = function(data, textStatus, xhr) {

            if( !data.response.numFound ){

              //There were no begin dates found
              model.set('totalBeginDates', 0);

              //Construct a query
              var query = model.get('query') +
                    " AND endDate:[" + model.firstPossibleDate + " TO " + (new Date()).toISOString() + "]" + //Use date filter to weed out badly formatted data
                    " AND -obsoletedBy:*",
                  //Get one row only
                  rows = "1",
                  //Sort the results in ascending order
                  sort = "endDate asc",
                  //Return only the endDate field
                  fl = "endDate";

              var successCallback = function(endDateData, textStatus, xhr) {
                //If not endDates or beginDates are found, there is no temporal data in the index, so save falsey values
                if(!endDateData.response.numFound){
                  model.set('firstBeginDate', null);
                  model.set('lastEndDate', null);
                }
                else{
                  model.set('firstBeginDate', new Date.fromISO(endDateData.response.docs[0].endDate));
                }
              }

              if( model.get("usePOST") ){

                var queryData = new FormData();
                queryData.append("q", query);
                queryData.append("rows", rows);
                queryData.append("sort", sort);
                queryData.append("fl", fl);
                queryData.append("wt", "json");

                var requestSettings = {
                  url: MetacatUI.appModel.get('queryServiceUrl'),
                  type: "POST",
                  contentType: false,
                  processData: false,
                  data: queryData,
                  dataType: "json",
                  success: successCallback
                }

              }
              else{
                //Find the earliest endDate if there are no beginDates
                var requestSettings = {
                  url: MetacatUI.appModel.get('queryServiceUrl') + "q=" + query +
                       "&rows=" + rows + "&sort=" + sort + "&fl=" + fl + "&wt=json",
                  type: "GET",
                  dataType: "json",
                  success: successCallback
                }
              }

              $.ajax(_.extend(requestSettings, MetacatUI.appUserModel.createAjaxSettings()));
            }
            else{
              // Save the earliest beginDate and total found in our model
              model.set('firstBeginDate', new Date.fromISO(data.response.docs[0].beginDate));
              model.set('totalBeginDates', data.response.numFound);

              model.trigger("change:firstBeginDate");
              model.trigger("change:totalBeginDates");
            }
          }

          //Construct a query
          var specialQueryParams = " AND beginDate:[" + this.firstPossibleDate + " TO " + (new Date()).toISOString() + "] AND -obsoletedBy:* AND -formatId:*dataone.org/collections* AND -formatId:*dataone.org/portals*",
              query = this.get("query") + specialQueryParams,
              //Get one row only
              rows = "1",
              //Sort the results in ascending order
              sort = "beginDate asc",
              //Return only the beginDate field
              fl = "beginDate";

          if( this.get("usePOST") ){

            //Get the unencoded query string
            if( this.get("postQuery") ){
              query = this.get("postQuery") + specialQueryParams;
            }
            else if( this.get("searchModel") ){
              query = this.get("searchModel").getQuery(undefined, { forPOST: true });
              this.set("postQuery", query);
              query = query + specialQueryParams;
            }

            var queryData = new FormData();
            queryData.append("q", query);
            queryData.append("rows", rows);
            queryData.append("sort", sort);
            queryData.append("fl", fl);
            queryData.append("wt", "json");

            var requestSettings = {
              url: MetacatUI.appModel.get('queryServiceUrl'),
              type: "POST",
              contentType: false,
              processData: false,
              data: queryData,
              dataType: "json",
              success: successCallback
            }

          }
          else{

            var requestSettings = {
              url: MetacatUI.appModel.get('queryServiceUrl') + "q=" + query +
                   "&rows=" + rows +
                   "&fl=" + fl +
                   "&sort=" + sort +
                   "&wt=json",
              type: "GET",
              dataType: "json",
              success: successCallback
            }

          }

          //Send the query
          $.ajax(_.extend(requestSettings, MetacatUI.appUserModel.createAjaxSettings()));

    		},

        getLastEndDate: function(){
          var model = this;

          var now = new Date();

          //Get the latest temporal data coverage year
          var specialQueryParams = " AND endDate:[" + this.firstPossibleDate + " TO " + now.toISOString() + "]" + //Use date filter to weed out badly formatted data
                " AND -obsoletedBy:* AND -formatId:*dataone.org/collections* AND -formatId:*dataone.org/portals*",
              query = this.get('query') + specialQueryParams,
              rows = 1,
              fl   = "endDate",
              sort = "endDate desc",
              wt   = "json";

          var successCallback = function(data, textStatus, xhr) {
            if(typeof data == "string"){
              data = JSON.parse(data);
            }

            if(!data.response.numFound){
              //Save some falsey values if none are found
              model.set('lastEndDate', null);
            }
            else{
              // Save the earliest beginDate and total found in our model - but do not accept a year greater than this current year
              var now = new Date();
              if(new Date.fromISO(data.response.docs[0].endDate).getUTCFullYear() > now.getUTCFullYear()){
                model.set('lastEndDate', now);
              }
              else{
                model.set('lastEndDate', new Date.fromISO(data.response.docs[0].endDate));
              }

              model.trigger("change:lastEndDate");
            }
          }

          if( this.get("usePOST") ){

            //Get the unencoded query string
            if( this.get("postQuery") ){
              query = this.get("postQuery") + specialQueryParams;
            }
            else if( this.get("searchModel") ){
              query = this.get("searchModel").getQuery(undefined, { forPOST: true });
              this.set("postQuery", query);
              query = query + specialQueryParams;
            }

            var queryData = new FormData();
            queryData.append("q", query);
            queryData.append("rows", rows);
            queryData.append("sort", sort);
            queryData.append("fl", fl);
            queryData.append("wt", "json");

            var requestSettings = {
              url: MetacatUI.appModel.get('queryServiceUrl'),
              type: "POST",
              contentType: false,
              processData: false,
              data: queryData,
              dataType: "json",
              success: successCallback
            }
          }
          else{
            //Query for the latest endDate
            var requestSettings = {
              url: MetacatUI.appModel.get('queryServiceUrl') + "q=" + query +
                   "&rows=" + rows + "&fl=" + fl + "&sort=" + sort + "&wt=" + wt,
              type: "GET",
              dataType: "json",
              success: successCallback
            }
          }

          $.ajax(_.extend(requestSettings, MetacatUI.appUserModel.createAjaxSettings()));
        },

        /**
        ** getFormatTypes will send three Solr queries to get the formatTypes and formatID statistics and will update the  model
        **/
        getFormatTypes: function(){
          var model = this;

          //Build the query to get the format types
          var specialQueryParams = " AND (formatType:METADATA OR formatType:DATA) AND -obsoletedBy:*  AND -formatId:*dataone.org/collections* AND -formatId:*dataone.org/portals*",
              query = this.get('query') + specialQueryParams,
              rows  = "2",
              group = true,
              groupField = "formatType",
              groupLimit = "0",
              stats      = true,
              statsField = "size",
              sort       = "formatType desc",
              wt         = "json";

          var successCallback = function(data, textStatus, xhr) {

            var formats = data.grouped.formatType.groups;

            if(formats.length == 1){	//Only one format type was found
              if(formats[0].groupValue == "METADATA"){ //That one format type is metadata
                model.set('dataCount', 0);
                model.trigger("change:dataCount");
                model.set('metadataCount', formats[0].doclist.numFound);
                model.set('dataFormatIDs', ["", 0]);
              }else{
                model.set('dataCount', formats[0].doclist.numFound);
                model.set('metadataCount', 0);
                model.trigger("change:metadataCount");
                model.set('metadataFormatIDs', ["", 0]);
              }
            }
            //If no data or metadata objects were found, draw blank charts
            else if(formats.length == 0){

              //Store falsey data
              model.set('dataCount', 0);
              model.trigger("change:dataCount");

              model.set("totalCount", 0);
              model.trigger("change:totalCount");

              model.set('metadataCount', 0);
              model.trigger("change:metadataCount");

              model.set('metadataFormatIDs', ["", 0]);
              model.set('dataFormatIDs', ["", 0]);

              return;
            }
            else{
              //Extract the format types (because of filtering and sorting they will always return in this order)
              model.set('metadataCount', formats[0].doclist.numFound);
              model.set('dataCount', formats[1].doclist.numFound);
            }

            //Get the total size of all the files in the index
            var totalSize = data.stats.stats_fields.size.sum;
            model.set("totalSize", totalSize);
          }

          if( this.get("usePOST") ){

            //Get the unencoded query string
            if( this.get("postQuery") ){
              query = this.get("postQuery") + specialQueryParams;
            }
            else if( this.get("searchModel") ){
              query = this.get("searchModel").getQuery(undefined, { forPOST: true });
              this.set("postQuery", query);
              query = query + specialQueryParams;
            }

            var requestData = new FormData();
            requestData.append("q", query);
            requestData.append("rows", rows);
            requestData.append("group", group);
            requestData.append("group.field", groupField);
            requestData.append("group.limit", groupLimit);
            requestData.append("stats", stats);
            requestData.append("stats.field", statsField);
            requestData.append("sort", sort);
            requestData.append("wt", wt);

            //Request settings for POST requests
            var requestSettings = {
              url: MetacatUI.appModel.get('queryServiceUrl'),
              data: requestData,
              contentType: false,
              processData: false,
              type: "POST",
              dataType: "json",
              success: successCallback
            }

          }
          else{
            //Run the query
            var requestSettings = {
              url: MetacatUI.appModel.get('queryServiceUrl') +
                   "q=" + query +
                   "&rows=" + rows +
                   "&group=" + group +
                   "&group.field=" + groupField +
                   "&group.limit=" + groupLimit +
                   "&stats=" + stats +
                   "&stats.field=" + statsField +
                   "&sort=" + sort +
                   "&wt=" + wt,
              type: "GET",
              dataType: "json",
              success: successCallback
            }
          }

          $.ajax(_.extend(requestSettings, MetacatUI.appUserModel.createAjaxSettings()));
        },

    		getDataFormatIDs: function(){
    			var model = this;

          if( !this.get('dataCount') ){
            return;
          }

          var specialQueryParams = " AND formatType:DATA AND -obsoletedBy:* AND -formatId:*dataone.org/collections* AND -formatId:*dataone.org/portals*",
              query = this.get('query') + specialQueryParams,
              facet = "true",
              facetField = "formatId",
              facetLimit = "-1",
              facetMincount = "1",
              rows = "0",
              wt = "json";

          var successCallback = function(data, textStatus, xhr) {
            model.set('dataFormatIDs', data.facet_counts.facet_fields.formatId);
          }

          if( this.get("usePOST") ){

            //Get the unencoded query string
            if( this.get("postQuery") ){
              query = this.get("postQuery") + specialQueryParams;
            }
            else if( this.get("searchModel") ){
              query = this.get("searchModel").getQuery(undefined, { forPOST: true });
              this.set("postQuery", query);
              query = query + specialQueryParams;
            }

            var queryData = new FormData();
            queryData.append("q", query);
            queryData.append("facet", facet);
            queryData.append("facet.field", facetField);
            queryData.append("facet.limit", facetLimit);
            queryData.append("facet.mincount", facetMincount);
            queryData.append("rows", rows);
            queryData.append("wt", wt);

            var requestSettings = {
              url: MetacatUI.appModel.get('queryServiceUrl'),
              type: "POST",
              contentType: false,
              processData: false,
              data: queryData,
              dataType: "json",
              success: successCallback
            }
          }
          else{
            //Now get facet counts of the data format ID's
            var requestSettings = {
              url: MetacatUI.appModel.get('queryServiceUrl') + "q=" + query +
                   "&facet=" + facet + "&facet.field=" + facetField +
                   "&facet.limit=" + facetLimit + "&facet.mincount=" + facetMincount +
                   "&rows=" + rows + "&wt=" + wt,
              type: "GET",
              dataType: "json",
              success: successCallback
            }
          }

          $.ajax(_.extend(requestSettings, MetacatUI.appUserModel.createAjaxSettings()));
    		},

        getMetadataFormatIDs: function(){

          if( !this.get('metadataCount') ){
            return;
          }

    			var model = this;

          var specialQueryParams = " AND formatType:METADATA AND -obsoletedBy:*  AND -formatId:*dataone.org/collections* AND -formatId:*dataone.org/portals*",
              query = this.get("query") + specialQueryParams,
              facet = "true",
              facetField = "formatId",
              facetLimit = "-1",
              facetMincount = "1",
              rows = "0",
              wt = "json";

          var successCallback = function(data, textStatus, xhr) {
            model.set('metadataFormatIDs', data.facet_counts.facet_fields.formatId);
          }

          if( this.get("usePOST") ){

            //Get the unencoded query string
            if( this.get("postQuery") ){
              query = this.get("postQuery") + specialQueryParams;
            }
            else if( this.get("searchModel") ){
              query = this.get("searchModel").getQuery(undefined, { forPOST: true });
              this.set("postQuery", query);
              query = query + specialQueryParams;
            }

            var queryData = new FormData();
            queryData.append("q", query);
            queryData.append("facet", facet);
            queryData.append("facet.field", facetField);
            queryData.append("facet.limit", facetLimit);
            queryData.append("facet.mincount", facetMincount);
            queryData.append("rows", rows);
            queryData.append("wt", wt);

            var requestSettings = {
              url: MetacatUI.appModel.get('queryServiceUrl'),
              type: "POST",
              contentType: false,
              processData: false,
              data: queryData,
              dataType: "json",
              success: successCallback
            }
          }
          else{
            //Now get facet counts of the metadata format ID's
            var requestSettings = {
              url: MetacatUI.appModel.get('queryServiceUrl') + "q=" + query +
                   "&facet=" + facet + "&facet.field=" + facetField +
                   "&facet.limit=" + facetLimit + "&facet.mincount=" + facetMincount +
                   "&rows=" + rows + "&wt=" + wt,
              type: "GET",
              dataType: "json",
              success: successCallback
            }
          }

          $.ajax(_.extend(requestSettings, MetacatUI.appUserModel.createAjaxSettings()));
        },

        /*
        * getUpdateDates will get the number of newest-version science metadata and data
        * objects uploaded in each month
        */
        getUpdateDates: function(){

          var model = this;

          var now = new Date();

          var metadataQueryParams = " AND -obsoletedBy:* AND formatType:METADATA  AND -formatId:*dataone.org/collections* AND -formatId:*dataone.org/portals*";
          var metadataQuery = this.get('query') + metadataQueryParams;

          var firstPossibleUpdate = MetacatUI.nodeModel.isCN(MetacatUI.nodeModel.get("currentMemberNode"))?
            this.firstPossibleDataONEDate : model.get("firstUpload");

          if( !firstPossibleUpdate ){
            firstPossibleUpdate = new Date();
            firstPossibleUpdate.setYear( firstPossibleUpdate.getYear() - 100 );
            firstPossibleUpdate = firstPossibleUpdate.toISOString();
          }

          var rows = "1",
              sort = "dateUploaded asc",
              facet = "true",
              facetMissing = "true", //Include months that have 0 uploads
              facetLimit = "-1",
              facetRange = "dateUploaded",
              facetRangeStart = firstPossibleUpdate,
              facetRangeEnd = now.toISOString(),
              wt = "json";

          var dataSuccessCallback = function(data, textStatus, xhr) {
            if( !data.response.numFound ){
              model.set("dataUpdateDates", []);
            }
            else{

              //Get the array of dateUploaded facets
              var updateDates = data.facet_counts.facet_ranges.dateUploaded.counts;

              //Remove all the empty facet counts at the beginning of the array
              while(updateDates[1] == 0){

                updateDates.splice(0, 2);

              }

              //Save the dateUploaded facets for data objects
              model.set("dataUpdateDates", updateDates);

              // Save the earliest dateUploaded and total found in our model
              if(updateDates[0] < model.get("firstUpdate"))
                model.set('firstUpdate', updateDates[0]);
            }
          }

          var metadataSuccessCallback = function(data, textStatus, xhr) {

            if( !data.response.numFound ){
              model.set('firstUpdate', null);

              model.set("metadataUpdateDates", []);
            }
            else{

              //Get the array of dateUploaded facets
              var updateDates = data.facet_counts.facet_ranges.dateUploaded.counts;

              //Remove all the empty facet counts at the beginning of the array
              while(updateDates[1] == 0){

                updateDates.splice(0, 2);

              }

              //Save the dateUploaded facets for metadata objects
              model.set("metadataUpdateDates", updateDates);

              // Save the earliest dateUploaded and total found in our model
              model.set('firstUpdate', updateDates[0]);
            }

            var dataQueryParams = " AND -obsoletedBy:* AND formatType:DATA",
                dataQuery = model.get("query") + dataQueryParams;

            if( model.get("usePOST") ){

              //Get the unencoded query string
              if( model.get("postQuery") ){
                dataQuery = model.get("postQuery") + dataQueryParams;
              }
              else if( model.get("searchModel") ){
                dataQuery = this.get("searchModel").getQuery(undefined, { forPOST: true });
                this.set("postQuery", query);
                dataQuery = dataQuery + dataQueryParams;
              }

              var queryData = new FormData();
              queryData.append("q", dataQuery);
              queryData.append("sort", sort);
              queryData.append("facet", facet);
              queryData.append("facet.missing", facetMissing);
              queryData.append("facet.limit", facetLimit);
              queryData.append("facet.range", facetRange);
              queryData.append("facet.range.start", facetRangeStart);
              queryData.append("facet.range.end", facetRangeEnd);
              queryData.append("facet.range.gap", "+1MONTH");
              queryData.append("rows", rows);
              queryData.append("wt", wt);

              var requestSettings = {
                url: MetacatUI.appModel.get('queryServiceUrl'),
                type: "POST",
                contentType: false,
                processData: false,
                data: queryData,
                dataType: "json",
                success: dataSuccessCallback
              }
            }
            else{
              var requestSettings = {
                url: MetacatUI.appModel.get('queryServiceUrl') + "q=" + dataQuery +
                     "&sort=" + sort + "&rows=" + rows + "&facet=" + facet +
                     "&facet.missing=" + facetMissing + "&facet.limit=" + facetLimit +
                     "&facet.range=" + facetRange + "&facet.range.start=" + facetRangeStart +
                     "&facet.range.end=" + facetRangeEnd + "&facet.range.gap=" + "%2B1MONTH" +
                     "&wt=" + wt,
                type: 'GET',
                dataType: "json",
                success: dataSuccessCallback
              }
            }

            $.ajax(_.extend(requestSettings, MetacatUI.appUserModel.createAjaxSettings()));
          }

          if( this.get("usePOST") ){

            //Get the unencoded query string
            if( this.get("postQuery") ){
              metadataQuery = this.get("postQuery") + metadataQueryParams;
            }
            else if( this.get("searchModel") ){
              metadataQuery = this.get("searchModel").getQuery(undefined, { forPOST: true });
              this.set("postQuery", metadataQuery);
              metadataQuery = metadataQuery + metadataQueryParams;
            }

            var queryData = new FormData();
            queryData.append("q", metadataQuery);
            queryData.append("sort", sort);
            queryData.append("facet", facet);
            queryData.append("facet.missing", facetMissing);
            queryData.append("facet.limit", facetLimit);
            queryData.append("facet.range", facetRange);
            queryData.append("facet.range.start", facetRangeStart);
            queryData.append("facet.range.end", facetRangeEnd);
            queryData.append("facet.range.gap", "+1MONTH");
            queryData.append("rows", rows);
            queryData.append("wt", wt);

            var requestSettings = {
              url: MetacatUI.appModel.get('queryServiceUrl'),
              type: "POST",
              contentType: false,
              processData: false,
              data: queryData,
              dataType: "json",
              success: metadataSuccessCallback
            }
          }
          else{
            //Run the query
            var requestSettings = {
              url: MetacatUI.appModel.get('queryServiceUrl') + "q=" + metadataQuery +
                   "&sort=" + sort + "&rows=" + rows + "&facet=" + facet +
                   "&facet.missing=" + facetMissing + "&facet.limit=" + facetLimit +
                   "&facet.range=" + facetRange + "&facet.range.start=" + facetRangeStart +
                   "&facet.range.end=" + facetRangeEnd + "&facet.range.gap=" + "%2B1MONTH" +
                   "&wt=" + wt,
              dataType: "json",
              type: "GET",
              success: metadataSuccessCallback
            }
          }

    			$.ajax(_.extend(requestSettings, MetacatUI.appUserModel.createAjaxSettings()));

    		},

        /*
        * Gets the earliest dateUploaded from the solr index
        */
        getFirstUpload: function(){

          var now = new Date(),
              model = this,
              firstPossibleUpload = new Date();

            firstPossibleUpload.setYear( firstPossibleUpload.getYear() - 100 );
            firstPossibleUpload = firstPossibleUpload.toISOString();

          //Get the earliest upload date
          var specialQueryParams = " AND formatType:(METADATA OR DATA)" + //Weeds out resource maps and annotations
                      " AND dateUploaded:[" + firstPossibleUpload + " TO " + now.toISOString() + "]" + //Weeds out badly formatted dates
                      " AND -obsoletes:*  AND -formatId:*dataone.org/collections* AND -formatId:*dataone.org/portals*",    //Only count one version of a revision chain
              query = this.get('query') + specialQueryParams,
              fl   = "dateUploaded",
              rows = "1",
              sort = "dateUploaded asc",
              wt   = "json";

          var successCallback = function(data, textStatus, xhr) {
            if(!data.response.numFound){
              //Save some falsey values if none are found
              model.set('totalUploads', 0);
              model.trigger("change:totalUploads");

              model.set('firstUpload', null);

              model.set("dataUploads", 0);
              model.set("metadataUploads", 0);
              model.set('metadataUploadDates', []);
              model.set('dataUploadDates', []);
            }
            else{
              // Save the earliest dateUploaded and total found in our model
              model.set('firstUpload', data.response.docs[0].dateUploaded);
              model.set('totalUploads', data.response.numFound);
            }
          }

          if( this.get("usePOST") ){

            //Get the unencoded query string
            if( this.get("postQuery") ){
              query = this.get("postQuery") + specialQueryParams;
            }
            else if( this.get("searchModel") ){
              query = this.get("searchModel").getQuery(undefined, { forPOST: true });
              this.set("postQuery", query);
              query = query + specialQueryParams;
            }

            var requestData = new FormData();
            requestData.append("q", query);
            requestData.append("rows", rows);
            requestData.append("fl", fl);
            requestData.append("sort", sort);
            requestData.append("wt", wt);

            //Request settings for POST requests
            var requestSettings = {
              url: MetacatUI.appModel.get('queryServiceUrl'),
              data: requestData,
              processData: false,
              contentType: false,
              type: "POST",
              dataType: "json",
              success: successCallback
            }

          }
          else{

            //Request settings for GET requests
            var requestSettings = {
              url: MetacatUI.appModel.get('queryServiceUrl') + "q=" + query +
                   "&rows=" + rows + "&fl=" + fl + "&wt=" + wt + "&sort=" + sort,
              type: "GET",
              dataType: "json",
              success: successCallback
            }

          }

    			$.ajax(_.extend(requestSettings, MetacatUI.appUserModel.createAjaxSettings()));

    		},

        /* getTemporalCoverage
        * Get the temporal coverage of this query/user from Solr
        */
        getCollectionYearFacets: function(){
          var model = this;

          //How many years back should we look for temporal coverage?
          var lastYear =  this.get('lastEndDate') ? this.get('lastEndDate').getUTCFullYear() : new Date().getUTCFullYear(),
              firstYear = this.get('firstBeginDate')? this.get('firstBeginDate').getUTCFullYear() : new Date().getUTCFullYear(),
              totalYears = lastYear - firstYear,
              today = new Date().getUTCFullYear(),
              now   = new Date(),
              yearsFromToday = {
               fromBeginning: today - firstYear,
               fromEnd: today - lastYear
              };

          //Determine our year bin size so that no more than 10 facet.queries are being sent at a time
          var binSize = 1;

          if((totalYears > 10) && (totalYears <= 20)){
          	binSize = 2;
          }
          else if((totalYears > 20) && (totalYears <= 50)){
          	binSize = 5;
          }
          else if((totalYears > 50) && (totalYears <= 100)){
          	binSize = 10;
          }
          else if(totalYears > 100){
          	binSize = 25;
          }

          //Construct our facet.queries for the beginDate and endDates, starting with all years before this current year
          var allFacetQueries = [],
              key = "";

          for(var yearsAgo = yearsFromToday.fromBeginning; yearsAgo >= yearsFromToday.fromEnd; yearsAgo -= binSize){
            // The query logic here is: If the beginnning year is anytime before or
            //  during the last year of the bin AND the ending year is anytime after
            //  or during the first year of the bin, it counts.
            if(binSize == 1){
              //Querying for just the current year needs to be treated a bit differently
              // and won't be caught in our for loop
              if((yearsAgo == 0) && (lastYear == today)){
                var oneYearFromNow = new Date();
                oneYearFromNow.setFullYear( oneYearFromNow.getFullYear() + 1 );

                var now = new Date();

                allFacetQueries.push("{!key=" + lastYear + "}(beginDate:[* TO " +
                                  oneYearFromNow.toISOString() + "/YEAR] AND endDate:[" +
                                  now.toISOString() + "/YEAR TO *])");
              }
              else{
                key = today - yearsAgo;

                var beginDateLimit = new Date();
                beginDateLimit.setFullYear( beginDateLimit.getFullYear() - (yearsAgo-1) );

                var endDateLimit = new Date();
                endDateLimit.setFullYear( endDateLimit.getFullYear() - yearsAgo );

                allFacetQueries.push("{!key=" + key + "}(beginDate:[* TO " +
                                  beginDateLimit.toISOString() + "/YEAR] AND endDate:[" +
                                  endDateLimit.toISOString() + "/YEAR TO *])");
              }
            }
            else if (yearsAgo <= binSize){
              key = (today - yearsAgo) + "-" + lastYear;

              var beginDateLimit = new Date();
              beginDateLimit.setFullYear( beginDateLimit.getFullYear() - yearsFromToday.fromEnd );

              var endDateLimit = new Date();
              endDateLimit.setFullYear( endDateLimit.getFullYear() - yearsAgo );

              allFacetQueries.push("{!key=" + key + "}(beginDate:[* TO " +
                                beginDateLimit.toISOString() +"/YEAR] AND endDate:[" +
                                endDateLimit.toISOString() + "/YEAR TO *])");
            }
            else{
              key = (today - yearsAgo) + "-" + (today - yearsAgo + binSize-1);

              var beginDateLimit = new Date();
              beginDateLimit.setFullYear( beginDateLimit.getFullYear() - (yearsAgo - binSize-1) );

              var endDateLimit = new Date();
              endDateLimit.setFullYear( endDateLimit.getFullYear() - yearsAgo );

              allFacetQueries.push("{!key=" + key + "}(beginDate:[* TO " +
                             beginDateLimit.toISOString() + "/YEAR] AND endDate:[" +
                             endDateLimit.toISOString() + "/YEAR TO *])");
            }
          }

          var now = new Date();

          //The full query
          var specialQueryParams = " AND beginDate:[" + this.firstPossibleDate + " TO " + now.toISOString() + "] AND -obsoletedBy:*  AND -formatId:*dataone.org/collections* AND -formatId:*dataone.org/portals*",
              query = this.get('query') + specialQueryParams,
              rows = "0",
              facet = "true",
              facetLimit = "30000", //Put some reasonable limit here so we don't wait forever for this query
              facetMissing = "true", //We want to retrieve years with 0 results
              wt = "json";

          var successCallback = function(data, textStatus, xhr) {
            model.set('temporalCoverage', data.facet_counts.facet_queries);
          }

          if( this.get("usePOST") ){

            //Get the unencoded query string
            if( this.get("postQuery") ){
              query = this.get("postQuery") + specialQueryParams;
            }
            else if( this.get("searchModel") ){
              query = this.get("searchModel").getQuery(undefined, { forPOST: true }) + specialQueryParams;
            }

            var requestData = new FormData();
            requestData.append("q", query);
            requestData.append("rows", rows);
            requestData.append("wt", wt);
            requestData.append("facet", facet);
            requestData.append("facet.limit", facetLimit);
            requestData.append("facet.missing", facetMissing);

            _.each(allFacetQueries, function(facetQuery){
              requestData.append("facet.query", facetQuery);
            });

            //Request settings for POST requests
            var requestSettings = {
              url: MetacatUI.appModel.get('queryServiceUrl'),
              data: requestData,
              processData: false,
              contentType: false,
              type: "POST",
              dataType: "json",
              success: successCallback
            }
          }
          else{
            var requestSettings = {
              url: MetacatUI.appModel.get('queryServiceUrl') + "q=" + query +
                   "&rows=" + rows + "&facet=" + facet + "&facet.limit=" + facetLimit +
                   "&facet.missing=" + facetMissing + "&wt=" + wt +
                   "&facet.query=" + allFacetQueries.join("&facet.query="),
              dataType: "json",
              success: successCallback
            }
          }

          $.ajax(_.extend(requestSettings, MetacatUI.appUserModel.createAjaxSettings()));
        },

        imgLoad: function(url) {
            // Create new promise with the Promise() constructor;
            // This has as its argument a function with two parameters, resolve and reject
            var model = this;
            return new Promise(function (resolve, reject) {
                // Standard XHR to load an image
                var request = new XMLHttpRequest();
                request.open('GET', url);
                request.responseType = 'blob';

                // When the request loads, check whether it was successful
                request.onload = function () {
                    if (request.status === 200) {
                        // If successful, resolve the promise by passing back the request response
                        resolve(request.response);
                    } else {
                        // If it fails, reject the promise with a error message
                        reject(new Error('Image didn\'t load successfully; error code:' + request.statusText));
                        model.set('mdqScoresError', request.statusText);
                    }
                };

                request.onerror = function () {
                    console.log("onerror");
                    // Also deal with the case when the entire request fails to begin with
                    // This is probably a network error, so reject the promise with an appropriate message
                    reject(new Error('There was a network error.'));
                };

                // Send the request
                request.send();
            });
        },

        getMdqScores: function(){
          try{
            var myImage = new Image();
            var model = this;
            myImage.crossOrigin = ""; // or "anonymous"
            if(MetacatUI.appView.currentView === null) return;

            // Call the function with the URL we want to load, but then chain the
            // promise then() method on to the end of it. This contains two callbacks
            var serviceUrl = MetacatUI.appModel.get('mdqScoresServiceUrl');

            if( !serviceUrl ){
              this.set("mdqScoresImage", this.defaults.mdqScoresImage);
              this.trigger("change:mdqScoresImage");
              return;
            }

            if( Array.isArray(MetacatUI.appModel.get('mdqAggregatedSuiteIds')) && MetacatUI.appModel.get('mdqAggregatedSuiteIds').length ){
              var suite = MetacatUI.appModel.get('mdqAggregatedSuiteIds')[0];
              var id = MetacatUI.appView.currentView.model.get("id");
              var url = serviceUrl + "?collection=" + id + "&suite=" + suite;
              this.imgLoad(url).then(function (response) {
                  // The first runs when the promise resolves, with the request.reponse specified within the resolve() method.
                  var imageURL = window.URL.createObjectURL(response);
                  myImage.src = imageURL;
                  model.set('mdqScoresImage', myImage);
                  // The second runs when the promise is rejected, and logs the Error specified with the reject() method.
              }, function (Error) {
                  console.error(Error);
              });
            }
            else{
              this.set("mdqScoresImage", this.defaults.mdqScoresImage);
            }
          }
          catch(e){
            this.set("mdqScoresImage", this.defaults.mdqScoresImage);
            this.trigger("change:mdqScoresImage");
            console.error("Cannot get the Metadata Quality scores: ", e);
          }
        },

        setRequestType: function(){
          if( MetacatUI.appModel.get("disableQueryPOSTs") ){
            this.set("usePOST", false);
          }
          else{
            if( this.get("query") && this.get("query").length > this.get("maxQueryLength") ){
              this.set("usePOST", true);
            }
          }
        }

      });
      return Stats;
    });