// $Id$

/**
 * Baseclass for all facet widgets.
 *
 * @class AbstractFacetWidget
 * @augments AjaxSolr.AbstractWidget
 */
AjaxSolr.AbstractFacetWidget = AjaxSolr.AbstractWidget.extend(
  /** @lends AjaxSolr.AbstractFacetWidget.prototype */
  {
  /**
   * The field to facet on.
   *
   * @field
   * @public
   * @type String
   */
  field: null,

  /**
   * Set to <tt>false</tt> to force a single "fq" parameter for this widget.
   *
   * @field
   * @public
   * @type Boolean
   * @default true
   */
  multivalue: true,

  init: function () {
    this.initStore();
  },

  /**
   * Add facet parameters to the parameter store.
   */
  initStore: function () {
    /* http://wiki.apache.org/solr/SimpleFacetParameters */
    var parameters = [
      'facet.prefix',
      'facet.sort',
      'facet.limit',
      'facet.offset',
      'facet.mincount',
      'facet.missing',
      'facet.method',
      'facet.enum.cache.minDf'
    ];

    this.manager.store.addByValue('facet', true);

    // Set facet.field, facet.date or facet.range to truthy values to add
    // related per-field parameters to the parameter store.
    if (this['facet.field'] !== undefined) {
      this.manager.store.addByValue('facet.field', this.field);
    }
    else if (this['facet.date'] !== undefined) {
      this.manager.store.addByValue('facet.date', this.field);
      parameters = parameters.concat([
        'facet.date.start',
        'facet.date.end',
        'facet.date.gap',
        'facet.date.hardend',
        'facet.date.other',
        'facet.date.include'
      ]);
    }
    else if (this['facet.range'] !== undefined) {
      this.manager.store.addByValue('facet.range', this.field);
      parameters = parameters.concat([
        'facet.range.start',
        'facet.range.end',
        'facet.range.gap',
        'facet.range.hardend',
        'facet.range.other',
        'facet.range.include'
      ]);
    }

    for (var i = 0, l = parameters.length; i < l; i++) {
      if (this[parameters[i]] !== undefined) {
        this.manager.store.addByValue('f.' + this.field + '.' + parameters[i], this[parameters[i]]);
      }
    }
  },

  /**
   * @returns {Boolean} Whether any filter queries have been set using this
   *   widget's facet field.
   */
  isEmpty: function () {
    return !this.manager.store.find('fq', new RegExp('^-?' + this.field + ':'));
  },

  /**
   * Sets the filter query.
   *
   * @returns {Boolean} Whether the selection changed.
   */
  set: function (value) {
    return this.changeSelection(function () {
      var a = this.manager.store.removeByValue('fq', new RegExp('^-?' + this.field + ':')),
          b = this.manager.store.addByValue('fq', this.fq(value));
      return a || b;
    });
  },

  /**
   * Adds a filter query.
   *
   * @returns {Boolean} Whether a filter query was added.
   */
  add: function (value) {
    return this.changeSelection(function () {
      return this.manager.store.addByValue('fq', this.fq(value));
    });
  },

  /**
   * Removes a filter query.
   *
   * @returns {Boolean} Whether a filter query was removed.
   */
  remove: function (value) {
    return this.changeSelection(function () {
      return this.manager.store.removeByValue('fq', this.fq(value));
    });
  },

  /**
   * Removes all filter queries using the widget's facet field.
   *
   * @returns {Boolean} Whether a filter query was removed.
   */
  clear: function () {
    return this.changeSelection(function () {
      return this.manager.store.removeByValue('fq', new RegExp('^-?' + this.field + ':'));
    });
  },

  /**
   * Helper for selection functions.
   *
   * @param {Function} Selection function to call.
   * @returns {Boolean} Whether the selection changed.
   */
  changeSelection: function (func) {
    changed = func.apply(this);
    if (changed) {
      this.afterChangeSelection();
    }
    return changed;
  },

  /**
   * An abstract hook for child implementations.
   *
   * <p>This method is executed after the filter queries change.</p>
   */
  afterChangeSelection: function () {},

  /**
   * One of "facet.field", "facet.date" or "facet.range" must be set on the
   * widget in order to determine where the facet counts are stored.
   *
   * @returns {Array} An array of objects with the properties <tt>facet</tt> and
   * <tt>count</tt>, e.g <tt>{ facet: 'facet', count: 1 }</tt>.
   */
  getFacetCounts: function () {
    var property;
    if (this['facet.field'] !== undefined) {
      property = 'facet_fields';
    }
    else if (this['facet.date'] !== undefined) {
      property = 'facet_dates';
    }
    else if (this['facet.range'] !== undefined) {
      property = 'facet_ranges';
    }
    if (property !== undefined) {
      switch (this.manager.store.get('json.nl').val()) {
        case 'map':
          return this.getFacetCountsMap(property);
        case 'arrarr':
          return this.getFacetCountsArrarr(property);
        default:
          return this.getFacetCountsFlat(property);
      }
    }
    throw 'Cannot get facet counts unless one of the following properties is set to "true" on widget "' + this.id + '": "facet.field", "facet.date", or "facet.range".';
  },

  /**
   * Used if the facet counts are represented as a JSON object.
   *
   * @param {String} property "facet_fields", "facet_dates", or "facet_ranges".
   * @returns {Array} An array of objects with the properties <tt>facet</tt> and
   * <tt>count</tt>, e.g <tt>{ facet: 'facet', count: 1 }</tt>.
   */
  getFacetCountsMap: function (property) {
    var counts = [];
    for (var facet in this.manager.response.facet_counts[property][this.field]) {
      counts.push({
        facet: facet,
        count: parseInt(this.manager.response.facet_counts[property][this.field][facet])
      });
    }
    return counts;
  },

  /**
   * Used if the facet counts are represented as an array of two-element arrays.
   *
   * @param {String} property "facet_fields", "facet_dates", or "facet_ranges".
   * @returns {Array} An array of objects with the properties <tt>facet</tt> and
   * <tt>count</tt>, e.g <tt>{ facet: 'facet', count: 1 }</tt>.
   */
  getFacetCountsArrarr: function (property) {
    var counts = [];
    for (var i = 0, l = this.manager.response.facet_counts[property][this.field].length; i < l; i++) {
      counts.push({
        facet: this.manager.response.facet_counts[property][this.field][i][0],
        count: parseInt(this.manager.response.facet_counts[property][this.field][i][1])
      });
    }
    return counts;
  },

  /**
   * Used if the facet counts are represented as a flat array.
   *
   * @param {String} property "facet_fields", "facet_dates", or "facet_ranges".
   * @returns {Array} An array of objects with the properties <tt>facet</tt> and
   * <tt>count</tt>, e.g <tt>{ facet: 'facet', count: 1 }</tt>.
   */
  getFacetCountsFlat: function (property) {
    var counts = [];
    for (var i = 0, l = this.manager.response.facet_counts[property][this.field].length; i < l; i += 2) {
      counts.push({
        facet: this.manager.response.facet_counts[property][this.field][i],
        count: parseInt(this.manager.response.facet_counts[property][this.field][i+1])
      });
    }
    return counts;
  },

  /**
   * @param {String} value The value.
   * @returns {Function} Sends a request to Solr if it successfully adds a
   *   filter query with the given value.
   */
  clickHandler: function (value) {
    var self = this, meth = this.multivalue ? 'add' : 'set';
    return function () {
      if (self[meth].call(self, value)) {
		  // probably want to somehow store this event as a google analytics search, too; look at ALL fq params
			call_google_analytics('fq=fq:'+value);
		  
		  
        self.manager.doRequest(0);
      }
      return false;
    }
  },

  /**
   * @param {String} value The value.
   * @returns {Function} Sends a request to Solr if it successfully removes a
   *   filter query with the given value.
   */
  unclickHandler: function (value) {
    var self = this;
    return function () {
      if (self.remove(value)) {
        self.manager.doRequest(0);
      }
      return false;
    }
  },

  /**
   * @param {String} value The value.
   * @returns {Function} Sends a request to Solr if it successfully adds a
   *   filter query with the given value.
   */
  clickHandlerAlt: function (value, init_values, source) {
    var self = this, meth = this.multivalue ? 'add' : 'set';
	var site = $('#subdomain').text();
	var geofilt_facet = $('#geofilt_facet').text();
	var hashURL =  '' + window.location.hash;
    return function () {
      if (self[meth].call(self, value, init_values)) {
console.log('value is category='+value+'&'+init_values);
//console.log('subdomain is: '+site);
		// probably want to somehow store this event as a google analytics search, too; look at ALL fq params
		call_google_analytics('category="'+value+'"'+init_values);

		// hashURL_impl - see if it occurs in the URL; if NOT, remove it. otherwise, keep it
		if(source == 'tabs'){
			self.manager.store.removeByValue('fq', 'content_type:organization');
			self.manager.store.removeByValue('fq', 'position_type:"Short-term Missions / Volunteer Internship"');
			self.manager.store.removeByValue('fq', 'position_type:"Local Volunteering (in person)"');
			self.manager.store.removeByValue('fq', 'position_type:"Virtual Volunteering (from home)"');
			self.manager.store.removeByValue('fq', 'content_type:opportunity');
		}

		var fq = self.manager.store.values('fq');
console.log('manager store '+self.manager.store.values('fq'));
		for (var i = 0, l = fq.length; i < l; i++) {
			var filter_query=fq[i];
			var filter=''+filter_query;
			var geo_index = filter.indexOf("{!geofilt pt=");
			if(geo_index!=-1){
				$('#geofilt_facet').text(''+fq[i]);
				self.manager.store.removeByValue('fq', fq[i]);
			}
		}
console.log('manager store '+self.manager.store.values('fq'));
		
		
		if(value=='organization'){
			$('#local').removeClass('active');
			$('#virtual').removeClass('active');
			$('#stm').removeClass('active');
			$('#organization').addClass('active');
//('adding organization is: '+value);
			self.manager.store.addByValue('fq', 'content_type:organization');
			self.manager.store.addByValue('fq', geofilt_facet);
	
			$('#srchmethod').val('organization');
		}else{
			if(value=='Virtual Volunteering (from home)'){
				$('#local').removeClass('active');
				$('#stm').removeClass('active');
				$('#organization').removeClass('active');
				$('#virtual').addClass('active');
//('adding opp and virtual is: '+value);
				self.manager.store.addByValue('fq', 'position_type:"Virtual Volunteering (from home)"');
				self.manager.store.addByValue('fq', 'content_type:opportunity');
				
			$('#srchmethod').val('Virtual Volunteering (from home)');
			}else if(value=='Short-term Missions / Volunteer Internship'){
				$('#local').removeClass('active');
				$('#virtual').removeClass('active');
				$('#organization').removeClass('active');
				$('#stm').addClass('active');
//('adding opp and stm is: '+value);
				self.manager.store.addByValue('fq', 'position_type:"Short-term Missions / Volunteer Internship"');
				self.manager.store.addByValue('fq', geofilt_facet);
				self.manager.store.addByValue('fq', 'content_type:opportunity');
//(self.manager.store.values('fq'));
		
				$('#srchmethod').val('Short-term Missions / Volunteer Internship');
				$('#contenttype_heading').text('STM');
				document.getElementById('benefits_offered').style.display='block';
				document.getElementById('trip_length').style.display='block';
				document.getElementById('country_tax').style.display='block';
				document.getElementById('region').style.display='block';
				$('#facet_benefits_offered').addClass('filter handle expanded');
				$('#facet_trip_length').addClass('filter handle expanded');
				$('#facet_country_tax').addClass('filter handle expanded');
				$('#facet_region').addClass('filter handle expanded');
			}else if(value=='Local Volunteering (in person)'){
				$('#virtual').removeClass('active');
				$('#stm').removeClass('active');
				$('#organization').removeClass('active');
				$('#local').addClass('active');
//('adding opp and local is: '+value);
				self.manager.store.addByValue('fq', 'content_type:opportunity');
				self.manager.store.addByValue('fq', geofilt_facet);
				self.manager.store.addByValue('fq', 'position_type:"Local Volunteering (in person)"');
				
				$('#srchmethod').val('Local Volunteering (in person)');
			}else{// if(value=='Local Volunteering (in person)'){
//				$('#virtual').removeClass('active');
//				$('#stm').removeClass('active');
//				$('#organization').removeClass('active');
//				$('#local').addClass('active');
				
//console.log('adding facet category is: '+value);
//				self.manager.store.addByValue('fq', 'content_type:opportunity');
				self.manager.store.addByValue('fq', geofilt_facet);
				
//				$('#srchmethod').val('Local Volunteering (in person)');
			}
		}
			 
        self.manager.doRequest(0);
      }
      return false;
    }
  },

  /**
   * @param {String} value The value.
   * @returns {Function} Sends a request to Solr if it successfully removes a
   *   filter query with the given value.
   */
  unclickHandlerAlt: function (value, init_values) {
    var self = this;
    return function () {
      if (self.remove(value)) {
        self.manager.doRequest(0);
      }
      return false;
    }
  },

  /**
   * @param {String} value The facet value.
   * @param {Boolean} exclude Whether to exclude this fq parameter value.
   * @returns {String} An fq parameter value.
   */
  fq: function (value, exclude) {
    return (exclude ? '-' : '') + this.field + ':' + AjaxSolr.Parameter.escapeValue(value);
  }
});

