$.fn.extend({
    /**
     * Trailblazer for front pages
     */
    trailblazer: function(options) {
        
        // Define default options

        if (options == undefined) {
            options = {};
        }

        if (options.header == undefined) {
            options.header = true;
        }

        if (options.display == undefined) {
            options.display = true;
        }

        if (options.thumbnails == undefined) {
            options.thumbnails = true;
        }

        if (options.thumbnailOpacity == undefined) {
            options.thumbnailOpacity = 0.33;
        }

        if (options.activeThumbnailOpacity == undefined) {
            options.activeThumbnailOpacity = 0.85;
        }

        // Fetch children <divs> and construct an array of objects

        var divs = $(this).children('div');

        var panes = [];

        divs.each(function(i, e) {
            var obj = {
                header: $(this).children('h3'),
                image: {
                    element: $(this).children('h3').next(),
                    baseWidth: null,
                    baseHeight: null
                },
                content: $(this).children().not('h3, .links, .thumbnail').not($(this).children('h3').next()),
                links: $(this).children('.links'),
                thumbnail: $(this).children('.thumbnail')
            }
            obj.image.element.bind('load', function() {
                obj.image.baseWidth = $(this).width();
                obj.image.baseHeight = $(this).height();
            });
            panes.push(obj);
        });

        // Construct the trailblazer

        var trailblazer = $('<div class="trailblazer" />');

        // Construct the header

        var header = $('<div class="trailblazer-header" />');
        header.append($(this).children('h2').html());

        // Construct the description
        
        var description = $('<div class="trailblazer-description"><div /></div>');

        // Construct the pane

        var pane = $('<div class="trailblazer-pane"><div class="pane-contents" /></div>');
        var paneContents = $(pane).children('.pane-contents');
        paneContents.hide();

        // Construct the picker

        var picker = $('<div class="trailblazer-picker" />');

        var showRow = function() {
            var row = $(this);
            var items = $('.picker-row:visible').children('.picker-item');
            var fader = function() {
                if (items.length > 0) {
                    var item = items.eq(0);
                    items = items.slice(1);
                    item.fadeTo('fast', 0.0, fader);
                }
                else {
                    $('.picker-row:visible').hide();
                    row.show();
                    var itemsToShow = row.children('.picker-item');
                    var showFader = function() {
                        if (itemsToShow.length > 0) {
                            var itemToShow = itemsToShow.eq(0);
                            itemsToShow = itemsToShow.slice(1);
                            if (itemToShow.hasClass('active')) {
                                itemToShow.fadeTo('fast', options.activeThumbnailOpacity, showFader);
                            }
                            else {
                                itemToShow.fadeTo('fast', options.thumbnailOpacity, showFader);
                            }
                        }
                    }
                    showFader();
                }
            }
            fader();
        }

        var generateButtons = function() {
            var prev = $('<div class="prev"></div>');
            prev.click(function() {
                var previousRow = $(this).parents('.picker-row').prev('.picker-row');
                if (previousRow.length < 1) {
                    previousRow = $(this).parents('.picker-row').parent().children('.picker-row:last');
                }
                previousRow.each(showRow);
            });
            var next = $('<div class="next"></div>');
            next.click(function() {
                var nextRow = $(this).parents('.picker-row').next('.picker-row');
                if (nextRow.length < 1) {
                    nextRow = $(this).parents('.picker-row').parent().children('.picker-row:first');
                }
                nextRow.each(showRow);
            });
            return [prev, next];
        }

        var curPickerRow = $('<div class="picker-row" />');
        picker.append(curPickerRow);

        $.each(panes, function(i, e) {
            if (curPickerRow.children().length >= 3) {

                $.each(generateButtons(), function(i, e) {
                    curPickerRow.append(e);
                });
                curPickerRow.append('<div style="clear: both" />');

                curPickerRow = $('<div class="picker-row" />');
                picker.append(curPickerRow);

            }

            var pickerItem = $('<div class="picker-item" />');
            pickerItem.attr({index: i});
            pickerItem.append(panes[i].thumbnail.clone());

            var pickerItemDesc = $('<div class="item-description">');
            pickerItemDesc.append($('<div />').append(panes[i].header.html()));
            var itemText = panes[i].content.eq(0).text().replace('\n', ' ');
            var periodIndex = itemText.indexOf('. ');
            if (periodIndex < 0) {
                pickerItemDesc.append($('<div />').append(itemText));
            }
            else {
                pickerItemDesc.append($('<div />').append(itemText.substring(0, periodIndex + 1)));
            }

            // temp

            if (!options.display) {
                if (panes[i].links.find('a[href]').length > 0 && panes[i].links.find('a[href]:first').attr('href').substring(0, 1) != '#') {
                    pickerItemDesc.addClass('linkable');
                }
            }

            // end temp

            pickerItem.append(pickerItemDesc);

            pickerItem.hover(
                function() {
                    $(this).stop(true).animate({opacity: 1.0});
                },
                function() {
                    $(this).stop(true);
                    if ($(this).hasClass('active')) {
                        $(this).animate({opacity: options.activeThumbnailOpacity});
                    }
                    else {
                        $(this).animate({opacity: options.thumbnailOpacity});
                    }
                }
            );

            pickerItem.click(function() {
                if (options.display) {
                    pick(i);
                }
                else {
                    if (panes[i].links.find('a[href]').length > 0) {
                        window.location = panes[i].links.find('a[href]:first').attr('href');
                    }
                }
            });

            curPickerRow.append(pickerItem);
        });

        $.each(generateButtons(), function(i, e) {
            curPickerRow.append(e);
        });
        curPickerRow.append('<div style="clear: both" />');

        // ...generate a series of components

        var pick = function(i) {

            picker.find('.picker-item').removeClass('active');
            picker.find('.picker-item').eq(i).addClass('active');
            picker.find('.picker-item').not(picker.find('.picker-item').eq(i)).mouseout();

            var title = $('<div class="description-title" />');
            title.html(panes[i].header.html());

            description.stop(true).animate({opacity: 0, marginLeft: '-25px'}, 'slow', function() {
                paneContents.fadeOut('slow', function() {

                    description.children().empty();
                    paneContents.empty();

                    description.children('div').append(title).append(panes[i].content.clone()).append(panes[i].links.clone());

                    var show = function() {
                        if (panes[i].image.baseWidth == null){
                            setTimeout(show, 1000);
                        }
                        else {
                            var img = panes[i].image.element.clone();
                            img.attr('baseWidth', panes[i].image.baseWidth);
                            img.attr('baseHeight', panes[i].image.baseHeight);
                            paneContents.append(img);

                            resizePane();

                            description.animate({opacity: 1, marginLeft: '0px'}, 'slow', function() {
                                paneContents.fadeIn('slow');
                            });
                        }
                    }

                    show();
                });
            });
        }

        // Put everything together

        if (options.header) {
            trailblazer.append(header);
        }

        if (options.display) {
            trailblazer.append(description).append(pane).append('<div style="clear: both" />');
        }

        if (options.thumbnails) {
            trailblazer.append(picker);
        }

        // Insert the creation before the element on which this was called

        $(this).before(trailblazer);

        // And pick the first pane and set default states

        if (options.display) {
            pick(0);
        }
        $('.picker-row').hide().children('.picker-item').css({opacity: 0.0});
        $('.picker-row:first').each(showRow);

        // Resize the pane

        var resizePane = function() {

            pane.height(pane.width() / 1.75);
            
            // Determine how we want to scale

            var baseWidth = paneContents.children().attr('baseWidth');
            var baseHeight = paneContents.children().attr('baseHeight');
            
            var widthScaling = 1.0 * paneContents.width() / baseWidth;
            var heightScaling = 1.0 * paneContents.height() / baseHeight;

            if (widthScaling < heightScaling) {
                paneContents.children().width(baseWidth * widthScaling).height(baseHeight * widthScaling);
            }
            else {
                paneContents.children().width(baseWidth * heightScaling).height(baseHeight * heightScaling);
            }

        }

        $(window).bind('resize', function() {
            resizePane();
        });

        resizePane();

        trailblazer.hide().fadeIn();
        $(this).css({position: 'absolute', visibility: 'hidden', height: '1px', overflow: 'hidden'});

    }
});
