(function($){
	var solrSearch = function(element, options) {		
		element = $(element);
		var obj = this;
		var template_str = '';
		var reg_exp_match = /\$\{(\w+)\}/g;
		var matches = [];
		var num_matches = 0;
		
		var settings = $.extend({
			query_url: '', 
			query_sort: 'score+desc',
			query: {}, // format should be {"field_name":"field_value","field_name":"field_value"} - send multiple values for an OR statement by using | to separate value options in the field_value
			facets: {items:[]}, // format should be {items:[{name:'facet-name',dd:1,top_text:'Shop By Size']}
			add_facets: {items:[]}, // format shoulg be {items:[{name:'facet-name',top_text:'Shop By Size',ops:[{'option_name':'option_val'}]]}
			facets_to: '.cat_nav',
			rt_fields: '', // comma delimited list of fields to get back from solr if there is a need to minimize response
			line_clear_code: '<div class="clear"><!-- --></div>',
			paging_prev_code: 'Previous',
			paging_next_code: 'Next',
			view_all_code: 'View All',
			paging_to: '.pages',
			product_listing: '#product_list',
			item_node_html: '/skin/frontend/default/lrg/js/item_template.jst',
			image_not_found: '/skin/frontend/default/lrg/images/no_image_cat.jpg',
			item_trans: {}, // format should be {'item_name':'p|i','another_item_name':'p|i'}
			suggestions: false,
			show_per_page: {},  // format should be {show_in:'.class_name',top_text:'Sort By',top_value:16,label:'',ops:[16,32,100]} if blank, nothing will be shown
			show_sort_by: {},  // format should be {show_in:'.class_name',top_text:'Sort By',top_value:'score+desc',label:'',ops:{'price':'price+asc','name':'name+asc'}} if blank, nothing will be shown
			total_items: 0,
			total_pages: 0,
			offset: 0,  
			per_page: 20,
			cur_page: 1,
			results_per_line: 4,
			reset_facet_dd: 1,
			success: null, // name of the function to send data results of the solr query back to. enables functions to be written to supplement functionality that's not built in
			not_found_response: '<p>No Products Found</p>'
		}, options || {})
		
		this.load_page = function() {
			$.ajax({type:'get',
					async:false,
					url:settings.item_node_html,
					success: function(data) {
						template_str = data;
					}
			});
			matches = template_str.match(reg_exp_match);
			num_matches = matches.length;
			for (var i = 0; i < num_matches; i++) {
				matches[i] = matches[i].replace('${','').replace('}','');
			}
				
			obj.run_search();
		}
		
		this.run_search = function() {
			$.getJSON(build_query(),
				function(data) {
					var item_code = '';
					var cnt = 1;
					if (data.response.numFound > 0) {
						
						if (settings.reset_facet_dd == 1) {
							add_facet_dropdowns(data.facet_counts)
						}
						
						$.each(
							data.response.docs,
							function(i, item) {
								item_code += get_product_node_html(item);
								if (cnt == settings.results_per_line) {
									item_code += settings.line_clear_code;
									cnt = 0;
								}
								cnt++;
							});
						
						settings.total_items = data.response.numFound;
						settings.total_pages = Math.ceil(settings.total_items / settings.per_page);
						
						$(settings.facets_to).show();
						$(settings.product_listing).html(item_code);
						
						page_links();
						
						settings.reset_facet_dd = 0;

						if ($j.isFunction(settings.success)) {
							settings.success.call(null,data);
						}
						
					} else {
						if (settings.reset_facet_dd == 1) {
							$(settings.facets_to).hide();
						}

						$(settings.product_listing).html(settings.not_found_response);
						
						page_links();
						
						settings.reset_facet_dd = 0;
					}					
				});
		}
		
		this.go_to_page = function(page_num) {
			settings.cur_page = parseFloat(page_num);
			obj.run_search();
		}
		
		this.view_all = function() {
                        
			settings.per_page = settings.total_items;
			settings.cur_page = 1;
			obj.run_search();
		};
		
		this.dropdown_select = function() {
			settings.cur_page = 1;
			obj.run_search();
		}
		
		var add_facet_dropdowns = function(facets) {
			$(settings.facets_to).html('');
		
			if (obj.isdefined(facets)) {
				var fields = facets.facet_fields;
				
				if (settings.facets.items.length > 0) {
					var facet_items = settings.facets.items;
					var f_length = facet_items.length;
					for (var i = 0; i < f_length; i++) {
						if (facet_items[i].dd == 1) {
							var facet_name = facet_items[i].name;
							var item_length = fields[facet_name].length;
							$(settings.facets_to).append('<select id="' + facet_name + '" class="dd_select select"></select>');
							$('#' + facet_name).append('<option value="0">' + facet_items[i].top_text + '</option>');
							for (var j = 0; j < item_length; j++) {
								if (fields[facet_name][j+1] > 0) { //check count of facet
									$('#' + facet_name).append('<option value="' + fields[facet_name][j] + '">' + fields[facet_name][j] + '</option>');
								}
								j++; // skip over the "count" of products per each item in facet
							}
						}
					}				
				}
			}
			
			if (settings.add_facets.items.length > 0) {
				var facet_items = settings.add_facets.items;
				var f_length = facet_items.length;
				for (var i = 0; i < f_length; i++) {
					var facet_name = facet_items[i].name;
					$(settings.facets_to).append('<select id="' + facet_name + '" class="dd_select select"></select>');
					$('#' + facet_name).append('<option value="0">' + facet_items[i].top_text + '</option>');
					$.each(facet_items[i].ops, function(key,value) {
						$('#' + facet_name).append('<option value="' + value + '">' + key + '</option>');
					});
				}				
			}
			
			if (obj.isdefined(settings.show_per_page.show_in)) {
				var ops = settings.show_per_page.ops;
				if (obj.isdefined(settings.show_per_page.label)) {
					$(settings.show_per_page.show_in).append(settings.show_per_page.label);
				}
				$(settings.show_per_page.show_in).append('<select id="per_page_select" class="spec_select select"></select>');
				if (obj.isdefined(settings.show_per_page.top_text)) {
					$('#per_page_select').append('<option value="' + settings.show_per_page.top_value + '">' + settings.show_per_page.top_text + '</option>');
				}
				$.each(ops, function(key,value) {
					$('#per_page_select').append('<option value="' + value + '">' + value + '</option>');
				});
			}
			
			if (obj.isdefined(settings.show_sort_by.show_in)) {
				var ops = settings.show_sort_by.ops;
				if (obj.isdefined(settings.show_sort_by.label)) {
					$(settings.show_sort_by.show_in).append(settings.show_sort_by.label);
				}
				$(settings.show_sort_by.show_in).append('<select id="sort_by_select" class="spec_select select"></select>');
				if (obj.isdefined(settings.show_sort_by.top_text)) {
					$('#sort_by_select').append('<option value="' + settings.show_sort_by.top_value + '">' + settings.show_sort_by.top_text + '</option>');
				}
				$.each(ops, function(key,value) {
					$('#sort_by_select').append('<option value="' + value + '">' + key + '</option>');
				});
			}
			
			$('.dd_select').change(obj.dropdown_select);
			$('.spec_select').change(obj.dropdown_select);
		}
		
		this.isdefined = function(variable) {
			return (typeof(variable) !== "undefined") ? true : false;
		}
		
		this.format_price = function(price) {
			price = price.toFixed(2) + '';
			x = price.split('.');
			x1 = x[0];
			x2 = x.length > 1 ? '.' + x[1] : '';
			var rgx = /(\d+)(\d{3})/;
			while (rgx.test(x1)) {
				x1 = x1.replace(rgx, '$1' + ',' + '$2');
			}
			return '$' + x1 + x2;
		}
		
		this.empty_image = function(image) {
			if (obj.isdefined(image)) {
				return image;
			}
			
			return settings.image_not_found;
		}
		
		var get_product_node_html = function(item) {			
			var html_code = template_str;		
			var output;
			//link check for parts_pdf_varchar_attribute attribute
			item['pdf_link'] = '';	
			if (obj.isdefined(item['parts_pdf_varchar_attribute'])) {
				item['pdf_link'] = '<div class="fl"><a class="pdf" target="new" href="/media/model_pdfs/' + item['parts_pdf_varchar_attribute'] + '">Download Owners Manual.pdf</a></div>';
			}
			
			var url = '';
			for (var i = 0; i < num_matches; i++) {
				output = item[matches[i]];
				
				if (matches[i] == 'product_url_stored_text_attribute') {
					url = item['product_url_stored_text_attribute'].toString();
					url = url.replace(/SID=[a-z0-9A-Z]+[\&]*/g,'');
					if (url.indexOf('?') == url.length-1) {
						url = url.substring(0,url.length-1);
					}				
					output = url;
				}
				
				if (obj.isdefined(settings.item_trans[matches[i]])) {
					if (settings.item_trans[matches[i]] == 'p') output = obj.format_price(item[matches[i]]);
					else if (settings.item_trans[matches[i]] == 'i') output = obj.empty_image(item[matches[i]]);
				}
				
				html_code = html_code.replace('${'+matches[i]+'}',output);
			}

			return html_code;
		}
		
		var build_query = function() {
			if (obj.isdefined(settings.show_per_page.show_in) && $('#per_page_select').length > 0) {                             
				settings.per_page = $('#per_page_select').val();
			}
			
			if (obj.isdefined(settings.show_sort_by.show_in) && $('#sort_by_select').length > 0) {
				settings.query_sort = $('#sort_by_select').val();
			}
			
			settings.offset = (settings.cur_page - 1) * settings.per_page;
			
			var query = settings.query_url;
			
			if (settings.query_sort.length > 0) {
				query += '&sort=' + settings.query_sort;
			}
			
			query += '&start=' + settings.offset + '&rows=' + settings.per_page;
			
			var empty_search = true;
			query += '&q=';
			
			$.each(settings.query, function(key,value) {
				if (value.toString().indexOf('|') > -1) {
					query += (!empty_search ? '+AND+' : '') + '(';
					var search_options = value.split('|');
					for (var so_cnt = 0; so_cnt < search_options.length; so_cnt ++) {
						query += (so_cnt > 0 ? '+OR+' : '') + key + ':' + search_options[so_cnt];
					}
					query += ')';
				} else if (value.toString().indexOf('_') > -1) {
					query += (!empty_search ? '+AND+' : '') + '(';
					var search_options = value.split('_');
					for (var so_cnt = 0; so_cnt < search_options.length; so_cnt ++) {
						query += (so_cnt > 0 ? '+AND+' : '') + key + ':' + search_options[so_cnt];
					}
					query += ')';
				} else {
					query += (!empty_search ? '+AND+' : '') + key + ':' + value;
				}
				empty_search = false;
			});	
			
			$('.dd_select').each(function() {
				if ($(this).val() != '0') {
					query += (!empty_search ? '+AND+' : '') + $(this).attr('id') + ':' + $(this).val();
					empty_search = false;
				}
			});
				
			if (empty_search) {
				query += '*:*';
			}
			
			if (settings.facets.items.length > 0) {
				var f_length = settings.facets.items.length;
				//query += '&facet=true';
				query += '&facet=';
				for (var i = 0; i < f_length; i++) {
					//query += '&facet.field=' + settings.facets.items[i].name;
					query += settings.facets.items[i].name;
					if (i + 1 < f_length) query += '|';
				}
			}
			
			if (settings.rt_fields.length > 0) {
				query += '&fl=' + settings.rt_fields;
			}
			
			return query;
		};
		
		var page_links = function () {
			var page_code = '';
			if (settings.total_items > 0) {
				var count_start = 1, count_end = 5, print_end = true;
			
				if (settings.total_pages > 1 && settings.cur_page > 1) {
					page_code += '<span class="prev_next_nav"><a href="#" class="paging_link" id="prev_' + (settings.cur_page-1).toString() + '">' + settings.paging_prev_code + '</a></span>';
				} else {
					page_code += '<span class="prev_next_nav">&nbsp;</span>';
				}
				
				if (settings.cur_page > 5) {
					page_code += '<span class="pl"><a href="#" class="paging_link" id="pl_1">1</a></span> <span class=\"dots\">...</span> ';
					count_start = settings.cur_page - 2;
					count_end = settings.cur_page + 2;
				}
				
				for (var i = count_start; i <= count_end; i++) {
					if (i == settings.cur_page) {
						page_code += '<span class="pl"><a class="current">' + i + '</a></span> ';
					} else if (i <= settings.total_pages) {
						page_code += '<span class="pl"><a href="#" class="paging_link" id="pl_' + i + '">' + i + '</a></span> ';
					}
				}
				
				if (settings.total_pages - settings.cur_page > 3 && settings.total_pages > 5) {
					page_code += ' <span class="dots">...</span> <span><a href="#" class="paging_link" id="pl_' + settings.total_pages + '">' + settings.total_pages + '</a></span> ';
				}
			
				if (settings.cur_page < settings.total_pages) {
					page_code += '<span class="prev_next_nav"><a href="#" class="paging_link" id="next_' + (settings.cur_page+1).toString() + '">' + settings.paging_next_code + '</a></span>';
				} else {
					page_code += '<span class="prev_next_nav">&nbsp;</span>';
				}
				
				if (settings.total_pages > 1 && settings.view_all_code.length > 0) {
					page_code += '<span><a href="#" class="view_all_link">' + settings.view_all_code + '</a></span>';
				}
			}
			
			$(settings.paging_to).html(page_code);
			
			$('.paging_link').click(function(e) {
				e.preventDefault();
				var page_num = $(this).attr('id').split('_');
				obj.go_to_page(page_num[1]);
			});
			
			$('.view_all_link').click(function(e) {
				e.preventDefault();
				obj.view_all();
			});
		}
   };

   $.fn.solrsearch = function(options)
   {
       return this.each(function() {
           var element = $(this);
          
           // Return early if this element already has a plugin instance
           if (element.data('solrsearch')) return;

           // pass options to plugin constructor
           var solrsearch = new solrSearch(this, options);

           // Store plugin object in this element's data
           element.data('solrsearch', solrsearch);
       });
   };
})(jQuery);
