/*
 *   Class: AjaxResults 
 *   Dependencies: s1JS.Jobs
 */

s1JS.Jobs.AjaxResults = Base.extend({
    
    /***************************
     *
     *   INSTANCE VARIABLES
     *
     */     
    
    // a jQuery object pointing to our results container
    $scope: null,
    base_URL: 'http://' + document.location.host + '/search/results.js?',
    do_vacancy_links: false,
    page_data: {},     
    results_container: 'search-results',       
    setup_complete: false,  
       
    template_data: 
    {
        loader: 'left-col-loading',
        template: '/job/results-body.tmpl',
        target: 'search-results-listings'
    },    
    
    /* **************************
     *
     *   INITIALISATION FUNCTIONS    
     *
     */       
    
    constructor: function(options)
    {   
        this.buildOptions(options);   
        this.template_data.loader = $('#' + this.template_data.loader); // cache  
        this.initEvents();
        this.initSort();                         
        
        $scope = $('#' + this.results_container);
        if(document.getElementById('previous-job') && document.getElementById('next-job'))
        {
            this.do_vacancy_links = true;
        }
    },
    
    buildOptions:function(options)
    {
        for(var prop in options)
        {
            if(typeof options[prop] == 'object')
            {
                this[prop] = s1JS.Jobs.merge(options[prop], this[prop])
            }
            else
            {
                this[prop] = options[prop];
            }
        }
    }, 
    
    initEvents:function()
    {       
        $('.previous', this.$scope).bind("click", {res:this}, this.pagePrevious);   
        $('.next', this.$scope).bind("click", {res:this}, this.pageNext);         
    },    
    
    initSort:function()
    {
        var query = s1JS.Jobs.createObjFromQuery(this.page_data.query_string);        
        var base_link = 'http://' + document.location.host + this.page_data.script + '?' + s1JS.Jobs.createQueryFromObj(query, {order_by: true});    
       
        var sort_data = [{ text: 'most recent', val: 'date_posted', selected: (!query['order_by'] || query['order_by'] == 'date_posted')},
                         { text: 'title a-z', val: 'job_title', selected: (query['order_by'] == 'job_title')},
                         { text: 'title z-a', vak: '_job_title', selected: (query['order_by'] == '_job_title')},
                         { text: 'location a-z', val: 'location', selected: (query['order_by'] == 'location')},    
                         { text: 'location z-a', val: '_location', selected: (query['order_by'] == '_location')},         
                         { text: 'company a-z', val: 'company', selected: (query['order_by'] == 'company')}, 
                         { text: 'company z-a', val: '_company', selected: (query['order_by'] == '_company')}];               
           
        var sel = document.createElement('SELECT');    
        var sel_ind = 0;    
        for(var i = 0; i< sort_data.length; i++)
        {
            sel_ind = sort_data[i].selected ? i : sel_ind;
            $(sel).append('<option value="' + sort_data[i].val + '"' + sel_ind + '>' + sort_data[i].text + '</option>');
        }    
        sel.selectedIndex = sel_ind;
        
        $('.sort-dropdown', this.$scope).html(sel);
        $('.sort-dropdown select', this.$scope).bind("change", {res:this}, this.sortJump);                                
    }, 
    
    showNext:function()
    {
        $('.next', this.$scope).css('visibility', 'visible');
    },
    
    showPrevious:function()
    {    
        $('.previous', this.$scope).css('visibility', 'visible');    
    },
    
    hideNext:function()
    {
        $('.next', this.$scope).css('visibility', 'hidden');    
    },
    
    hidePrevious:function()
    {
        $('.previous', this.$scope).css('visibility', 'hidden');    
    },
    
    navCheck:function()
    {
        if(this.page_data.current_page == 1)
        {
            this.hidePrevious();
        }
        else
        {
            this.showPrevious();
        }
        if(this.page_data.current_page == this.page_data.max_page)
        {
            this.hideNext();
        }
        else
        {
            this.showNext();
        }
    },
    
    /* ***********************************
     *
     *   NAVIGATION EVENT HANDLERS
     *
     */    

    /*
     *  Event handlers for navigating between AJAX search result pages
     *   - pageJump, callback for clicks on page dropoptions
     *   - pageNext, next page of AJAX search results
     *   - pagePrevious, previous page of AJAX search results
     */   
    pageJump:function(e)
    {          
        var this_r = e.data.res;
        this_r.page_data.current_page = $(this).val();
        this_r.doRequest();
        this_r.updateSearchCookie();
        return false;
    },
    
    pageNext:function(e)
    {  
        var this_r = e.data.res;        
        this_r.page_data.current_page++;    
        this_r.doRequest();
        this_r.updateSearchCookie();   
     
        return false;
    },      
    
    pagePrevious:function(e)
    {
        var this_r = e.data.res;               
        this_r.page_data.current_page--;  
        this_r.doRequest();
        this_r.updateSearchCookie();
        return false;
    },    
    
    /*
     *  Callback function for 'sort by' dropoptions clicks
     */
    sortJump:function(e)
    {   
        var this_r = e.data.res;        
        var query = s1JS.Jobs.createObjFromQuery(this_r.page_data.query_string);   
        this_r.page_data.query_string = s1JS.Jobs.createQueryFromObj(query, {order_by: true}) + '&order_by=' + $(this).val();
        
        this_r.page_data.current_page = 1;
        this_r.doRequest();
        this_r.updateSearchCookie();
        return false;
    }, 

    /*
     *  Handlers for previous and next vacancy link clicks
     *
     *  When they hit previous or next vacancy, no matter where they've navigated to with the current AJAX search
     *  it has to return to its original state when the vacancy is loaded OR one page before/after if the previous/next
     *  vacancy is on a different page, this is so the vacancy they load is highlighted (desired behaviour)
     */    
    vacancyNext:function(e)
    {
        var this_r = e.data.res;
        this_r.page_data.current_page = (this_r.page_data.next_vac_not_on_page) ? this_r.page_data.page + 1 : this_r.page_data.page;
        this_r.page_data.query_string = this_r.page_data.original_query_string;
        this_r.updateSearchCookie();          
    },        
    
    vacancyPrevious:function(e)
    {
        var this_r = e.data.res;        
        this_r.page_data.current_page = (this_r.page_data.prev_vac_not_on_page) ? this_r.page_data.page - 1 : this_r.page_data.page;
        this_r.page_data.query_string = this_r.page_data.original_query_string;        
        this_r.updateSearchCookie();  
    },      
    
    
    /* ****************************
     *
     *     GENERAL FUNCTIONS
     *
     */
    
    
    /*
     *  AJAX request functions
     *
     *  preRender  - called after an AJAX request is made and data has been rendered to the page
     *  render     - renders the data for display in the target div
     *  postRender - called after the template has been rendered into the page
     *  doRequest  - Convenience function which builds a URL and runs the the above three functions (in that order)
     */

    preRender:function(data)
    {
        // Fill in variables not sent by Perl  
        if(data.featured_jobs && this.page_data.type == 'featured')
        {
            for(var i = 0; i < data.featured_jobs.length; i++)
            {
                if(this.page_data.vacancy_id == data.featured_jobs[i].vacancy_id)
                {
                    data.featured_jobs[i].selected = true;
                }
            }
        }
        
        if(data.results && this.page_data.type == 'current')
        {
            for(var i = 0; i < data.results.length; i++)
            {
                if(this.page_data.vacancy_id == data.results[i].vacancy_id)
                {
                    data.results[i].selected = true;
                }
                if(i % 2 != 0)
                {
                    data.results[i].__odd__ = true;
                }
            }
        }        
        return data;
    },   
    
    /*
     *  Uses embeddedJS and jQuery effects
     */
    render:function(data)
    {
        if(this.template)
        {
            this.template.render(data);
        }
        else
        {
            var tmpl_data = data;
            var res = this;
            $.get(this.template_data.template, function(d) { 
                      res.template = new s1JS.PerlTemplates({template:d, data:tmpl_data, target: res.template_data.target}); 
                      res.template.render();
                      res.template_data.loader.height($('#'+ res.template_data.target).parent().height());                         
                 });
        }
    },
    
    postRender:function(data)
    {        
        /** 
         *   Only call this the first time, it's basically used to set up all the "extra" functionality on the page
         *   but which requires the current search results to be loaded first
         */
        if(!this.setup_complete)
        {
            // let's set options like total count, etc.
            this.page_data.count = data.count;
            this.page_data.number_per_page = data.number_per_page;
            this.page_data.max_page = parseInt(this.page_data.count/this.page_data.number_per_page) + ( ( this.page_data.count % this.page_data.number_per_page == 0 ) ? 0 : 1 );
            this.page_data.dovals = true;
            this.navCheck(); // needs max_page value, so do it here too 

            if(parseInt(this.page_data.count) > parseInt(this.page_data.number_per_page))
            {      

                var sel = s1JS.Jobs.createPageSelect(this.page_data);
                $('.page-dropdown').html(sel);
                
                var page = this.page_data.page;
                $('.page-dropdown select').each(function () { 
                    this.selectedIndex = page - 1;
                });                
                
                $('.page-dropdown select').bind("change", {res: this}, this.pageJump);                              
            }
            else
            {
                $('.page-dropdown').html('showing 1 to ' + this.page_data.count + ' of ' + this.page_data.count);
            }
            
            if(this.do_vacancy_links)
            {
                this.doPrevNextLinks(data);                            
            }                        
           
            $('#store-search-link').click(function() {
                $('#tip').show();
                return false;
            });            
                    
            if(s1JS.Jobs.loggedIn())
            {
                $('.js-store').click(function() {
                    var url = $(this).attr('href') + '&js=1';
                    $.get(url, function(data) {
                        $('#store-message').addClass('friendly-message').html(data).show();
                        $('#tip').hide();
                    });
                    return false;
                });
            }            
            
            this.setup_complete = true;
        }       
    },     
    
    doRequest:function()
    {    
        this.template_data.loader.show();   
        this.navCheck(); // decide whether to show previous and/or next button        
        var url = this.base_URL + this.page_data.query_string + '&page=' + this.page_data.current_page;
        
        var this_r = this;
                
        $.getJSON(url, 
            function(data) {
                this_r.preRender(data);
                this_r.render(data);
                this_r.postRender(data);
                this_r.template_data.loader.hide();
            });        
    
        
        this.updatePageDrop();
    },    
    
    updateSearchCookie:function()
    {        
        // This value will be loaded by CGI on the Perl side and it doesn't like ampersands...
        var val = this.page_data.query_string + '&page=' + this.page_data.current_page;
        var cookie = 'search=' + escape(val) + ';expires=' + new Date((new Date()).getTime() +  600000) + ';path=/';
        document.cookie = cookie;
    },
   
    updatePageDrop:function()
    {
        var page = this.page_data.current_page;
        
        $('.page-dropdown select').each(function () { 
            this.selectedIndex = page - 1;
        });
    },
    
    /*
     *  Function which loops through the vacancies to find which vacancy is next or previous
     */
    doPrevNextLinks:function(data)
    {         
        if(data.featured_jobs && this.page_data.type == 'featured')
        {
            for(var i=0; i < data.featured_jobs.length; i++)
            {              
                // Found our current vacancy 
                if(this.page_data.vacancy_id == data.featured_jobs[i].vacancy_id)
                {
                    this.setStats(i + 1);
                    
                    // Set the previous link only if it isn't the top listing
                    // featured jobs only appear on the first page so need to check
                    // our prev_vac_id value here 
                    if(i > 0)    
                    {
                        this.setPreviousLink(data.featured_jobs[i - 1].vacancy_id, true);
                    }
                    // The next vacancy will either be the next featured job...
                    if(data.featured_jobs[i + 1])
                    {
                        this.setNextLink(data.featured_jobs[i + 1].vacancy_id, true);
                    }
                    // Or the first proper result..
                    else
                    {
                        this.setNextLink(data.results[0].vacancy_id);
                    }
                }
            }
        }
        
        if(data.results && this.page_data.type == 'current')
        {
            for(i = 0; i < data.results.length; i++)
            {   
                // Found our current vacancy
                if(this.page_data.vacancy_id == data.results[i].vacancy_id)        
                {         
                    var offset = (data.featured_jobs) ? data.featured_jobs.length : 0;          
                    this.setStats(i + offset + 1);
                                     
                    // This is the first listing on this page
                    if(i == 0)
                    {                       
                        // Perl calculates this value for us, it's the last result on the previous page 
                        if(data.featured_jobs)
                        {
                            this.setPreviousLink(data.featured_jobs[data.featured_jobs.length - 1].vacancy_id, true);
                        }
                        else if(data.prev_vac_id)
                        {                            
                            this.page_data.prev_vac_not_on_page = true;
                            this.setPreviousLink(data.prev_vac_id);
                        }
                    }
                    else
                    {
                        this.setPreviousLink(data.results[i - 1].vacancy_id);
                    }
                    
                    if(data.results[i + 1])
                    {
                        this.setNextLink(data.results[i + 1].vacancy_id);
                    }
                    else if(data.next_vac_id)
                    {
                        this.page_data.next_vac_not_on_page = true;                    
                        this.setNextLink(data.next_vac_id);
                    }
                }
            }            
        }
    },
    
    setPreviousLink:function(vacancyId, featured)
    {
        var link = (featured) ? '/featured/' : '/job/';
        link += vacancyId + '.html';
    
        document.getElementById('previous-job').innerHTML = "<a class=\"previous\" href=\""+ link + "\"> previous </a>";
        $('#previous-job a').bind("click", {res:this}, this.vacancyPrevious);
    },
    
    setNextLink:function(vacancyId, featured)
    {
        var link = (featured) ? '/featured/' : '/job/';
        link += vacancyId + '.html';        
    
        document.getElementById('next-job').innerHTML = "<a class=\"next\" href=\"" + link + "\"> next </a>"
        $('#next-job a').bind("click", {res:this}, this.vacancyNext);        
    },
    
    setStats:function(position)
    {
        var offset = this.page_data.number_per_page * (this.page_data.page - 1);
        document.getElementById('job-stats').innerHTML = " | Job " + (offset + position) + " of " + s1JS.Jobs.commas(this.page_data.count);
    }    
       
    
});

