(function ($) {
	
	$.heritage = function (options) {
		return $.heritage.impl.init(this, options);
	};
	
	$.fn.heritage = function (options) {
		return $.heritage.impl.init(this, options);
	};
	
	/*
	 * heritage default options
	 */
	$.heritage.defaults = {
	    animationTime:  750
	};
	
	$.heritage.impl = {
		
		/*
		 * heritage options
		 */
		opts: null,
		
		/*
		 * heritage helper
		 */
		helper: {},
		
		/*
		 * Initialize the heritage
		 */
		init: function (template, options) {
            
            var self = this;
            
            self.opts = $.extend({}, $.heritage.defaults, options);
            
            // suppress sub level images from loading on page load
            $('ul.heritageitem-collection img').suppressLoad();
            
            // create the helper objects
            self.helper.container       = template;
            self.helper.categories      = template.find('.heritagecategory-collection');
            self.helper.background      = $('<div class="heritagecategory-background"></div>').appendTo(self.helper.container);
            self.helper.overlay         = $('<div class="heritagegrid-overlay"></div>').appendTo(self.helper.container);
            self.helper.category        = $('<div class="heritagecategory-container"><div class="heritageitem-collection-container"></div></div>').appendTo(self.helper.container);
            self.helper.categoryNav     = $('<ul class="nav-heritagecategory"></ul>').appendTo(self.helper.container);
            self.helper.grid            = $('<ul class="heritageitem-collection"></ul>');
            self.helper.item            = $('<div class="heritageitem-container"></div>').appendTo(self.helper.container);
            self.helper.itemClose       = $('<div class="close-heritageitem"></ul>').appendTo(self.helper.item);
            self.helper.itemDetail      = $('<div class="heritageitem-detail"><div class="heritageitem-info"></div><div class="heritageitem-image-container"></div></div>').appendTo(self.helper.item);
            self.helper.itemStatus      = $('<div class="heritageitem-status"><span class="current">&#8212;</span> of <span class="length">&#8212;</span></div>').appendTo(self.helper.item);
            self.helper.itemControls    = $('<div class="heritageitem-controls"><a class="prev-heritageitem" href="#" title="' + self.opts.res.previous + '">' + self.opts.res.previous + '</a><a class="next-heritageitem" href="#" title="' + self.opts.res.next + '">' + self.opts.res.next + '</a></div>').appendTo(self.helper.item);
            self.helper.itemNav         = $('<ul class="nav-heritageitem"></ul>').appendTo(self.helper.item);
            
            // set the option values
            self.width                  = self.helper.categories.outerWidth();
            self.height                 = self.helper.categories.outerHeight();
            self.categoryWidth          = Math.floor(self.width/self.helper.categories.children().length);
            self.view                   = 'landing';
            
            // create the background div
            $('<div class="heritagecategory-black"></div>')
                .css({
                    paddingTop: (self.helper.categories.children().length)*(147) + 'px'
                })
                .prependTo(self.helper.container)
                ;
            
            // initialize the categories
            self.helper.categories.children().each(function(i, category){
                
                $(category).css({
                    top:    100 + (i)*($(category).height()) + 'px'
                });
                
                $(category).find('.heritagecategory-open')
                    .attr('title', $(category).find('.heritagecategory-title').text())
                    ;
                
                $(category).find('.heritagecategory-image').css({
                    left:   -parseInt($(category).css('left')) + 'px',
                    top:    -(100 + (i)*($(category).height())) + 'px'
                });
                
            });
            
            // show the categories
            self.helper.categories
                .css({
                    position:   'relative',
                    left:       0,
                    display:    'none'
                })
                .fadeIn(self.opts.animationTime, function(){
                    
                    self.width  = self.helper.categories.outerWidth();
                    self.height = self.helper.categories.outerHeight();
                    
                    // load the images
                    self.helper.categories.find('img.heritagecategory-image').each(function(i, item){
                        
                        $(new Image()).load(function(){
                            
                            $(item).fadeIn(self.opts.animationTime);
                            
                        }).attr('src', $(item).attr('src'));
                        
                    });
                    
                })
                ;
            
            // build the category nav
	        self.helper.categories.children().each(function(i, item){
	            self.helper.categoryNav.append($('<li><a href="#" title="' + $(item).find('.heritagecategory-title').text() + '">' + $(item).find('.heritagecategory-title').text() + '</a></li>'))
	        });
            
            // bind the category events
            self.bindCategoryEvents();
            
			return self;
		},
		
		/*
		 * Bind the category events
		 */
		bindCategoryEvents: function() {
		    
		    var self    = this;
		    
		    // click
		    self.helper.categories.children().click(function(e){
		        e.preventDefault;
		        
		        $(this).unbind();
		        
		        var category = this;
		        
		        // add active class to category nav
		        $(self.helper.categoryNav.find('a')[$(category).prevAll().length]).addClass('active').parent().siblings().children().removeClass('active');
		        
		        var overlay = $(category).clone().addClass('heritagecategory-overlay');
		        
		        overlay
		            .appendTo(self.helper.categories)
		            .siblings().unbind()
		            ;
		        
		        overlay.find('.heritagecategory-image').animate({
		            left:   0,
		            top:    0
		        }, self.opts.animationTime, 'easeOutCubic');
		        
		        overlay
		            .animate({
		                left:   0,
		                top:    0,
		                width:  self.width + 'px',
		                height: self.height + 'px'
		            }, self.opts.animationTime, 'easeOutCubic')
		            ;
		        
		        // animate dummy object to delay grid init
		        $('<div></div>').animate({height: 0}, self.opts.animationTime, function(){
		            
		            self.helper.overlay.fadeIn(self.opts.animationTime);
		            overlay.find('.heritagecategory-text').fadeOut(self.opts.animationTime);
                    self.helper.categoryNav.fadeIn(self.opts.animationTime);
                    self.initGrid(category);
		            
		        })
		        
		    });
		    
		    // hover
//		    self.helper.categories.children().hover(
//		        function(){
//		            $(this).siblings().find('img').queue("fx", []);
//		            $(this).siblings().find('img').fadeTo(150, '0.33');
//		        },
//		        function(){
//		            $(this).siblings().find('img').queue("fx", []);
//		            $(this).siblings().find('img').fadeTo(150, '1.00');
//		        }
//		    );
		    
		    self.helper.categories.find('.heritagecategory').hover(
		        function(){
		            $(this).siblings().queue("fx", []);
		            $(this).siblings().fadeTo(150, '0.33');
		        },
		        function(){
		            $(this).siblings().queue("fx", []);
		            $(this).siblings().fadeTo(150, '1.00');
		        }
		    );
		    
		    return;
		},
		
		/*
		 * Initialize the grid
		 */
		initGrid: function (category) {
		    
		    var self        = this;
		    var $container  = self.helper.category.find('.heritageitem-collection-container');
		    
		    self.items      = $(category).find('ul.heritageitem-collection').children();
		    self.view       = 'category';
		    
		    // loop through the items
		    self.items.each(function(i, item){
		        
		        var title = $(item).find('.heritageitem-title').text();
		        
		        var $gi = $('<li class="heritageitem heritageitem-' + (i + 1) + '"></li>').append($('<a class="heritageitem-open" href="#" title="' + title + '">' + title + '</a>'));
		        var $ni = $('<li></li>').append('<a href="#" title="' + title + '"></a>');;
		        
		        // load the grid image
		        $(new Image()).load(function(){
		            
		            $(this).css('display', 'none');
		            
		            // append the grid image
		            $gi
		                .prepend($(this).addClass('heritageitem-grid-image'))
		                .css('background-color', '#ccc')
		                ;
		            
		            // show the grid image
		            $(this).fadeIn(self.opts.animationTime);
		            
		        }).attr('src', $.data($(item).find('img.heritageitem-grid-image').get(0), 'src'));
		        
		        // load the nav image
		        $(new Image()).load(function(){
		            
		            // append the nav image
		            $ni.children()
		                .append($(this))
		                ;
		            
		        }).attr('src', $.data($(item).find('img.heritageitem-thumb-image').get(0), 'src'));
		        
		        // append item to collection
		        self.helper.grid.append($gi);
		        self.helper.itemNav.append($ni);
		        
		    });
		    
		    $container.empty().append(self.helper.grid);
		    
		    // update the background image
		    $(new Image()).load(function(){
		        
		        self.helper.background.append($(this).css('display', 'none'));
		        self.helper.background.find('img').fadeIn(self.opts.animationTime);
		        
		    }).attr('src', $(category).find('img.heritagecategory-image').attr('src'));
		    
		    // show the grid
		    self.helper.category.fadeIn(self.opts.animationTime, function(){
		        
		        // bind the grid events
		        self.bindGridEvents();
		        self.bindCategoryNavEvents();
		    });
		    
		    return;
		},
		
		/*
		 * Reset the grid
		 */
		resetGrid: function () {
		    
		    var self    = this;
		    
		    // empty the grid object
		    self.helper.grid.empty();
		    
		    // empty the item nav object
		    self.helper.itemNav.empty();
		    
		    return;
		},
		
		/*
		 * Bind the grid events
		 */
		bindGridEvents: function () {
		    
		    var self    = this;
		    
		    // grid hover
		    self.helper.category.find('li.heritageitem').unbind().hover(
		        function(){
		            $(this).siblings().queue("fx", []);
		            $(this).siblings().fadeTo(150, '0.33');
		        },
		        function(){
		            $(this).siblings().queue("fx", []);
		            $(this).siblings().fadeTo(150, '1.00');
		        }
		    );
		    
		    // grid click
		    self.helper.category.find('li.heritageitem a.heritageitem-open').unbind().click(function(e){
		        e.preventDefault();
		        
		        self.helper.category.fadeOut(self.opts.animationTime);
		        
		        self.initItem($(this).parent().prevAll().length);
		        
		    });
		    
		    return;
		},
		
		/*
		 * Bind the category nav events
		 */
		bindCategoryNavEvents: function () {
		    
		    var self    = this;
		    
		    self.helper.categoryNav.find('a').unbind().click(function(e){
		        e.preventDefault();
		        
		        if (!$(this).hasClass('active'))
		            $(this).addClass('active').parent().siblings().children().removeClass('active');
		        
		        self.changeCategory(self.helper.categories.children()[$(this).parent().prevAll().length]);
		        
		    });
		    
		    return;
		},
		
		/*
		 * Initialize the item detail
		 */
		initItem: function (i) {
		    
		    var self    = this;
		    var item    = self.items[i];
		    
		    self.view   = 'item';
		    
		    // disable prev/next buttons
		    if (i == 0)
		    {
		        self.helper.itemControls.find('a.prev-heritageitem')
		            .addClass('disabled')
		            .siblings()
		                .removeClass('disabled')
		                ;
		    }
		    else if (i == self.items.length - 1)
		    {
		        self.helper.itemControls.find('a.next-heritageitem')
		            .addClass('disabled')
		            .siblings()
		                .removeClass('disabled')
		                ;
		    }
		    else
		    {
		        self.helper.itemControls.find('a')
		            .removeClass('disabled')
		            ;
		    }
		    
		    // set active item in item nav
		    $(self.helper.itemNav.children()[i]).find('a').addClass('active').parent().siblings().find('a').removeClass('active');
		    
		    // build the item detail
		    self.helper.itemDetail.find('div.heritageitem-info')
		        .append($(item).find('.heritageitem-title').clone())
		        .append($(item).find('.heritageitem-body').clone())
		        ;
		    
		    // load the detail image
		    $(new Image()).load(function(){
    		        
	            // append the image
	            self.helper.itemDetail.find('.heritageitem-image-container')
	                .append($(this).css('display', 'none'))
	                ;
		        
	            // show the image
	            $(this).fadeIn(self.opts.animationTime);
		        
	        }).attr('src', $.data($(item).find('img.heritageitem-detail-image').get(0), 'src'));
		    
		    // update the status
		    self.helper.itemStatus.find('.current').text(i + 1);
		    self.helper.itemStatus.find('.length').text(self.items.length);
		    
		    // show the item
		    self.helper.item.fadeIn(self.opts.animationTime, function(){
		        
		        self.bindItemEvents(i);
		        
		    });
		    
		    return;
		},
		
		/*
		 * Reset the item detail
		 */
		resetItem: function () {
		    
		    var self    = this;
		    
		    // empty the item detail
		    self.helper.itemDetail.find('div.heritageitem-info')
		        .empty()
		        ;
		    
		    self.helper.itemDetail.find('.heritageitem-image-container')
	            .empty()
	            ;
		    
		    return;
		},
		
		/*
		 * Bind the item events
		 */
		bindItemEvents: function (i) {
		    
		    var self    = this;
		    
		    // nav click
		    self.helper.itemNav.find('a').unbind().click(function(e){
		        e.preventDefault();
		        
		        if (!$(this).hasClass('active'))
		        {
		            self.resetItem();
		            self.initItem($(this).parent().prevAll().length);
		        }
		        
		    });
		    
		    // controls click
		    self.helper.itemControls.find('a').unbind().click(function(e){
		        e.preventDefault();
		        
		        $this = $(this);
		        
		        if ($this.hasClass('prev-heritageitem'))
		        {
		            if (i == 0)
		            {
		                //self.initItem(self.items.length - 1);
		            }
		            else
		            {
		                self.resetItem();
		                self.initItem(i - 1);
		            }
		        }
		        else if ($this.hasClass('next-heritageitem'))
		        {
		            if ((i + 1) == self.items.length)
		            {
		                //self.initItem(0);
		            }
		            else
		            {
		                self.resetItem();
		                self.initItem(i + 1);
		            }
		        }
		        
		    });
		    
		    // click off item returns to grid
		    self.helper.itemClose.unbind().click(function(e){
		        e.preventDefault();
		        
		        self.resetItem();
		        
		        self.changeCategory(self.helper.categories.children()[self.helper.categoryNav.find('a.active').parent().prevAll().length]);
		        
		    });
		    
		    
		    return;
		},
		
		/*
		 * Change the category
		 */
		changeCategory: function (category) {
		    
		    var self    = this;
		    
		    self.resetGrid();
		    
		    if (self.view == 'item')
		    {
		        self.helper.item.fadeOut(self.opts.animationTime, self.resetItem());
		    }
		    else if (self.view == 'category')
		    {
		        var $clone = self.helper.category.clone().insertAfter(self.helper.category);
		        
		        $clone.fadeOut(self.opts.animationTime, function(){
		            $clone.remove();
		        });
		        
		        self.helper.category.css('display', 'none');
		    }
		    
		    self.initGrid(category);
		    
		    return;
		}
		
	};
})(jQuery);