$(document).ready(function() {
    $("div#makeMeScrollable").smoothDivScroll({visibleHotSpots: "always"});
    $("#makeMeScrollable").smoothDivScroll("showHotSpotBackgrounds");
});

(function ($) {
    $.extend(com.luigibormioli.products, {
        CategoryList: function () {
            var $categories, $default, $window, active, categories, reset;
            (function () {
                $categories = $('ul#categories-list');
                // REFACTOR: PERFORMANCE
                $default = $categories.find('li.default');
                $window = $(window).one('CATEGORY_VIEW_OPEN', open);
                active = null;
                categories = {};
                reset = new com.luigibormioli.products.CategoryListReset;
                $categories
                    .bind('CATEGORY_VIEW_OPEN', function (event, categoryIdentifier) {
                        $window.trigger('VIEW_CONTROLLER_OPEN', [new com.luigibormioli.products.CategoryView(categoryIdentifier)]);
                        return false;
                    })
                    .bind('mouseenter', function () {
                        $categories.addClass('hover');
                    })
                    .bind('mouseleave', function () {
                        $categories.removeClass('hover');
                    })
                    // REFACTOR: PERFORMANCE
                    .find('li:not(li.default)')
                    .each(function () {
                        var category = new com.luigibormioli.products.CategoryListCategory($(this));
                        categories[category._identifier] = category;
                    });
            })();
            function close () {
                $window
                    .unbind('COLLECTION_BROWSER_UNFILTER', close)
                    .unbind('VIEW_CONTROLLER_ERROR', close)
                    .one('CATEGORY_VIEW_OPEN', open);
                reset.disable();
                active.deselect();
                active = null;
                $default.addClass('selected');
            }
            function open (event, categoryIdentifier) {
                if (categories[categoryIdentifier]) {
                    $window
                        .one('COLLECTION_BROWSER_UNFILTER', close)
                        .one('VIEW_CONTROLLER_ERROR', close);
                    reset.enable();
                    $default.removeClass('selected');
                    active = categories[categoryIdentifier];
                    active.select();
                }
            }
        },
        CategoryListCategory: function ($category) {
            var $link, identifier;
            (function () {
                $link = $category.find('a');
                identifier = $link.attr('rel');
                enable();
            })();
            this._identifier = identifier;
            this.deselect = deselect;
            this.select = select;
            function deselect () {
                enable();
                $category.removeClass('selected');
            }
            function disable () {
                $link.unbind('click', open);
            }
            function enable () {
                $link.bind('click', open);
            }
            function open () {
                $category.trigger('CATEGORY_VIEW_OPEN', [identifier]);
            }
            function select () {
                disable();
                $category.addClass('selected');
            }
        },
        CategoryListReset: function () {
            var $reset, $window;
            (function () {
                $reset = $('a#categories-reset');
                $window = $(window);
            })();
            this.disable = disable;
            this.enable = enable;
            function disable () {
                $reset
                    .unbind('click', reset)
                    .animate({opacity: 0}, 500, 'easeInOutQuad', function () {
                        $reset.css({visibility: 'hidden'});
                    });
            }
            function enable () {
                $reset
                    .stop()
                    .one('click', reset)
                    .css({visibility: 'visible'})
                    .animate({opacity: 1}, 500, 'easeInOutQuad');
            }
            function reset () {
                $window
                    .trigger('COLLECTION_BROWSER_UNFILTER')
                    .trigger('VIEW_CONTROLLER_CLOSE');
            }
        },
        ViewController: function () {
            var $body, $content, $view, $window, active, position;
            (function () {
                $body = $('html, body').attr('scrollTop', 0);
                $content = $('div#view-content');
                $view = $('div#view');
                $window = $(window)
                    .bind('VIEW_CONTROLLER_OPEN', open)
                    .bind('VIEW_CONTROLLER_SUCCESS', function (event, scroll) {
                        load(scroll);
                    })
                    .bind('VIEW_CONTROLLER_ERROR', function (event, message) {
                        $content.html('<div id="view-description">' + message + '</div>');
                        load();
                    });
                active = null;
                position = ($content.offset() == null ? 0 : $content.offset().top - 24);
                $.ajaxSetup({dataType: 'json', global: false, url: '/products/view/', timeout: 5000});
            })();
            function close () {
                // DEBUG
                if ($.browser.msie) $content.css({visibility: 'hidden'});
                $view
                    .queue([])
                    .stop()
                    .animate({opacity: 0}, 500, 'easeInOutQuad')
                    .animate({height: 0}, 1000, 'easeInOutExpo', function () {
                        $content
                            .css({visibility: 'hidden'})
                            .empty();
                        $view.css({backgroundImage: 'url(/include/img/loading.gif)', overflow: 'hidden'});
                    });
            }
            function load (scroll) {
                $view
                    .animate({opacity: 0}, 500, 'easeInOutQuad')
                    .animate({height: $content.height()}, 1000, 'easeInOutExpo', function () {
                        if (scroll) $body.animate({scrollTop: position}, 1000, 'easeInOutQuad');
                        $content.css({visibility: 'visible'});
                        $view
                            .css({backgroundImage: 'none', overflow: 'visible'})
                            .animate({opacity: 1}, 500, 'easeInOutQuad');
                        $window.trigger('VIEW_CONTROLLER_LOAD');
                    });
            }
            function open (event, view) {
/*
                $body.animate({scrollTop: 0}, 1000, 'easeInOutQuad');
                if (active) $window.trigger('VIEW_CONTROLLER_CLOSE');
                active = view;
                $window.one('VIEW_CONTROLLER_CLOSE', close);
                $view
                    .animate({height: 72}, 500, 'easeInOutQuad')
                    .animate({opacity: 1}, 500, 'easeInOutQuad', request);
*/
            	request();
            }
            function request () {
/*                var cached = $.cache($.ajaxSettings.url + '?' + $.param($.ajaxSettings.data)),
                    success = $.ajaxSettings.success;
                if (cached) success.apply(cached.scope, cached.arguments);
                else {
                    $.ajaxSetup({success: function (response) {
                        if (response) {
                            $.cache(this.url, {scope: this, arguments: arguments});
                            success.apply(this, arguments);
                        }
                        else $.ajaxSettings.error.call(this);
                    }});
                    $.ajax();
                }
*/
            	window.location = this.url;
            }
        },
        CollectionView: function (collectionIdentifier, itemIdentifier) {
            var $window;
            (function () {
                $window = $(window).one('VIEW_CONTROLLER_OPEN', function () {
                    $window.trigger('COLLECTION_VIEW_OPEN', [collectionIdentifier]);
                });
                $.ajaxSetup({
                    data: {collection: collectionIdentifier},
                    success: function (response) {
                        $('div#view-content').html(response.view);
                        var $description = $('div#view-description'),
                            $items = $('ul#view-items-list'),
                            $reset = $('h2#view-reset a').bind('click', reset),
                            $title = $('h1#view-title'),
                            $subtitle = $title.find('span'),
                            active = null,
                            description = $description.html(),
                            guarantee = new com.luigibormioli.products.Guarantee,
                            items = {},
                            loading = 0,
                            scroller = new com.luigibormioli.products.CollectionViewItemScroller;
                        $description.height($description.height());
                        $window
                            .one('VIEW_CONTROLLER_LOAD', open)
                            .one('VIEW_CONTROLLER_CLOSE', close)
                            .bind('COLLECTION_VIEW_SEEK', seek);
                        $items
                            .bind('COLLECTION_VIEW_ITEM_LOAD', load)
                            .bind('COLLECTION_VIEW_SEEK', seek)
                            .bind('COLLECTION_VIEW_FOCUS', focus)
                            .find('li')
                            .each(function () {
                                ++loading;
                                var item = new com.luigibormioli.products.CollectionViewItem($(this));
                                items[item._identifier] = item;
                            });
                        function close () {
                            $window
                                .unbind('VIEW_CONTROLLER_LOAD', open)
                                .unbind('COLLECTION_VIEW_SEEK', seek);
                            $items
                                .unbind('COLLECTION_VIEW_ITEM_LOAD', load)
                                .unbind('COLLECTION_VIEW_SEEK', seek)
                                .unbind('COLLECTION_VIEW_FOCUS', focus);
                            $reset.unbind('click', reset);
                        }
                        function focus (event, itemIdentifier) {
                            if (itemIdentifier) {
                                $subtitle
                                    .html(items[itemIdentifier]._title)
                                    .css({opacity: 1});
                            }
                            else {
                                $subtitle
                                    .html('')
                                    .css({opacity: 0});
                            }
                            return false;
                        }
                        function load () {
                            if (!--loading) {
                                $items.unbind('COLLECTION_VIEW_ITEM_LOAD', load);
                                $window.trigger('VIEW_CONTROLLER_SUCCESS', [true]);
                            }
                            return false;
                        }
                        function open () {
                            $window.trigger('COLLECTION_VIEW_SEEK', [itemIdentifier]);
                            return false;
                        }
                        function reset () {
                            $window.trigger('COLLECTION_VIEW_SEEK');
                        }
                        function seek (event, itemIdentifier) {
                            if (itemIdentifier) {
                                if (active) {
                                    if (itemIdentifier === active._identifier) return;
                                    items[active._identifier] = active;
                                    $subtitle.animate({opacity: 0}, 500, 'easeInOutQuad');
                                }
                                active = items[itemIdentifier];
                                delete items[itemIdentifier];
                                active.disable();
                                active.unfilter();
                                $.each(items, function () {
                                    this.disable();
                                    this.filter();
                                });
                                $description.animate({opacity: 0}, 500, 'easeInOutQuad', function () {
                                    $subtitle
                                        .html(active._title)
                                        .animate({opacity: 1}, 500, 'easeInOutQuad');
                                    $reset
                                        .css({visibility: 'visible'})
                                        .animate({opacity: 1}, 500, 'easeInOutQuad');
                                    $description
                                        .html(active._description)
                                        .animate({opacity: 1}, 500, 'easeInOutQuad');
                                });
                                scroller.seek(active._position);
                            }
                            else {
                                if (active) {
                                    items[active._identifier] = active;
                                    active = null;
                                    $subtitle.animate({opacity: 0}, 500, 'easeInOutQuad', function () {
                                        $subtitle.html('');
                                    });
                                    $reset.animate({opacity: 0}, 500, 'easeInOutQuad', function () {
                                        $reset.css({visibility: 'hidden'});
                                    });
                                    $description.animate({opacity: 0}, 500, 'easeInOutQuad', function () {
                                        $description
                                            .html(description)
                                            .animate({opacity: 1}, 500, 'easeInOutQuad');
                                    });
                                }
                                $.each(items, function () {
                                    this.enable();
                                    this.unfilter();
                                });
                                scroller.seek();
                            }
                            return false;
                        }
                    },
                    error: function () {
                        $window.trigger('VIEW_CONTROLLER_ERROR', ['An error occurred while loading a collection. Please try again.']);
                    }
                });
            })();
        },
        CollectionViewItem: function ($item) {
            var $link, description, identifier, position, timer, title;
            (function () {
                // REFACTOR: PERFORMANCE
                $link = $item.children('a');
                description = $item.find('p').html();
                identifier = $link.attr('rel');
                position = $item.offset().left;
                timer = null;
                title = '&nbsp;/&nbsp;' + $item.find('h2').html();
                $(new Image)
                    .one('load', function () {
                        $item.trigger('COLLECTION_VIEW_ITEM_LOAD');
                    })
                    .attr('src', $link.find('img').attr('src'));
                enable();
            })();
            this._description = description;
            this._identifier = identifier;
            this._position = position;
            this._title = title;
            this.disable = disable;
            this.enable = enable;
            this.filter = filter;
            this.seek = seek;
            this.unfilter = unfilter;
            function blur () {
                $item.trigger('COLLECTION_VIEW_FOCUS');
            }
            function disable() {
                if ($.browser.msie) {
                    stop();
                    $item
                        .unbind('mouseover', start)
                        .unbind('mouseout', blur);
                }
                else {
                    $item
                        .unbind('mouseover', focus)
                        .unbind('mouseout', blur);
                }
                $link
                    .unbind('click', seek)
                    .bind('click', reset);
            }
            function enable() {
                if ($.browser.msie) {
                    $item
                        .bind('mouseover', start)
                        .bind('mouseout', blur);
                }
                else {
                    $item
                        .bind('mouseover', focus)
                        .bind('mouseout', blur);
                }
                $link
                    .unbind('click', reset)
                    .bind('click', seek);
            }
            function filter () {
                $item.animate({opacity: .2}, 500, 'easeInOutQuad');
            }
            function focus () {
                $item.trigger('COLLECTION_VIEW_FOCUS', [identifier]);
            }
            function reset () {
                $item.trigger('COLLECTION_VIEW_SEEK');
            }
            function seek () {
                $item.trigger('COLLECTION_VIEW_SEEK', [identifier]);
            }
            function start () {
                $item.bind('mouseout', stop);
                timer = setTimeout(focus, 100);
            }
            function stop () {
                $item.unbind('mouseout', stop);
                clearTimeout(timer);
                timer = null;
            }
            function unfilter () {
                $item.animate({opacity: 1}, 500, 'easeInOutQuad');
            }
        },
        CollectionViewItemScroller: function () {
            var $items, $scrollbar, $scroller, $window, active, currentPosition, itemsWidth, maximumDuration, maximumPosition, minimumPosition, positionOffset, positionRatio, targetPosition, timer;
            (function () {
                $items = $('ul#view-items-list');
                $scrollbar = $('div#collection-browser-scrollbar');
//                $scroller = $('div#view-items').bind('mousemove', function (event) {
//                    targetPosition = (event.pageX * positionRatio) - positionOffset;
//                });
                
                $window = $(window).bind('resize', function () {
                    calculate();
                    if (active) scroll(currentPosition, true);
                });
                active = true;
                currentPosition = ($items.position() == null ? 0 : $items.position().left);
                itemsWidth = $items.width();
                maximumDuration = 2000;
                maximumPosition = currentPosition;
                minimumPosition = null;
                positionOffset = currentPosition;
                positionRatio = null;
                targetPosition = null;
                timer = null;
                calculate();
                scroll(currentPosition);
            })();
            this.seek = seek;
            function calculate () {
                var scrollbarWidth = $scrollbar.width();
                minimumPosition = positionOffset;
                positionRatio = 0;
                if (itemsWidth > scrollbarWidth) {
                    minimumPosition -= itemsWidth - scrollbarWidth;
                    positionRatio = (itemsWidth - scrollbarWidth) / $window.width();
                }
            }
            function scroll (position, animate) {
                clearInterval(timer);
                timer = null;
                if (active) {
                    if (position < minimumPosition) position = minimumPosition;
                    else if (position > maximumPosition) position = maximumPosition;
                }
                if (animate) {
                    var duration = (Math.abs(position - currentPosition) / maximumPosition) * maximumDuration;
                    if (duration > maximumDuration) duration = maximumDuration;
                    $items
                        .stop()
                        .animate({left: position}, duration, 'easeOutQuint', (active) ? start : null);
                }
                else {
                    $items.css({left: position});
                    start();
                }
                currentPosition = position;
                targetPosition = position * -1;
            }
            function seek (position) {
                if (position) {
                    active = false;
                    position = (positionOffset - position) + positionOffset;
                }
                else {
                    active = true;
                    position = currentPosition;
                }
                scroll(position, true);
            }
            function start () {
                timer = setInterval(function () {
                    currentPosition -= (currentPosition - (targetPosition * -1)) / 10;
                    $items
                        .stop()
                        .css({left: currentPosition});
                }, 1);
            }
        },
        CategoryView: function (categoryIdentifier) {
            var $window;
            (function () {
                $window = $(window)
                    .one('VIEW_CONTROLLER_OPEN', function () {
                        $window.trigger('CATEGORY_VIEW_OPEN', [categoryIdentifier]);
                    })
                    .trigger('COLLECTION_BROWSER_UNFILTER');
                $.ajaxSetup({
                    data: {category: categoryIdentifier},
                    success: function (response) {
                        $('div#view-content').html(response.view);
                        $window
                            .trigger('COLLECTION_BROWSER_FILTER', [response.filter])
                            .trigger('VIEW_CONTROLLER_SUCCESS');
                    },
                    error: function () {
                        $window.trigger('VIEW_CONTROLLER_ERROR', ['An error occurred while loading a category. Please try again.']);
                    }
                });
            })();
        },
        CollectionBrowser: function (filter) {
            var $window, active, collections, scrollbar;
            (function () {
                $window = $(window)
                    .one('COLLECTION_VIEW_OPEN', open)
                    .bind('COLLECTION_BROWSER_FILTER', function (event, results) {
                        var position = null;
                        $.each(collections, function (collectionIdentifier, collection) {
                            if (results[collectionIdentifier]) $.each(this._items, function () {
                                if (!results[collectionIdentifier][this._identifier]) this.filter();
                                else if (!position) position = collection._position;
                            });
                            else $.each(this._items, function () {
                                this.filter();
                            });
                        });
                        scrollbar.seek(position);
                    })
                    .bind('COLLECTION_BROWSER_UNFILTER', function () {
                        $.each(collections, function () {
                            $.each(this._items, function () {
                                this.unfilter();
                            });
                        });
                        scrollbar.seek();
                    });
                active = null;
                collections = {};
                scrollbar = new com.luigibormioli.products.CollectionBrowserScrollbar;
                $('div#collection-browser').bind('wheel', scrollbar.wheel);
                $('ul#collection-browser-list')
                    .bind('COLLECTION_VIEW_OPEN', function (event, collectionIdentifier, itemIdentifier) {
                        $window.trigger('VIEW_CONTROLLER_OPEN', [new com.luigibormioli.products.CollectionView(collectionIdentifier, itemIdentifier)]);
                        return false;
                    })
                    .bind('COLLECTION_VIEW_SEEK', function (event, itemIdentifier) {
                        $window.trigger('COLLECTION_VIEW_SEEK', [itemIdentifier]);
                        return false;
                    })
                    // REFACTOR: PERFORMANCE
                    .children('li')
                    .each(function () {
                        var collection = new com.luigibormioli.products.CollectionBrowserCollection($(this));
                        collections[collection._identifier] = collection;
                    });
                /* The following 2 lines are to keep the collection browser from wrapping. */
                $cbList = $('ul#collection-browser-list');
                $cbList.width($cbList.width() + 39);
/* Category fix?
                if(filter) {
                	$window.trigger('COLLECTION_BROWSER_FILTER', filter);
                }
*/
            })();
            function close () {
                $window
                    .unbind('VIEW_CONTROLLER_ERROR', close)
                    .unbind('VIEW_CONTROLLER_CLOSE', close)
                    .one('COLLECTION_VIEW_OPEN', open);
                active.deselect();
                active = null;
            }
            function open (event, collectionIdentifier) {
                if (collections[collectionIdentifier]) {
                    $window
                        .one('VIEW_CONTROLLER_ERROR', close)
                        .one('VIEW_CONTROLLER_CLOSE', close);
                    active = collections[collectionIdentifier];
                    //scrollbar.seek(active._position);
                    active.select();
                }
            }
        },
        CollectionBrowserScrollbar: function () {
            var $collections, $handle, $scrollbar, collectionsOffset, collectionsWidth, handleHalfWidth, handlePosition, handleWidth, maximumDuration, maximumPosition, minimumPosition, positionRatio;
            (function () {
                $collections = $('ul#collection-browser-list');
                $handle = $('a#collection-browser-scrollbar-handle')
                    .bind('dragstart', function () {
                        $handle.addClass('hover');
                    })
                    .bind('drag', function (event) {
                        var position = event.offsetX - (collectionsOffset + 278);
                        scroll(position);
                    })
                    .bind('dragend', function () {
                        $handle.removeClass('hover');
                        return false;
                    });
                $scrollbar = $('div#collection-browser-scrollbar')
                    .bind('mousedown', function (event) {
                        var position = event.pageX - handleHalfWidth - (collectionsOffset + 278);
                        scroll(position, true);
                    })
                    .bind('wheel', wheel);
                collectionsOffset = $collections.position().left;
                collectionsWidth = $collections.width();
                handlePosition = $handle.position().left;
                handleWidth = $handle.width();
                handleHalfWidth = handleWidth / 2;
                maximumDuration = 1000;
                maximumPosition = null;
                minimumPosition = handlePosition;
                positionRatio = null;
                $(window).bind('resize', function () {
                    var position = handlePosition / maximumPosition;
                    calculate();
                    position *= maximumPosition;
                    scroll(position, true);
                });
                calculate();
            })();
            this.seek = seek;
            this.wheel = wheel;
            this.scroll = scroll;
            this.calculate = calculate;
            this._maximumPosition = maximumPosition;
            function calculate () {
                var scrollbarWidth = $scrollbar.width();
                maximumPosition = scrollbarWidth - handleWidth;
                if (handlePosition > maximumPosition) $handle.css({left: maximumPosition});
                positionRatio = ((collectionsWidth - scrollbarWidth) / maximumPosition) * -1;
            }
            function seek (position) {
                if (position) scroll(Math.abs((position - collectionsOffset + 278) / positionRatio), true);
                else scroll(minimumPosition, true);
            }
            function scroll (position, animate) {
                if (position <= minimumPosition) {
                    position = minimumPosition;
                    $handle.css({cursor: 'e-resize'});
                }
                else if (position >= maximumPosition) {
                    position = maximumPosition;
                    $handle.css({cursor: 'w-resize'});
                }
                else $handle.css({cursor: 'ew-resize'});
                var collectionsPosition = (position * positionRatio) + collectionsOffset;
                if (animate) {
                    $handle
                        .queue([])
                        .stop();
                    $collections
                        .queue([])
                        .stop();
                    var duration = (Math.abs(position - handlePosition) / maximumPosition) * maximumDuration;
                    if (duration > maximumDuration) duration = maximumDuration;
                    $handle.animate({left: position}, duration, 'easeOutQuint');
                    $collections.animate({left: collectionsPosition}, duration, 'easeOutQuint');
                }
                else {
                    $handle.css({left: position});
                    $collections.css({left: collectionsPosition});
                }
                handlePosition = position;
            }
            function wheel (event, delta) {
                scroll(handlePosition + (((delta < 0) ? 1 : -1) * handleWidth), true);
                return false;
            }
        },
        CollectionBrowserCollection: function ($collection) {
            var $title, $subtitle, items, identifier, position;
            (function () {
                $title = $collection.find('h3 a');
                $subtitle = $collection.find('h4 a');
                items = {};
                identifier = $title.attr('rel');
                position = $collection.offset().left;
                $collection
                    .find('ul')
                    .bind('COLLECTION_VIEW_OPEN', function (event, itemIdentifier) {
                        $collection.trigger('COLLECTION_VIEW_OPEN', [identifier, itemIdentifier]);
                        return false;
                    })
                    .bind('COLLECTION_VIEW_SEEK', function (event, itemIdentifier) {
                        $collection.trigger('COLLECTION_VIEW_SEEK', [itemIdentifier]);
                        return false;
                    })
                    .find('li')
                    .each(function () {
                        var item = new com.luigibormioli.products.CollectionBrowserItem($(this));
                        items[item._identifier] = item;
                    });
                enable();
            })();
            this._items = items;
            this._identifier = identifier;
            this._position = position;
            this.deselect = deselect;
            this.select = select;
            function blur () {
                $.each(items, function () {
                    this.hide();
                });
            }
            function deselect () {
                enable();
                $.each(items, function () {
                    this.enable();
                    this.hide();
                });
            }
            function disable () {
                $title
                    .unbind('click', open)
                    .unbind('mouseover', focus)
                    .unbind('mouseout', blur)
                    .bind('click', seek);
                $subtitle
                    .unbind('click', open)
                    .unbind('mouseover', focus)
                    .unbind('mouseout', blur)
                    .bind('click', seek);
            }
            function enable () {
                $title
                    .unbind('click', seek)
                    .bind('click', open)
                    .bind('mouseover', focus)
                    .bind('mouseout', blur);
                $subtitle
                    .unbind('click', seek)
                    .bind('click', open)
                    .bind('mouseover', focus)
                    .bind('mouseout', blur);
            }
            function focus () {
                $.each(items, function () {
                    this.show();
                });
            }
            function open (event, itemIdentifier) {
                $collection.trigger('COLLECTION_VIEW_OPEN', [identifier, itemIdentifier]);
            }
            function seek (event, itemIdentifier) {
                $collection.trigger('COLLECTION_VIEW_SEEK', [itemIdentifier]);
            }
            function select () {
                disable();
                $.each(items, function () {
                    this.disable();
                    this.show();
                });
            }
        },
        CollectionBrowserItem: function ($item) {
            var $image, $link, identifier, filtered;
            (function () {
                $link = $item
                    .find('a')
                    .animate({opacity: 1}, 500, 'easeInOutQuad');
                $image = $link.find('img');
                identifier = $link.attr('rel');
                filtered = false;
                var source = $image.attr('src');
                $(new Image)
                    .one('load', function () {
                        $link.animate({opacity: 0}, 500, 'easeInOutQuad', function () {
                                $image.css({visibility: 'visible'});
                                $link
                                    .css({background: 'transparent url(' + source + ') 0 -75px no-repeat'})
                                    .animate({opacity: (filtered) ? .465 : 1}, 500, 'easeInOutQuad');
                            });
                    })
                    .attr('src', source);
                enable();
            })();
            this._identifier = identifier;
            this.disable = disable;
            this.enable = enable;
            this.filter = filter;
            this.hide = hide;
            this.show = show;
            this.unfilter = unfilter;
            function disable () {
                $link
                    .unbind('mouseover', show)
                    .unbind('focus', show)
                    .unbind('mouseout', hide)
                    .unbind('blur', hide)
                    .unbind('click', open)
                    .bind('click', seek);
            }
            function enable () {
                $link
                    .unbind('click', seek)
                    .bind('mouseover', show)
                    .bind('focus', show)
                    .bind('mouseout', hide)
                    .bind('blur', hide)
                    .bind('click', open);
            }
            function filter () {
                filtered = true;
                $link.animate({opacity: .465}, 500, 'easeInOutQuad');
            }
            function hide () {
                if (filtered) $link.animate({opacity: .465}, 250, 'easeInOutQuad');
                $image.animate({opacity: 1}, 250, 'easeInOutQuad');
            }
            function open () {
                $item.trigger('COLLECTION_VIEW_OPEN', [identifier]);
            }
            function seek () {
                $item.trigger('COLLECTION_VIEW_SEEK', [identifier]);
            }
            function show () {
                if (filtered) $link
                    .queue([])
                    .stop()
                    .animate({opacity: 1}, 250, 'easeInOutQuad');
                $image
                    .queue([])
                    .stop()
                    .animate({opacity: 0}, 250, 'easeInOutQuad');
            }
            function unfilter () {
                filtered = false;
                $link.animate({opacity: 1}, 500, 'easeInOutQuad');
            }
        },
        CollectionList: function () {
            var $window, active, collections;
            (function () {
                $window = $(window).one('COLLECTION_VIEW_OPEN', open);
                active = null;
                collections = {};
                $('ul#collection-list-list')
/*                    .bind('COLLECTION_VIEW_OPEN', function (event, collectionIdentifier) {
                        $window.trigger('VIEW_CONTROLLER_OPEN', [new com.luigibormioli.products.CollectionView(collectionIdentifier)]);
                        return false;
                    })
*/
                    .bind('COLLECTION_VIEW_SEEK', function () {
                        $window.trigger('COLLECTION_VIEW_SEEK');
                        return false;
                    })
                    .find('a')
                    .each(function () {
                        var collection = new com.luigibormioli.products.CollectionListCollection($(this));
                        collections[collection._identifier] = collection;
                    });
            })();
            function close () {
                $window
                    .unbind('VIEW_CONTROLLER_ERROR', close)
                    .unbind('VIEW_CONTROLLER_CLOSE', close)
                    .one('COLLECTION_VIEW_OPEN', open);
                active.enable();
                active = null;
            }
            function open (event, collectionIdentifier) {
                if (collections[collectionIdentifier]) {
                    $window
                        .one('VIEW_CONTROLLER_ERROR', close)
                        .one('VIEW_CONTROLLER_CLOSE', close);
                    active = collections[collectionIdentifier];
                    active.disable();
                }
            }
        },
        CollectionListCollection: function ($collection) {
            var identifier;
            (function () {
                identifier = $collection.attr('rel');
                enable();
            })();
            this._identifier = identifier;
            this.disable = disable;
            this.enable = enable;
            function disable () {
                $collection
                    .unbind('click', open)
                    .bind('click', seek);
            }
            function enable () {
                $collection
                    .unbind('click', seek)
                    .bind('click', open);
            }
            function open () {
//                $collection.trigger('COLLECTION_VIEW_OPEN', [identifier]);
            }
            function seek () {
                $collection.trigger('COLLECTION_VIEW_SEEK');
            }
        }
    });
    $(function () {
        if (($.browser.msie && ($.browser.version < 6)) || ($.browser.safari && ($.browser.version < 500))) return false;
        new com.luigibormioli.products.CategoryList;
        new com.luigibormioli.products.ViewController;
        new com.luigibormioli.products.CollectionBrowser;
        new com.luigibormioli.products.CollectionList;
//        var hash = location.hash.match(/^#\/(collection\/(\d+)(\/item\/(\d+))?|category\/(\d+))\/?$/);
        var hash = location.hash.match(/^#\/view\/(collection\/(\d+)(\/item\/(\d+))?|category\/(\d+))\/?$/);
        
        if (hash) {
            var view = (hash[2]) ?
                new com.luigibormioli.products.CollectionView(hash[2], (hash[4]) ? hash[4] : null) : ((hash[5]) ?
                    new com.luigibormioli.products.CategoryView(hash[5]) : null);
            if (view) $(window).trigger('VIEW_CONTROLLER_OPEN', [view]);
        }
    });
})(jQuery);

