/**
* @author Craig MacKenzie
*/
// Application namespace
var _MCCAIN = {};


//--------------------------------------------------------------------------------
// Configuration module
//--------------------------------------------------------------------------------

_MCCAIN.config = function() {

    // private functions



    // public methods/properties
    return {
        previousCategory: null,
        currentCategory: null,
        currentView: '#IF_landing',
        currentItems: 0, // Default to 0
        items: [], // used to store the current selection of items
        maxItems: 3, // maximum number of items to be added
        container: $(function() {
            return $('#IngredientFinder');
        }),
        enlargeBasketItem: {
            width: 106,
            height: 113
        },
        urlPath: window.location.pathname,
        resources: '',
        webservices: {
            getCategory: 'test1.xml', // used for testing, update this URL for retrieving selected category
            setCategoryFilters: 'test1.xml'
        }
    };


} ();





//--------------------------------------------------------------------------------
// Tools module
//--------------------------------------------------------------------------------

_MCCAIN.tools = function() {

    // Private

    function removeFilter() {
        if (!$.support.opacity) {
            try {
                this.style.removeAttribute('filter');
            }
            catch (smother) {
            } // handle old opera versions
        }
    }

    // view manager
    function viewManager(currentView, selectedView) {
        if (_MCCAIN.config.currentView != selectedView) {
            $(_MCCAIN.config.currentView).fadeOut('slow', function() {

                if (_MCCAIN.config.currentView === '#IF_landing') {
                    $('#CompareDashboard, #Filters').fadeIn('slow');
                }

                _MCCAIN.config.currentView = selectedView;

                $(_MCCAIN.config.currentView).fadeIn('fast', function() {
                    // update container height
                    updateHeight($('#Wrapper .content'), $('#IngredientFinder'));

                    // remove filter from IE (caused text aliasing)
                    removeFilter();
                });

            });
        }
    }

    // update height of popup and it's container
    function updateHeight(container, target) {
        container.height(target.outerHeight() + 100);
        container.find('.overlay').height(container.outerHeight());
    }

    // public methods/properties
    return {
        // function for handling ajax requests
        ajaxRequest: function(config) {
            /*$.ajax({
            url: config.url || alert('Please provide a URL for your Ajax request.'),
            type: config.method || alert('Please provide whether to use GET or POST for you Ajax Request.'),
            dataType: config.mimeType || alert('Please provide a mime type for you Ajax request.'),
            data: config.data,
            cache: config.cache || false,
            timeout: config.timeout || 30000,
            error: function(){
            //  alert('data failed to load.');
            },
            success: config.cb_function //success, data sent to cb_function
            });*/
        },
        showLoader: function(target, loader) {
            target.fadeTo('fast', 0.5, function() {
                loader.slideDown();
                removeFilter();
            });

        },
        removeLoader: function(target, loader) {
            $(loader).slideUp('fast', function() {
                target.fadeTo('fast', 1, removeFilter); // removeFilter removes filter from IE that causes text to not be anti-aliased
            });
        },
        viewManager: viewManager,
        updateHeight: updateHeight,
        removeFilter: removeFilter,
        console: {
            log: function debug(what) {
                if (window.console && window.console.firebug) {
                    console.log(what);
                }
                else {
                    alert(what);
                }
            }
        }
    };
} ();


//--------------------------------------------------------------------------------
// Ingredient Finder Module
//--------------------------------------------------------------------------------

_MCCAIN.IngFinder = function() {


    // private methods/properties
    // cache target container
    var target = _MCCAIN.config.container;

    // show reset notice
    function showNotice(category) {
        _MCCAIN.config.previousCategory = _MCCAIN.config.currentCategory;

        // curent category is set from the radio value attribute
        _MCCAIN.config.currentCategory = $(this).attr('value');

        if (_MCCAIN.config.currentCategory !== null && _MCCAIN.config.currentItems !== 0) {
            // show prompt before resetting users comparison basket
            // if the user clicks continue the category will be updated
            target.find('.notice').slideDown('fast');
        }
        else {
            // change category
            changeCategory(_MCCAIN.config.currentCategory)
        }

    }




    // change category
    function changeCategory(currentCategory) {

        // hide reset notice
        target.find('.notice').slideUp('fast');

        $('#noResults').fadeOut();
        $('#noFiltersSelected').fadeOut();

        // clear basket
        clearItems();

        // disable clear and view buttons
        target.find('a.viewPC, a.clearPC').addClass('disabled');

        // enable add product buttons
        target.find('a.addProduct').removeClass('disabled');



        // show loaders
        _MCCAIN.tools.showLoader(target.find('.modifyFilters, #ResultsWrapper'), target.find('.loading'));


        // show selected view
        _MCCAIN.tools.viewManager(_MCCAIN.config.viewState, '#CompareContent');


        // set currentCategory variable (this is redundant but it should make the code easier to follow)
        currentCategory = _MCCAIN.config.currentCategory;

        // send ajax request 

        CallCategory(JSON.stringify(currentCategory), "");

        /* _MCCAIN.tools.ajaxRequest({
        // URL: Change to whatever is appropiate in the Config module. 
        url: _MCCAIN.config.webservices.getCategory,
        // data/params
        data: {
        category: currentCategory
        },
        // Method: Get or Post
        method: 'GET',
        // mimeType: can be xml, html, json, jsonp, script, or text. More documentation can be seen here: http://api.jquery.com/jQuery.ajax/
        mimeType: 'XML',
        // call back function to run after a succesful request. Function is passed the response data.
        cb_function: updateCategory
        });       
        */
    }



    // update category
    function updateCategory(arg) {
        //data = $(arg);

        // You can start manipulating the data here
        target.find("div.modifyFilters")[0].innerHTML = arg;

        // remove loaders   
        setTimeout(function() {
            _MCCAIN.tools.removeLoader(target.find('.modifyFilters, #ResultsWrapper'), target.find('.loading'));
        }, 1000);

        // used to update the popup container/wrappers height
        _MCCAIN.tools.updateHeight($('#Wrapper .content'), $('#IngredientFinder'));
    }


    function updateViewItems(arg) {

        // remove loaders   
        _MCCAIN.tools.removeLoader(target.find('.modifyFilters, #ResultsWrapper'), target.find('.loading'));

        // enable/disable adding more items to the comparison basket
        if (_MCCAIN.config.currentItems === _MCCAIN.config.maxItems) {
            target.find('.addAnother').addClass('disabled');
        }
        else {
            target.find('.addAnother').removeClass('disabled');
        }

        $('#ViewPC')[0].innerHTML = arg;

        // show selected view
        _MCCAIN.tools.viewManager(_MCCAIN.config.viewState, '#ViewPC');
    }

    function getUpdateFilterParameters() {
        // filter data object
        var filters = new Array();

        // get filters
        var elFilters = target.find('div.modifyFilters :input:checked');

        // PageSize;
        filters[0] = getPageSize();
        //Selected Page;
        filters[1] = selectedPage;
        filters[2] = _MCCAIN.config.currentCategory;

        for (var i = 0; i < elFilters.length; i++) {
            filters[i + 3] = elFilters[i].name;
        }

        if (elFilters.length > 0) {
            return JSON.stringify(filters);
        } else {
            return null;
        }
    }

    function setProdcutsCount(count) {
        var productCountControls = target.find('span.productsCount');
        for (var i = 0; i < productCountControls.length; i++) {
            productCountControls[i].innerHTML = count;
        }
    }

    // update category filters
    function updateFilters() {

        // show selected view
        _MCCAIN.tools.viewManager(_MCCAIN.config.viewState, '#CompareContent');

        var selectedInput = $(this);

        // select/unselect all inputs
        if (selectedInput.attr('name') == 'SelectAll' && selectedInput.is(':checked')) {
            //selectedInput.siblings('label').text('Remove All');
            selectedInput.closest('ul').find(':input').each(function() {
                $(this).attr('checked', 'checked');
            });
        }
        else
            if (selectedInput.attr('name') == 'SelectAll' && !selectedInput.is(':checked')) {
            //selectedInput.siblings('label').text('Select All');
            selectedInput.closest('ul').find(':input').each(function() {
                $(this).removeAttr('checked');
            });
        }


        /*
        target.find('div.modifyFilters :input:checked').each(function(){
        filters[$(this).attr('name')] = 1;
        );
        */

        var filters = getUpdateFilterParameters();

        if (filters) {
            // show loaders
            _MCCAIN.tools.showLoader(target.find('#ResultsWrapper'), target.find('#ResultsPC .loading'));

            pageCount = -1;
            selectedPage = 0;
            firstVisiblePage = 0;

            $('#noResults').fadeOut();
            $('#noFiltersSelected').fadeOut();

            CallFilters(filters, "");
        } else {
            // Clear products
            target.find("#ResultsWrapper")[0].innerHTML = '';

            setProdcutsCount('0');

            $('#noResults').fadeOut();
            $('#noFiltersSelected').fadeIn();

            _MCCAIN.tools.removeLoader(target.find('.modifyFilters, #ResultsWrapper'), target.find('.loading'));
        }

        /* send ajax request */
        /*_MCCAIN.tools.ajaxRequest({
        // URL: Change to whatever is appropiate in the Config module.
        url: _MCCAIN.config.webservices.setCategoryFilters,
        // Method: Get or Post
        method: 'GET',
        // send applied filters
        data: filters,
        // mimeType: can be xml, html, json, jsonp, script, or text. More documentation can be seen here: http://api.jquery.com/jQuery.ajax/
        mimeType: 'XML',
        // call back function to run after a succesful request. Function is passed the response data.
        cb_function: applyFilters
        });
        */

    }



    // update category
    function applyFilters(data) {
        //data = $(dat daa);

        if (target.find('div.modifyFilters :input:checked').length > 0) {
            // You can start manipulating the data here

            var stringsArray = data.split(';');

            var productCount = stringsArray[0];

            setProdcutsCount(productCount);

            var newPageCount = stringsArray[1];

            if (pageCount != newPageCount) {
                pageCount = newPageCount;
                renderPager(firstVisiblePage, selectedPage, pagerSize, pageCount);
            }

            target.find("#ResultsWrapper")[0].innerHTML = stringsArray[2];

            if ((target.find("#ResultsWrapper img.addProduct").length == 0)) {
                $('#noResults').fadeIn();
            }

            for (var i = 0; i < _MCCAIN.config.currentItems; i++) {
                var itemRelation = $('#CompareDashboard ol li:eq(' + i + ') span').attr('rel');

                addProduct = target.find('#ResultsPC div[rel=' + itemRelation + ']');

                addProduct.attr('added', 'true');
                addProduct.fadeTo('fast', 0.5);

                // Disable items in the results gallery
                // target.find('#ResultsPC div[rel=' + itemRelation + ']').fadeTo('fast', 1, _MCCAIN.tools.removeFilter).removeAttr('added');
            }


            // remove loaders
            setTimeout(function() {
                _MCCAIN.tools.removeLoader(target.find('#ResultsWrapper'), target.find('.loading'));
            }, 1000);
        }

        // used to update the popup container/wrappers height
        _MCCAIN.tools.updateHeight($('#Wrapper .content'), $('#IngredientFinder'));

    }



    // Change how many products are show per page
    function itemsPerPage() {

        // alert the valute of items per page value
        //alert($(this).val());

        // set other items per page select to the same value
        target.find('select.itemsPerPage').val($(this).val());


        pageCount = -1;
        firstVisiblePage = 0;
        selectedPage = 0;

        // show loaders
        _MCCAIN.tools.showLoader(target.find('#ResultsWrapper'), target.find('#ResultsPC .loading'));

        CallFilters(getUpdateFilterParameters(), "");
    }





    // remove item from basket
    function removeItem(e) {

        // return false if there are no items to remove
        if (_MCCAIN.config.currentItems === 0) {
            return false;
        }
        else // hide the remove button on the 1st added item in the basket when removing items
            if (_MCCAIN.config.currentItems == 1) {
            // disable clear all and view
            target.find('a.viewPC, a.clearPC').addClass('disabled');
            target.find('#CompareDashboard ol li').find('.remove').hide();
        }


        // decrement the current amount of items by 1
        _MCCAIN.config.currentItems = _MCCAIN.config.currentItems - 1;

        // get the parent index of the item to be removed
        var itemIndex = $(e.target).parent().index();

        // get item relation so we can renable the item in the gallery
        var itemRelation = $('#CompareDashboard ol li:eq(' + itemIndex + ') span').attr('rel');

        // clear rel
        //       target.find('#CompareDashboard ol li:eq(' + itemIndex + ') span').removeAttr('rel');


        // renable item in the results gallery
        target.find('#ResultsPC div[rel=' + itemRelation + ']').fadeTo('fast', 1, _MCCAIN.tools.removeFilter).removeAttr('added');



        if (_MCCAIN.config.items.length > 0) {
            // remove item from array index
            _MCCAIN.config.items.splice(itemIndex, 1);
            // push stored empty item block to the end of the array
            _MCCAIN.config.items.push(_MCCAIN.IngFinder.emptyItem);

            // redraw sorted comparison basket
            var x;
            for (x in _MCCAIN.config.items) {
                target.find('#CompareDashboard ol li:eq(' + x + ') span').empty().prepend(_MCCAIN.config.items[x]);
            }

            // Shift relations
            for (var i = itemIndex; i < _MCCAIN.config.currentItems; i++) {
                var rel = target.find('#CompareDashboard ol li:eq(' + (i + 1) + ') span').attr('rel');

                if (rel) {
                    target.find('#CompareDashboard ol li:eq(' + i + ') span').attr('rel', rel);
                }
            }
        }



        // hide remove button from empty basket items
        target.find('#CompareDashboard ol li:gt(' + (_MCCAIN.config.currentItems - 1) + ')').find('.remove').hide();

        // renable add product buttons
        target.find('.addAnother, .addProduct').removeClass('disabled');


        return false;
    }




    // add item to basket
    function addItem(e) {

        var addProduct = $(e.target);

        // Only add an item if the current amount of items are less than the max ammount
        // If max limit is reached disable adding of items.
        if (_MCCAIN.config.currentItems < _MCCAIN.config.maxItems && addProduct.closest('div').attr('added') != "true") {

            // store selected items content minus the add button
            var clonedItem = addProduct.closest('div').contents().not('a.addProduct').clone();

            // set added flag on selected product
            addProduct.closest('div').attr('added', 'true');

            addProduct.closest('div').fadeTo('fast', 0.5, function() {

                // cache current basket item selector
                var basketItem = target.find('#CompareDashboard ol li:eq(' + (_MCCAIN.config.currentItems) + ') span');

                // store selected item into the current item slot
                _MCCAIN.config.items[_MCCAIN.config.currentItems] = clonedItem;

                // swap in selected product
                basketItem.css('opacity', 0).attr('rel', addProduct.attr('rel')).empty();
                basketItem.append(_MCCAIN.config.items[_MCCAIN.config.currentItems]);
                basketItem.fadeTo('fast', 1, _MCCAIN.tools.removeFilter);


                basketItem.parent().find('.remove').show();
                // increment how many items are in the basket
                _MCCAIN.config.currentItems = _MCCAIN.config.currentItems + 1;

                if (_MCCAIN.config.currentItems >= _MCCAIN.config.maxItems) {
                    // disable adding of items to basket
                    target.find('a.addProduct').addClass('disabled');
                }
            });

            // renable clear all and view
            target.find('a.viewPC, a.clearPC').removeClass('disabled');

        }

        return false;
    }


    
    // enlarge basket items
    $(function(){
        var w;
        var h;
        var top;
        var left;
        var size = function(isOver, tartget){
            w = isOver ? _MCCAIN.config.enlargeBasketItem.width : '71px';
            h = isOver ? _MCCAIN.config.enlargeBasketItem.height : '75px';
            top = isOver ? '-20px' : 0;
            left = isOver ? '-20px' : 0;
            
            tartget.stop().animate({
                top: top,
                left: left,
                width: w,
                height: h
            }, 100, 'swing');
        }
        
        // enlarge image on hover
        $('#CompareDashboard').find('img').live('mouseover mouseout', function(event){
            if (event.type == 'mouseover') {
                size(true, $(this))
            }
            else {
                size(false, $(this))
            }
        });
    })
    

    function renderPager(firstPage, selectedPage, pageSize, pageCount) {
        var innerHtml = '';

        if (pageCount > 0 && getPageSize() != 'All') {
            if (firstPage > 0) {
                innerHtml += '<li><a href="#Prev">&lt;&lt;</a></li>';
            }

            var lastPage = Math.min(firstPage + pageSize - 1, pageCount - 1);

            for (var i = firstPage; i <= lastPage; i++) {

                if (i == selectedPage) {
                    innerHtml += '<li><a href="#' + i + '"><b>' + (i + 1) + '</b></a></li>'
                }
                else {
                    innerHtml += '<li><a href="#' + i + '">' + (i + 1) + '</a></li>'
                }
            }

            if (lastPage < pageCount - 1) {
                innerHtml += '<li><a href="#Next">&gt;&gt;</a></li>';
            }
        }

        var pagers = target.find('ul.pagination');

        for (var i = 0; i < pagers.length; i++) {
            pagers[i].innerHTML = innerHtml;
        }
    }

    function getPageSize() {
        return target.find('select.itemsPerPage').val();
    }

    var pageCount = -1;
    var selectedPage = 0;
    var firstVisiblePage = 0;
    var pagerSize = 3;

    // change page
    function pagination() {

        var value = this.hash.substr(1);

        if (value == 'Next') {
            selectedPage++;
            firstVisiblePage++;
        }
        else if (value == 'Prev') {
            selectedPage--;
            firstVisiblePage--;
        }
        else {
            selectedPage = value;
        }

        renderPager(firstVisiblePage, selectedPage, pagerSize, pageCount);

        //alert('page change');
        // TODO:ajax request to update results with selectedPage.

        // show loaders
        _MCCAIN.tools.showLoader(target.find('#ResultsWrapper'), target.find('#ResultsPC .loading'));

        CallFilters(getUpdateFilterParameters(), "");

        return false;
    }




    // clear all items
    function clearItems() {


        if ($(this).hasClass('disabled'))
            return false;


        // reset current items
        _MCCAIN.config.currentItems = 0;

        // remove all items from array
        _MCCAIN.config.items.splice(0, _MCCAIN.config.items.length);

        // reset compare basket
        target.find('#CompareDashboard ol li span').each(function() {
            $(this).empty().prepend(_MCCAIN.IngFinder.emptyItem);
            target.find($(this).attr('rel')).fadeTo('fast', 1, _MCCAIN.tools.removeFilter).removeAttr('added');
        })

        // renable gallery items
        $('#ResultsWrapper tr td div[added=true]').fadeTo('fast', 1, _MCCAIN.tools.removeFilter).removeAttr('added');

        // hide remove button from empty basket items
        target.find('#CompareDashboard ol li').find('.remove').hide();

        // disable view/clear buttons
        target.find('a.viewPC, a.clearPC').addClass('disabled');

        // renable add product buttons
        target.find('.addProduct, .addAnother').removeClass('disabled');

        // Clear products
        target.find("#ResultsWrapper")[0].innerHTML = '';

        // Reset products count
        setProdcutsCount('0');

        $('#noFiltersSelected').fadeIn();

        return false;
    }




    // view items in your comparison basket
    function viewItems() {

        if ($(this).hasClass('disabled'))
            return false;

        var selectedProducts = new Array();


        for (var i = 0; i < _MCCAIN.config.currentItems; i++) {
            selectedProducts[i] = target.find('#CompareDashboard ol li:eq(' + i + ') span').attr('rel');
        }

        CallViewItems(JSON.stringify(selectedProducts), "");

        // show loaders
        _MCCAIN.tools.showLoader(target.find('#ResultsWrapper'), target.find('#ResultsPC .loading'));

        return false;
    }


    // add another (go back to search results
    function addAnother() {

        if ($(this).hasClass('disabled'))
            return false;

        // show selected view
        _MCCAIN.tools.viewManager(_MCCAIN.config.viewState, '#CompareContent');

    }

    // start over
    function startAgain() {

        // show selected view
        _MCCAIN.tools.viewManager(_MCCAIN.config.viewState, '#CompareContent');

        // clear basket
        clearItems();

        // reset filters 
        target.find('div.modifyFilters :input:checked').each(function() {
            $(this).removeAttr('checked');
        });


        // disable clear and view buttons
        target.find('a.viewPC, a.clearPC').addClass('disabled');

        // enable add product buttons
        target.find('a.addProduct').removeClass('disabled');
    }

    // reset category selection (firefox seems to be caching it)
    $(function() {
        target.find('#ChangeCategory li :input').removeAttr('checked');
    })

    // public methods/properties
    return {
        updateViewItemsPublic: function(arg) { return updateViewItems(arg); },
        applyFiltersPublic: function(arg) { return applyFilters(arg); },
        updateCategoryPublic: function(arg) { return updateCategory(arg); },
        showResetNotice: $(function() {
            // had to use the click event as IE didn't respond well to the on change event.
            target.find('#ChangeCategory input').live('click', showNotice);
        }),
        changeCategory: $(function() {
            // if the user clicks 'Continue? YES' proceed with changing the category
            target.find('.notice .reset').click(changeCategory);
        }),
        hideNotice: $(function() {
            // if the user clicks 'Continue? NO' hide notice panel
            target.find('.notice .no-reset').click(function() {
                _MCCAIN.config.currentCategory = _MCCAIN.config.previousCategory;
                // hide reset notice
                $(this).closest('.notice').slideUp('fast');

                target.find('#ChangeCategory li :input').each(function() {
                    if ($(this).attr('value') == _MCCAIN.config.currentCategory) {
                        $(this).attr('checked', 'true');
                    } else {
                        $(this).removeAttr('checked');
                    }
                });
            });

            /*
            var x;
            var categories = target.find('#ChangeCategory li :input');
            for (x in categories) {
            if (categories[x].attr("value") == _MCCAIN.config.currentCategory) {
            categories[x].checked = true;
            break;
            }
            }*/
        }),
        updateFilter: $(function() {
            // event that is fired when you change a filter
            target.find('.modifyFilters input').live('click', updateFilters);
        }),
        updateItemsPerPage: $(function() {
            // event that is fired when you change how many items to display per page
            target.find('select.itemsPerPage').change(itemsPerPage);
        }),
        removeItem: $(function() {
            // event that is fired when you remove an item from your comparison basket
            $('#CompareDashboard ol li .remove').live('click', removeItem);
        }),
        addItem: $(function() {
            // save empty basket HTML so it can be used later when deleting items from your basket
            _MCCAIN.IngFinder.emptyItem = target.find('#CompareDashboard ol li:eq(0)').html();
            // event that is fired when you add an item to your comparison basket
            target.find('#ResultsPC .addProduct').live('click', addItem);
        }),
        changePage: $(function() {
            // event that is fired when you add an item to your comparison basket
            target.find('ul.pagination a').live('click', pagination);
        }),
        clearItems: $(function() {
            // event that is fired when you add an item to your comparison basket
            target.find('div.compareActions .clearPC').live('click', clearItems);
        }),
        viewItems: $(function() {
            // event that is fired when you view the items in your comparison basket
            target.find('div.compareActions .viewPC').live('click', viewItems);
        }),
        addAnother: $(function() {
            // event that is fired when you view the items in your comparison basket
            target.find('.addAnother').live('click', addAnother);
        }),
        startAgain: $(function() {
            // event that is fired when you view the items in your comparison basket
            target.find('.startAgain').live('click', startAgain);
        })



    };


} ();

