(function ($) {
    $.fn.search = function (settings) {
        debug(this);

        var config = $.extend({}, $.fn.search.defaults, settings);

        if (settings) $.extend(config, settings);

        this.each(function () {
            $this = $(this);

            var o = $.meta ? $.extend({}, config, $this.data()) : config;

            var searchable = $(this).find(".searchable");

            debug(searchable);
			
			var haveResults = false;
			$(this).find(".no-results").remove();

            searchable.each(function () {
                var text = $(this).text();
                if (o.searchTerm == "") return;

                var re = new RegExp(o.searchTerm, "gi");

                $.fn.search.resetElement($(this));

                if (re.test(text)) {
					haveResults = true;
                    $.fn.search.show($(this));
                    $.fn.search.highlight($(this), o);
                    if (o.callback) {
                        o.callback($(this));
                    }
                } else {
                    $.fn.search.hide($(this));
                }
            });
			
			if(!haveResults) {
				$(this).append('<div class="no-results">No search results found</div>');
			}
        });

        return this;
    };

    $.fn.reset = function (settings) {
        this.each(function () {
            $this = $(this);

            var config = $.extend({}, null, settings);

            $.fn.search.resetElement($this);
			$(this).find(".no-results").remove();

            var searchable = $(this).find(".searchable");
            searchable.each(function () {
                $.fn.search.show($(this));
                if (config.resetCallback) {
                    config.resetCallback($(this));
                }
            });
        });
    }

    $.fn.search.defaults = {
        hightlight: true,
        highlightClass: 'red'
    };

    function debug($obj) {
        if (window.console && window.console.log) {
            window.console.log('search item count: ' + $obj.size());
        }
    };

    function debug_string($str) {
        if (window.console && window.console.log) {
            window.console.log($str);
        }
    };

    $.fn.search.hide = function (element) {
        element.hide();
    };

    $.fn.search.show = function (element) {
        element.show();
    };

    $.fn.search.highlight = function (element, config) {
        if (!config.hightlight) return;

        var html = element.html();
        html = html.replace(new RegExp(config.searchTerm, "gi"), '<span class="search-highlight ' + config.highlightClass + '">' + config.searchTerm + '</span>');
        element.html(html);
    };

    $.fn.search.resetElement = function (element) {
        var html = element.html();
        html = html.replace(new RegExp('(<span class="search-highlight)(.*?)(">)(.*?)(<\/span>)', "gi"), '$4');
        element.html(html);
    };

})(jQuery);
