/*
    Public searcher object, performing ajax searches on a page.
    Rendered customfields should can fire it's search method, their inputs
    will sent if they're placed inside the searchers options.form object.

    They can also register callbacks to be called after the search is done.
*/



/* FIXME: depracated! remove when all code is converted to use search callbacks! */
var Search = {
    last_result: null,
    query_string_dict: null
};

(function($){
 $.searcher = (function() {
    /* internal functions */
    var S = {
        // curtains indicating search in progress (called on results_target)
        loader: null,
        loader_done: null,

        options: {},
        // holds extra params set by ajax links
        extra: {},

        // holds an object of callbacks for each widgetid
        callbacks: {},

        // Connects click events for all ajax links to fire a search with their parameter,
        //FIXME: turning off extra values! all ajax links cause a get with their url.
        //       we need some way of marking the extra param calls
        enable_ajax_links: function(target) {
            $(S.options.links_selector, target).click(function() {
                var href = $(this).attr('href');
                //if (href.search(/\?/i)>=0) {
                //    S.search_extra(href.split('?')[1].split('&')[0], true);
                //} else {
                    S.ajax_search("", href);
                //}
                return false;
            });
        },

        // Ads an extra hidden input to the search form
        setextra: function(fieldname, value) {
             // FIXME: remove this after persistent ajax options are correctly handled
            if (fieldname=='page') return;

            var f = S.extra[fieldname];
            if (!f) f = S.extra[fieldname] = S.form.find('input[name='+fieldname+']');
            if (!f.length) {
                f = S.extra[fieldname] = $('<input type="hidden" name="'+fieldname+'"/>').appendTo(S.form);
                }
            f.val(value);
        },

        // Proxies the actual search. if the persistent param is set the value will
        // be added to the form as hidden inputs so it's kept between calls.
        // this should only be used for weird exceptions (like layout setting on onet).
        // Real search params should be encoded in links generated in the results!
        search_extra: function(extra, persistent) {
            if ((typeof(extra)=='string')&& persistent) {
                S.setextra(extra.split('=')[0], extra.split('=')[1]);
            }
            S.ajax_search(extra);
        },

        // The main callback after the seach is done.
        callback: function(data) {
            var cbs, widget; //[mj]multiple variable declaration sucks a little bit :-)
            if (S._current_url != window.location.pathname) {
                window.location.hash = 'search-url:'+S._current_url;
            } else {
                window.location.hash = ''; // first page case
            }
            for (widget in S.callbacks) {
                cbs = S.callbacks[widget];
                if (cbs.checker!==true && !cbs.checker.length) {//widget is not persistant and dont have any nodes
                    // no longer with us! 
                    delete S.callbacks[widget];
                } else {
                    cbs.before && cbs.before(data, {}, S.options.results_target);
                }
            }

           // insert results into correct places
            S.options.results_target.html(data.results);
            S.last_result = data;

            S.enable_ajax_links(S.options.results_target);
            S.loader_done && S.loader_done(S.indicator);
            S.indicator = null;

            // CALLBACKS!
            
            for (widget in S.callbacks) {
                cbs = S.callbacks[widget];
                cbs.after && cbs.after(data, {}, S.options.results_target);
            }


            // FIXME: callback set by some session plugin?
            $('#sessionMessages').html(data.session_messages);


            // FIXME: hack until we convert everything using this to use callbacks
            Search.last_result = S.last_result;
        },

        // Performs the actual search.
        // Call all registered callbacks when the results are back.
        ajax_search: function(extra, fullurl) {
            // FIXME: hack, will get rid of it later
            if (window.sensimap&&sensimap.geocoding) { return false; }

            if (S.indicator) { return false; }
            S.indicator = S.loader && S.loader(S.options.results_target, true);
            var url;
            if (fullurl) {
                url = fullurl;
            } else {
                url = S.options.url+S.form.serialize();
                if (extra) { url += '&'+ extra; }
            }

            // FIXME: possibly add as a callback? results data['search_path'] holds
            // the complete and seo friendly url, maybe it's better?
            if(typeof(pageTracker) != 'undefined')
            {
                // pageTracker is not in this file, so probably it's sometimes created by some other scripts,
                // but sometimes does not mean always, thus i've added typeof checking if it's actually created
                pageTracker._trackPageview(url)
            }
            S._current_url = url;
            // ensure response is JSON and not a HTML cached by browser
            url += ((url.indexOf('?') == -1) ? '?' : '&') + 'no_b=' + Math.random();
            $.getJSON(url, S.callback);
            return false;
        }
    };
    return {
        init: function (options) {
            S.options = $.extend({
                // Default options to be overridden at initialization.
                url: '/search/advanced/?',
                form: $('#searchAdvancedForm'),
                results_target: $('.adverts_list'),
                links_selector: '.searchnav a'
                }, options);

            S.form = S.options.form; // shortcut
            S.indicator = null;
            S.options.form.submit(S.ajax_search); // init searcher only ONCE because of that!
            S.enable_ajax_links(); // for ALL links on the page



            //FIXME: this should be removed once we agree that's something we need for
            //every page and it will always be included, like popup code
            if (!window.loader) {
                S.loader = function(t) { return 1; };
                S.loader_done = function(l) {};
                }
                else S.loader = window.loader 
            // FIXME: DEPRECATED: category change functionality, can be implemented outside of search!
            var category_select = $('#searchAdvancedForm #search_select_category');
            var advanced_form = $('#advanced_search_ajax_form_id');
            category_select.change(function() {
                $.get( "/search/form/" + category_select.val() + "/", { 'output' : 'inner_html' },
                    function(data) { advanced_form.html(data); });
                }).change();

        },

        /** Add a set of callbacks coresponding to a given field.
         * callbacks are hold under field keys so they can be replace (if a searchable customfield
         * widget reloads after category change it will override old callbacks)
         * 
         * @param: {Object} callbacks:
         * @param: {Function} callbacks.after - called after search is done and results are injected to DOM. 
         *      Arguments passed:
         *          results_data - the result object returned by the app
         *          cluster_counts - counts extracted for the given field_name
         *          results_target - for convenience (it is returned by add callback, so it can be stored)
         * @param {Function} callbacks.before - called after search is done but before results are injected to DOM
         * @param {Bool} [dontCheck] - if true wigdet is persistant, default undefined (false)
         */
        addcallbacks: function(widgetid, callbacks, dontCheck) {
            var widget = {}
            if(!dontCheck) {//if widget is checkable 
                var classname = widgetid+'_cls';
                $('#'+widgetid).addClass(classname);
                widget.checker = $('.'+classname);
            } else {
                widget.checker = true;
            }
            widget.after  = callbacks.after;
            widget.before = callbacks.before;

            S.callbacks[widgetid] = widget;
            return S.options.results_target;
        },

        // FIXME: i don't know how to handle this... we should remove callbacks for widget's that are gone
        // (after category change for example).
        // for now after each search call the list of callbacks is checked if the objects actually exists
//        removecallbacks: function(widgetid) {
//            delete S.callbacks[widgetid];
//        },

        get_params: function() {
            return S.form.serialize();
        },

        // Public search interface
        run: function() {
            S.ajax_search.apply(this, arguments);
        },

        get_current_url: function() {
            return S._current_url;
        },

        _debug: function() { console.log(S); } // you can look at the internal state, but don't
    };


    })();
})(jQuery);




