/**
 * AjaxSearchHandler
 *
 * @author Boz
 * @classDescription Handles ajax search.
 * @params
 *
 *  url - the url that is retreived for the partial page refresh
 *  stage - the HTML element that will be updated with new data
 *
 * @css
 *
 * .filter - attached to checkboxes used as filters 
 * .searchByText - attached to form used for text search 
 * .searchByPage - attached to links <a> used for pagination i.e. <a class="searchByPage>1</a>
 * .pre - attached to pagination links used to get the previous page
 * .nxt - attached to pagination links used to get the next page
 * #searchTerm - input used for search by text
 * .sortable - attached to elements used to initiat sorting
 * .resulthover - attached to result rows on mouseover , removed on mouse out
 *
 * Assumptions:
 *
 **/

mdp.app.AjaxSearchHandler = function(target,stage){
    /* ---[ CLASS VARIABLES ]--- */
    this.fx = new Fx.Style($("results"),"opacity",{duration:200});
    this.stage = stage;
    var self = this;
    var initMatchingCategories = 2;
    var windowOffsetY = 250;
    var sendReport = true;
    var reportFilter = null;
    var reportFilterVal = null;
    var enableSearch = false;

    /* ---[ CONSTRUCTOR ]--- */
    function init(){

        /* initialize variables */
        mdp.filterInput = {};
        if(typeof(mdp.search) == 'object'){
            mdp.search.sortBy = "";
            if(mdp.search.page == ""){mdp.search.page = 1;}
        }

        /* set flag to search if there is an initial hash value */
        if(window.location.hash != ""){
            enableSearch = true;
        }
        else{
            search();
        }

        /* customize the instance of HistoryManager */
        HistoryManager.initialize({
            stateSeparator:"&",
            onStateChange:function(){
                if(enableSearch){
                    report();
                    search();
                }
            }
        });

        /* initialization code */
        setupEventListeners();

        enableSearch = true;
    }

    /* ---[ PUBLIC METHODS ]--- */


    /* ---[ PRIVATE METHODS ]--- */
    function search(hashParams){
        self.fx.set(0);
        new Ajax(target + "?" + buildQuery(hashParams),{
            evalScripts:true,
            update:stage,
            onComplete:handleResults,
            onStart:function(){ self.fx.set(0); }
        }).request();
    }

    function buildQuery(hashParams){
        var obj = $merge(mdp.search,mdp.filterInput);
        if(hashParams != null){
            obj = $merge(obj,hashParams);
        }
        return Object.toQueryString(obj);
    }

    function handleResults(){

        /* Check the # of results */
        if(mdp.pagination.totalResults >0){
            /* Re-attach rollovers */
            attachRollOvers();

            /* Update search header */
            displayObj(mdp.search);

            /* Update pagination */
            updatePagination();
        }

        /* Update filters */
        updateFilters();

        /* Update suggestions */
        updateSuggestions();

        /* Ease in animation */
        self.fx.start(0,1);

        /* adjust page height */
        if(window.getScrollTop() > windowOffsetY){
            window.scrollTo(0,windowOffsetY);
        }        
      
    }

    function updateFilters(){
        for(var i=0; i<mdp.filterOutput.length; i++){
            var li = $(mdp.filterOutput[i].facetField);
            if(li != null){
                $(mdp.filterOutput[i].facetField).getNext().setHTML("(" + mdp.filterOutput[i].numResults + ")");
            }
        }
    }

    function updatePagination(){
        /* update display items */
        displayObj(mdp.pagination);

        /* iterate through all pagination instances */
        $$(".pagination").each(function(pagination){

            /* update pages numbers */          
            $ES(".searchByPage",pagination).each(function(pagelink,index){
                pagelink.setHTML(mdp.pagination.listOfPages[index]);
            });

            /* update current pages style */
            $$(".pages").each(function(el){
                el.empty();
                mdp.pagination.listOfPages.each(function(item,index){
                    var a = new Element("a",{
                        "class":"pointer searchByPage",
                        "events":{
                            "click":handleSearchByPage
                        }
                    }).setHTML(item).injectInside(el);
                    if(item == parseInt(mdp.search.page,10)){
                        a.addClass("unlink");
                    }
                    if(index != mdp.pagination.listOfPages.length-1){
                        el.appendText(" | ");
                    }
                });
            });

            /* enable/disable links */
            $$(".pre").each(function(link){
                if(mdp.pagination.hasPrev){
                    link.removeClass("disable");
                }else{
                    link.addClass("disable");
                }
            });

            $$(".nxt").each(function(link){
                if(mdp.pagination.hasNext){
                    link.removeClass("disable");
                }else{
                    link.addClass("disable");
                }
            });

        });
    }

    function handleSearchByPage(){
        if(!$(this).hasClass("unlink")){
            var pageNum = $(this).getText();
            page([pageNum + ""]);
            HistoryManager.setValue("page",0,pageNum);
        }
    }

    function displayObj(obj){
        /* iterate obj */
        var name;
        for(name in obj){
            if(obj.hasOwnProperty(name)){
                var el = $(name + "Display");
                if(el != null){
                    el.setHTML(obj[name]);
                }else{
                    el = $$("." + name + "Display");
                    if(el != null && el.length > 0){
                        el.setHTML(obj[name]);
                    }
                }
            }
        }
    }

    function attachRollOvers(){
        $$("#" + self.stage.id + " tr").addEvent("mouseover", function(){ $(this).addClass("resulthover"); });
        $$("#" + self.stage.id + " tr").addEvent("mouseout", function(){ $(this).removeClass("resulthover"); });
    }

    function updateSuggestions(){
        var dymd;    
        var dymc = $("didYouMeanContainer");
        if(dymc != null){
            if(typeof(mdp.suggestions) == 'object' && typeof(mdp.suggestions.suggestions) == 'object'){
                if(mdp.suggestions.suggestions.length > 0){
                    dymc.removeClass("hide");
                    dymd = $("didYouMeanDisplay");
                    dymd.empty();
                    for(var i=0; i<mdp.suggestions.suggestions.length; i++){
                        new Element("a",{"href":"/search/?searchTerm="+mdp.suggestions.suggestions[i]}).setHTML(mdp.suggestions.suggestions[i]).injectInside(dymd);
                    }
                }
            }
            else{
               dymc.addClass("hide");
            }
        }
    }

    function updateCategories(){
        if(mdp.categories.length > 0){
            var resultcategories = $("resultcategories");
            var categoriesDisplay = $("categoriesDisplay");
            var seemorecatlink = $("seemorecatlink");

            if(mdp.categories.length>initMatchingCategories){
                $("seemorecatlink").removeClass("hide");
            }
            resultcategories.removeClass("hide");
            var offset = resultcategories.getFirst().getSize().size.y;
            var height = $E("#resultcategories a").getSize().size.y;
            var startHeight = (height * initMatchingCategories) + offset;

            if(mdp.categories.length>initMatchingCategories){
                resultcategories.setStyle("height",startHeight+"px");
            }

            for(var i=0; i<mdp.categories.length; i++){
                var div = new Element("div");
                new Element("a",{
                    "href":mdp.categories[i].virtualPath
                }).setHTML(mdp.categories[i].name).injectInside(div);
                div.injectInside(categoriesDisplay);
            }

        }

    }

    function report(){

        if(typeof(s) == "object"){
            var pagename = "";

            /* build reporting string */
            if(reportFilter != null && reportFilterVal != null){
                pagename = "Search:Results:"+ mdp.search.page + ":" + reportFilterVal + ":" + reportFilter;
            }else{
                pagename = "Search:Results:"+ mdp.search.page;
            }

            /* set omniture values */
            s.eVar9 = pagename;
            if(typeof(sendPageEvent) == 'function'){
                sendPageEvent('',pagename);
            }
        }
    }

    function toggleCategories(){
        var resultcategories = $("resultcategories");
        var seemorecatlink = $(this);
        var offset = resultcategories.getFirst().getSize().size.y;
        var height = $E("#resultcategories a").getSize().size.y;
        var startHeight = (height * initMatchingCategories) + offset;
        var endHeight = (height * mdp.categories.length) + offset;
        if(resultcategories.getSize().size.y == startHeight){
            new Fx.Style(resultcategories,"height").start(startHeight,endHeight);
            seemorecatlink.setHTML("Hide Categories");
        }else{
            new Fx.Style(resultcategories,"height").start(endHeight,startHeight);
            seemorecatlink.setHTML("See More Categories");
        }
    }

    function filterByPartner(args){
        var id = args[0];
        $(id).setProperty("checked",(args[1] == "true")?"checked":"");
        mdp.filterInput[id] = (args[1] == "true")? true: false;

        sendReport = true;
        if(args[1] == "true"){
            reportFilter = id;
            reportFilterVal = "filter";
        }else{
            reportFilter = id;
            reportFilterVal = "remove";
        }
    }

    function sortBy(params){
        if(params[0] == "default"){
            $$(".sortable").removeClass("sorted");
            mdp.search.sortBy="";
            return;
        }
        var el = $(params[0]);
        var sorted = $E(".sorted",$("sort"));
        var parent = el.getParent();

        if(sorted != null){ sorted.removeClass("sorted");}
        el.addClass("sorted");
        mdp.search.sortBy = el.id;

        sendReport = false;
    }

    function sortDescending(params){
        var el = $(mdp.search.sortBy);
        if(el != null){
            var parent = el.getParent();

            if(params[0] == "true"){
                mdp.search.sortDescending = true;
                parent.removeClass("sortDescending");
            }
            else{
                mdp.search.sortDescending = null;
                parent.addClass("sortDescending");
            }
        }
        sendReport = false;
    }

    function page(params){
        mdp.search.page = parseInt(params[0],10);
        sendReport = true;
        reportFilter = null;
        reportFilterVal = null;
    }

    /* ---[ EVENT LISTENERS ]--- */
    function setupEventListeners(){

        $$(".filter").each(function(el){

            /* setup states for each filter */
            HistoryManager.register(el.id,[el.id,"false"],
                filterByPartner,
                function(params){
                    return params[0] + "=" + params[1];
                },
                '('+ el.id +')=(true|false)'
            );

            /* set state on click */
            el.addEvent("click",function(){
                var checkbox = $(this);
                var id = checkbox.id;
                var value = (checkbox.getValue() == "on")?"true":"false";

                page(["1"]);
                filterByPartner([id,value]);

                HistoryManager.setValues(id, [id,value]);
                HistoryManager.setValue("page",0,"1");
            });

            /* populate filterInput object */
            mdp.filterInput[el.id] = (el.getValue() == "on")? true:false;
        });

        HistoryManager.register("page",["1"],
            page,
            function(params){
                return "page=" + params[0];
            },
            /page=(\d+)/
        );

        $$(".searchByPage").addEvent("click",handleSearchByPage);

        $$(".pre").addEvent("click",function(){
            if(mdp.pagination.hasPrev){
                page([parseInt(mdp.search.page,10) - 1 + ""]);
                HistoryManager.setValue("page",0,mdp.search.page);
            }
        });

        $$(".nxt").addEvent("click",function(){
            if(mdp.pagination.hasNext){
                page([parseInt(mdp.search.page,10) + 1 + ""]);
                HistoryManager.setValue("page",0,mdp.search.page);
            }
        });

        HistoryManager.register("sortBy",["default"],
            sortBy,
            function(params){
                return "sortBy=" + params[0];
            },
            "sortBy=" + '(name|prepTime|totalTime|ratingAvg)'
        );

        HistoryManager.register("sortDescending",["false"],
            sortDescending,
            function(params){
                return "sortDescending=" + params[0];
            },
            "sortDescending=" + '(true|false)'
        );

        $$(".sortable").addEvent("click",function(e){
            new Event(e).preventDefault();
            var el = $(this);
            var sorted = $E(".sorted",$("sort"));
            var parent = el.getParent();
           
            /* toggle asc/desc */
            if(parent.hasClass("sortDescending")){
                if(mdp.search.sortBy != "" && mdp.search.sortBy == el.id){
                    sortDescending(["true"]);
                    HistoryManager.setValue("sortDescending",0,"true");
                }else{
                    sortBy([el.id]);
                    HistoryManager.setValue("sortBy",0,el.id);
                }
            }
            else{
                if(mdp.search.sortBy != "" && mdp.search.sortBy == el.id){
                    sortDescending(["false"]);
                    HistoryManager.setValue("sortDescending",0,"false");
                }else{
                    sortBy([el.id]);
                    HistoryManager.setValue("sortBy",0,el.id);
                }
            }
        });

        var seemorecatlink = $("seemorecatlink");
        if(seemorecatlink != null){
            $("seemorecatlink").addEvent("click",toggleCategories);
        }

        attachRollOvers();

        HistoryManager.start();

    }

    /* ---[ RUN ]--- */
    init();
};
