/* ---------------------------------------------------------------------
Global JavaScript & jQuery

Target Browsers: All
Authors: Jeremy Madrid, Dan Piscitiello
------------------------------------------------------------------------ */

var NERD = NERD || {};

$(function() {
    // Initialize!
    NERD.ExternalLinks.init();
    NERD.AutoReplace.init();
    NERD.JScrollPane.init();
    NERD.CustomInputs.init();
    NERD.FacebookLike.init();
});

/* ---------------------------------------------------------------------
Extend the Array Object in browsers that don't support Array.indexOf()
------------------------------------------------------------------------ */
// I had to comment out the below code. I was receiving a Type Mismatch with Sharepoint wsadder.js(trying to add a webpart to a page.
//if (!Array.prototype.indexOf) {
//    Array.prototype.indexOf = function(elt /*, from*/) {
//        var len = this.length >>> 0;
//        var from = Number(arguments[1]) || 0;
//        from = (from < 0) ? Math.ceil(from) : Math.floor(from);
//        if (from < 0) {
//            from += len;
//        }
//        for (; from < len; from++) {
//            if (from in this && this[from] === elt) {
//                return from;
//            }
//        }
//        return -1;
//    };
//}

/* ---------------------------------------------------------------------
FacebookLike
Author: Dan P

Configure the Facebook Like button
------------------------------------------------------------------------ */
NERD.FacebookLike = {
    $buttons: undefined,

    init: function() {
        var self = this;
        var $buttons = $('div.facebook-like');

        if (!$buttons) {
            return false;
        }

        self.$buttons = $buttons;
        self.setupButtons();
    },

    setupButtons: function() {
        var self = this;
        var markup = '<iframe src="http://www.facebook.com/plugins/like.php?app_id=' + NERD.fbAppId + '&amp;href=' + NERD.fbLikeUrl + '&amp;send=false&amp;layout=button_count&amp;width=93&amp;show_faces=false&amp;action=like&amp;colorscheme=light&amp;font&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:93px; height:21px;" allowTransparency="true"></iframe>';

        self.$buttons.each(
            function() {
                $(this).html(markup);
            }
        );
    }
};

/* ---------------------------------------------------------------------
CustomInputs

Set up any custom form elemnent inputs
------------------------------------------------------------------------ */
NERD.CustomInputs = {
    init: function() {
        if ($('.filter-pens').length) {
            var penFilters = new CustomFormElements({
                checkboxHeight: 8
            });
        }
    }
};

/* ---------------------------------------------------------------------
jScrollPane

Initialize jScrollPane on specific elements
------------------------------------------------------------------------ */
NERD.JScrollPane = {
    init: function() {
        var scrollers = $('div.scroll-me');

        if (!scrollers.length) {
            return false;
        }

        scrollers.jScrollPane(
            {
                showArrows: true,
                verticalGutter: 30,
                animateScroll: true
            }
        );

        this.bind();
    },

    bind: function() {
        if ($('ul.faq-questions').length) {
            this.bindFaq();
        }
    },

    bindFaq: function() {
        var api = $('div.scroll-me').data('jsp');
        var qs = $('ul.faq-questions');
        var as = $('ul.faq-answers');

        qs.delegate('a', 'click',
            function(e) {
                e.preventDefault();
                api.scrollToElement($(this).attr('href'), true)
            }
        );

        as.delegate('a.faq-top', 'click',
            function(e) {
                e.preventDefault();
                api.scrollToElement($(this).attr('href'), true)
            }
        );
    }
};

/* ---------------------------------------------------------------------
ExternalLinks
Author: Nerdery Boilerplate

Launches links with a rel="external" in a new window
------------------------------------------------------------------------ */

NERD.ExternalLinks = {
    init: function() {
        $('a[rel=external]').attr('target', '_blank');
    }
};

/* ---------------------------------------------------------------------
AutoReplace
Author: Nerdery Boilerplate

Mimics HTML5 placeholder behavior

Additionally, adds and removes 'placeholder-text' class, used as a styling
hook for when placeholder text is visible or not visible

Additionally, prevents forms from being
submitted if the default text remains in input field - which we may 
or may not want to leave in place, depending on usage in site
------------------------------------------------------------------------ */
NERD.AutoReplace = {
    $fields: undefined,

    init: function() {
        var $fields = $('[placeholder]');

        if ($fields.length !== 0) {
            var self = this;
            self.$fields = $fields.addClass('placeholder-text');
            self.bind();
        }
    },

    bind: function() {
        var self = this;

        self.$fields.each(
            function() {
                var me = $(this);
                var defaultText = me.attr('placeholder');
                me.attr('placeholder', '').val(defaultText);

                me.focus(
                    function() {
                        if (me.val() === defaultText) {
                            me.val('').removeClass('placeholder-text');
                        } 
                    }
                );

                me.blur(
                    function() {
                        if (me.val() === '') {
                            me.val(defaultText).addClass('placeholder-text');
                        }
                    }
                );

                me.parents('form').submit(
                    function() {
                        if (me.is('.required') && (me.val() === defaultText || me.val() === "")) {
                            return false;
                        }
                    }
                );
            }
        );
    }
};

/* ---------------------------------------------------------------------
Products
Author: Dan P

Controls loading and filtering of product data
------------------------------------------------------------------------ */

NERD.Products = {
    productData: undefined, // json object of product data
    $list: undefined,       // dom element holding our product LI's
    $filters: undefined,    // the filter menu items
    $scroller: undefined,   // custom scroll element
    activeProducts: [],     // array of active product id's

    init: function(url) {
        var self     = this;
        var $list    = $('ul.pens-list');
        var $filters = $('div.filter-pens');

        // If pens-list or filter inputs don't exist, stop execution
        if (!$list.length || !$filters.length) {
            return false;
        }

        // Assign DOM elements as properties of this object
        self.$list    = $list;
        self.$filters = $filters;

        // Init complete, bind events
        self.bind();
        
        // Init complete, load product data, render initial list on callback
        self.loadProductData(url, self.renderInitialList);
    },

    bind: function() {
        var self = this;

        // Change event for filter inputs
        self.$filters.delegate('input', 'change',
            function() {
                NERD.Pens.hideAllDetails();
                self.filterProducts();
            }
        );


        // Click event for 'show all pens' links
        $('#form-pen-filter').delegate('a.reset-filters', 'click',
            function(e) {
                e.preventDefault();
                self.clearFilters();
            }
        );
    },

    loadProductData: function(url, callback) {
        var self = this;

        $.ajax({
            url: url,
            dataType: 'json',
            success: function(data) {
                self.productData = data.products;
                callback.call(self);
            },
            error: function() {
                self.$list.html('<li style="display: list-item;" class="filter-error">An error has occurred loading product data, please reload this page.</li>');
            } 
        });
    },

    renderInitialList: function() {
        var self = this;
        var fragment = document.createDocumentFragment();

        for (var i = 0; i < self.productData.length; i++) {
            fragment.appendChild(NERD.Pens.parseItem(self.productData[i], i));
            self.activeProducts.push(i);
        }

        self.$list.get(0).appendChild(fragment.cloneNode(true));

        NERD.Pens.init();        // all pens now exist in DOM, initialize pens' behaviors
        self.customScrollInit(); // all pens now exist in DOM, initialize custom scrollbars
        self.parseUrlFilters();  // Check for filter query on url
        self.filterProducts();   // Initial list is rendered, now filter the list in case the page has been reloaded
    },

    // Set up jScrollPane for products
    customScrollInit: function() {
        var self = this;
        self.$scroller = $('div.products-scroll')
        self.$scroller.jScrollPane(
            {
                showArrows: true,
                verticalGutter: 30,
                animateScroll: true,
                animateDuration: 1000,
                animateEase: 'easeInOutQuad'
            }
        );
    },

    // Check the URL for any pre-populating filters
    parseUrlFilters: function() {
        var filters = window.location.href.substr(window.location.href.indexOf('?') + 1, window.location.href.length);
        filters = filters.split('&');

        for (var i = 0; i < filters.length; i++) {
            $('#filter-' + filters[i]).click();
        }
    },

    // Uncheck all filters
    clearFilters: function() {
        var self = this;
        self.$filters.find('input:checked').trigger('click').trigger('change'); // both click() and change() required to work in IE
    },

    // Constructs array of activeProducts based on filter values
    filterProducts: function() {
        var self     = this;
        var $inputs  = self.$filters.find('input:checked');
        var $resets  = $('a.reset-filters');
        var filters  = {};
        var systems  = [];
        var types    = [];
        var sizes    = [];
        var colors   = [];
        var features = [];
        var temp     = [];

        self.activeProducts = [];

        // If no filters are checked, show all products
        if (!$inputs.length) {
            self.showAllProducts();
            $resets.fadeOut();
            return;
        }

        // If a filter is checked, fade in the reset links
        $resets.fadeIn();

        // Further filter the inputs down by type
        filters.$systems  = $inputs.filter('#js-filter-system input');
        filters.$type     = $inputs.filter('#js-filter-type input');
        filters.$size     = $inputs.filter('#js-filter-size input');
        filters.$color    = $inputs.filter('#js-filter-color input');
        filters.$features = $inputs.filter('#js-filter-features input');

        // Loop through each pen and filter it by checked inputs
        for (i = 0; i < self.productData.length; i++) {
            //filter this pen by system
            if (filters.$systems.length) {
                filters.$systems.each(
                    function() {
                        if (self.productData[i].system === $(this).val()) {
                            systems.push(i);
                        }
                    }
                );
            }
            //filter this pen by type
            if (filters.$type.length) {
                filters.$type.each(
                    function() {
                        if (self.productData[i].type === $(this).val()) {
                            types.push(i)
                        }
                    }
                );
            }
            //filter this pen by size
            if (filters.$size.length) {
                filters.$size.each(
                    function() {
                        if (self.filterBySize($(this).val(), self.productData[i])) {
                            sizes.push(i);
                        }
                    }
                );
            }
            //filter this pen by color
            if (filters.$color.length) {
                filters.$color.each(
                    function() {
                        if (self.filterByColor($(this).val(), self.productData[i])) {
                            colors.push(i);
                        }
                    }
                );
            }
            //filter this pen by features
            if (filters.$features.length) {
                filters.$features.each(
                    function() {
                        // indexOf method wasn't working in IE in Sharepoint, changed it to the jquery inArray, wwh 11/20/11
	                    if ($.inArray($(this).val(), self.productData[i].keyfeatures) !== -1) {
                        //if (self.productData[i].keyfeatures.indexOf($(this).val()) !== -1) {
                            features.push(i);
                        }
                    }
                );
            }
        }

        // Only add non empty filters to temp
        if (systems.length) {
            temp.push(systems);
        }
        if (types.length) {
            temp.push(types);
        }
        if (sizes.length) {
            temp.push(sizes);
        }
        if (colors.length) {
            temp.push(colors);
        }
        if (features.length) {
            temp.push(features);
        }

        // If only one checkbox checked, use the only item in temp
        if ($inputs.length === 1) {
            self.activeProducts = temp[0];
            self.renderFilteredList(); // List has been filtered, now display appropriate items
            return;
        } 

        // If there's more than one checkbox checked there's only one category in temp,
        // load active products up with just items from that category
        if ($inputs.length > 1 && temp.length === 1) { 
            for (var i = 0; i < temp[0].length; i++) {
                self.activeProducts.push(temp[0][i]);
            }
            self.renderFilteredList(); // List has been filtered, now display appropriate items
            return;
        }

        // If there's more than one checkbox checked and more than one category represented,
        // find only pens with shared values
        if ($inputs.length > 1 && temp.length > 1) {
            self.findSharedValues(temp);
            self.renderFilteredList(); // List has been filtered, now display appropriate items
            return;
        }
    },

    filterBySize: function(value, pen) {
        var self = this;
        var sizes = pen.pointsize;

        for (var i = 0; i < sizes.length; i++) {
            if (value === "0.38 mm - 0.5 mm" && (sizes[i] >= 0.38 && sizes[i] <= 0.5)) {
                return true;
            }
            if (value === "0.6 mm - 0.7 mm" && (sizes[i] >= 0.6 && sizes[i] <= 0.7)) {
                return true;
            }
            if (value === "0.8 mm - 1.0 mm" && (sizes[i] >= 0.8 && sizes[i] <= 1)) {
                return true;
            }
        }

        return false;
    },

    filterByColor: function(value, pen) {
        var self = this;
        var colors = pen.colors;

        for (var i = 0; i < colors.length; i++) {
            if (colors[i] === value) {
                return true;
            } else if (value === "Other" && (colors[i] !== "Black" && colors[i] !== "Blue" && colors[i] !== "Red" && colors[i] !== "")) {
                return true;
            }            
        }

        return false;
    },

    // Compares the arrays in data argument and constructs new activeProducts
    // array containing only pen id's that are found across all filtered categories
    findSharedValues: function(data) {
        var self = this;
        var hits = [];
        var id   = undefined;
        
        data.sort(self.sortNumbers);

        for (var i = 0, pass; i < data[0].length; i++) {
            id = data[0][i];
            pass = true;
            for (var j = 1; j < data.length; j++) {
                // indexOf method wasn't working in IE in Sharepoint, changed it to the jquery inArray, wwh 11/20/11            
                if ($.inArray(id, data[j]) ===  -1) {
                //if (data[j].indexOf(id) === -1) {
                    pass = false;
                }
            }
            
            if (pass && $.inArray(id, hits) ===  -1) {
            // indexOf method wasn't working in IE in Sharepoint, changed it to the jquery inArray, wwh 11/20/11            
            //if (pass && hits.indexOf(id) === -1) {
                hits.push(id);
            }
        }

        self.activeProducts = hits;
        self.renderFilteredList();
    },

    // Sorting function: sort arrays by length
    sortNumbers: function(a, b) {
        return a.length - b.length;
    },

    renderFilteredList: function() {
        var self = this;
        // Start off by hiding all pens and error messages
        var $errMsg = $('li.filter-error').hide();
        self.$list.children().hide();

        // If there are no products in the activeProducts array, show error
        if (self.activeProducts.length === 0) {
            $errMsg.show();
            self.$scroller.data('jsp').reinitialise();
            return false;
        }

        // Find each item in the filtered list by id and show
        for (var i = 0; i < self.activeProducts.length; i++) {
            self.$list.find('#pen-id-' + self.activeProducts[i]).show();
        }

        self.$scroller.data('jsp').reinitialise();
    },

    showAllProducts: function() {
        this.$list.children().show();
        this.$list.find('li.filter-error').hide();
        this.$scroller.data('jsp').reinitialise();
    }
};

/* ---------------------------------------------------------------------
Pens
Author: Dan P

Controls rendering and events for individual pens
------------------------------------------------------------------------ */
NERD.Pens = {
    $pens: undefined,       // jquery collection of individual pen DOM elements
    $details: undefined,    // jquery collection of just the pen details elements

    init: function() {
        var self = this;
        var $pens = $('#js-pens-list');
        var $details = $pens.find('div.pen-expanded');

        if (!$pens.length || !$details.length) {
            return false;
        }

        self.$pens = $pens;
        self.$details = $details;
        self.bind();
        self.initCarousel();
    },

    bind: function() {
        var self = this;

        // Click event on Pen in listing grid
        self.$pens.delegate('div.pen', 'click',
            function() {
                var me = $(this);
                self.hideAllDetails();
                self.showMyDetails(me);
                me.addClass('active');
                return false;
            }
        );

        // Click event on either pen details close button
        self.$details.delegate('a.close-box, a.close-pen-carousel', 'click',
            function() {
                self.hideAllDetails();
                return false;
            }
        );

        // Click event on a pen detail thumb, to open gallery view
        self.$details.delegate('ul.pen-gallery a', 'click',
            function() {
                var me       = $(this);
                var href     = me.attr('href');
                var carousel = me.parents('div.pen-expanded').find('div.pen-carousel').show();

                self.showCarouselImage(carousel, href);
                return false;
            }
        );

        // Click event on pen carousel thumb, to load large image
        self.$details.delegate('ul.pen-detail-carousel a', 'click',
            function() {
                var me = $(this);
                var href = me.attr('href');
                var carousel = me.parents('div.pen-carousel');

                self.showCarouselImage(carousel, href);
                return false;
            }
        );

        // Click event to retrun from gallery view to detail view
        self.$details.delegate('a.carousel-back', 'click',
            function() {
                $(this).parents('div.pen-carousel').hide();
                return false;
            }
        );
    },

    hideAllDetails: function() {
        var self = this;

        NERD.Products.$list.children('li.active')
            .removeClass('active')
            .removeClass('alt-right')
            .removeClass('alt-bottom')
            .removeClass('alt-middle')
        ;

        self.$pens.find('div.pen.active').removeClass('active');

        self.$details.find('div.pen-carousel').hide();
    },

    showMyDetails: function($el) {
        var $parent         = $el.parents('li');
        var $details        = $parent.find('div.pen-expanded');
        var parentPosition  = $parent.position();
        var viewportWidth   = NERD.Products.$list.width();
        var viewportHeight  = NERD.Products.$list.parents('div.products-scroll').height();
        var scroller        = NERD.Products.$scroller.data('jsp');
        var contentHeight   = scroller.getIsScrollableV() ? scroller.getContentHeight() : viewportHeight;
        var detailsWidth    = undefined;
        var detailsHeight   = undefined;
        var detailsPosition = undefined;

        $parent.addClass('active');

        detailsWidth    = $details.width();
        detailsHeight   = $details.height();
        detailsPosition = $details.position();

        // If details width would exceed viewport, switch it to the left
        if ((viewportWidth - parentPosition.left) < (detailsWidth + detailsPosition.left)) {
            $parent.addClass('alt-right');
        }

        // If I'm not at the top or bottom, show details in the middle
        if ((parentPosition.top > 0 && detailsHeight <= viewportHeight)) {
            $parent.addClass('alt-middle');
            detailsPosition = $details.position();
        }

        // If I'm at the bottom and exceed the scroll area, show details higher
        if ((contentHeight - parentPosition.top < detailsHeight + detailsPosition.top) && (detailsHeight + detailsPosition.top + parentPosition.top > contentHeight)) {
            $parent.removeClass('alt-middle').addClass('alt-bottom');
        }

        scroller.scrollToY(parentPosition.top + detailsPosition.top, true);
    },

    initCarousel: function() {
        var $carousels = $('ul.pen-detail-carousel');

        if (!$carousels.length) {
            return false;
        }

        $carousels.each(
            function() {
                var me = $(this);
                var items = me.find('li').length;

                if (items > 3) {
                    me.jcarousel({
                        scroll: 1,
                        wrap: 'circular'
                    });
                } else {
                    me.jcarousel({
                        scroll: 1
                    });
                    me.parents('div.jcarousel-container').find('div.jcarousel-next, div.jcarousel-prev').css('visibility', 'hidden');
                }

            }
        );
    },

    showCarouselImage: function(carousel, href) {
        var img = carousel.find('div.pen-carousel-image img');

        img.unbind('load').load(
            function() {
                img.fadeIn();
            }
        );

        if (img.attr('src') === href) {
            return false;
        }
        
        img.hide().attr('src', href);
    },

    // Constructs markup for each pen in the products.json file
    parseItem: function(product, id) {
        var self   = this;
        var markup = '';

        markup += '<li id="pen-id-' + id + '">';
        markup +=   '<div class="pen ' + product.system.toLowerCase() + '">';
        markup +=       '<span>+</span>';
        markup +=       '<img src="/SiteCollectionImages/products/' + product.thumbnail + '" alt="' + product.shortname +'" />';
        markup +=       '<div class="pen-name">' + product.shortname + '</div>';
        markup +=   '</div>';
        markup +=   '<span class="pen-arrow"></span>';
        markup +=   '<div class="pen-expanded">';
        markup +=       '<a class="close-box" href="#">close</a>';
        markup +=       '<img class="pen-full" src="/SiteCollectionImages/products/' + product.heroimage + '" alt="" />';
        markup +=       '<div class="pen-detailed-titles">';
        markup +=           '<h2 class="pen-detailed-brand">uni-ball&reg;</h2>';
        markup +=           '<h3 class="pen-detailed-product">' + product.title + '</h3>';
        markup +=           '<h4 class="pen-detailed-type">' + product.subtitle + '</h4>';
        markup +=           '<div class="pen-facebook-like">';
        markup +=               '<a target="_blank" href="' + encodeURI('http://www.facebook.com/dialog/feed?app_id=' + NERD.fbAppId + '&link=' + window.location.href + '&redirect_uri=' + window.location.href +  '&picture=' + NERD.baseUrl + '/SiteCollectionImages/products/' + product.thumbnail + '&name=' + product.title + '&description=' + (product.copy[0].replace('<b>', '')).replace('</b>', '')) + '">Share</a>';
        markup +=           '</div>';
        markup +=       '</div>';
        markup +=       '<div class="pen-detailed-attributes">';
        markup +=           '<h5 class="pen-detailed-attributes-heading">Key Features</h5>';

        for (var i = 0; i < product.copy.length; i++) {
            markup +=           '<p>' + product.copy[i] + '</p>';
        }

        if (product.colors && product.colors[0] !== '') {

            markup +=           '<h5 class="pen-detailed-attributes-heading ink-colors">Ink colors</h5>';
            markup +=           '<ul class="pen-detailed-colors">';

            for (var i = 0, file = ''; i < product.colors.length; i++) {
                markup +=           '<li><img src="/SiteCollectionImages/products/' + (product.colors[i].replace(' ', '')).replace('/', '') + '.png" alt="' + product.colors[i] + '" /></li>';
            }

            markup +=           '</ul>';
            
        }

        markup +=           '<h5 class="pen-detailed-attributes-heading point-sizes">Point size</h5>';
        markup +=           '<ul class="pens-point-sizes">';
  
        for (var i = 0; i < product.pointsizethumb.length; i++) {
            markup +=           '<li><img src="/SiteCollectionImages/products/' + product.pointsizethumb[i] + '" alt="" /></li>';
        }

        markup +=           '</ul>';
        markup +=       '</div>';

        if (product.footnote && product.footnote !== '') {
            markup +=   '<p class="footnote">' + product.footnote + '</p>';
        }

        markup +=       '<ul class="pen-gallery">';

        // We only want the first three gallery thumbnails
        for (var i = 0, thumbUrl = ''; i < 3 && i < product.gallery.length; i++) {
            thumbUrl = product.gallery[i].indexOf('.jpg');
            thumbUrl = product.gallery[i].substring(0, thumbUrl) + '_thumb.jpg';

            markup +=        '<li><a href="/SiteCollectionImages/products/' + product.gallery[i] + '"><img src="/SiteCollectionImages/products/' + thumbUrl + '" alt="" /><span>+</span></a></li>';
        }

        markup +=       '</ul>';

        markup +=       '<div class="pen-carousel">';
        markup +=           '<div class="pen-carousel-image"><img src="/SiteCollectionImages/products/' + product.gallery[0] + '" alt="" /></div>';
        markup +=           '<ul class="pen-detail-carousel">';

        for (var i = 0, thumbUrl = ''; i < product.gallery.length; i++) {
            thumbUrl = product.gallery[i].indexOf('.jpg');
            thumbUrl = product.gallery[i].substring(0, thumbUrl) + '_thumb.jpg';

            markup +=           '<li><a href="/SiteCollectionImages/products/' + product.gallery[i] + '"><img src="/SiteCollectionImages/products/' + thumbUrl + '" alt="" /><span>+</span></a></li>';
        }

        markup +=           '</ul>';
        markup +=           '<a href="#" class="close-pen-carousel">close</a>';
        markup +=           '<a href="#" class="carousel-back">details</a>';
        markup +=       '</div>';
        markup +=   '</div>';
        markup += '</li>';

        return $(markup).get(0);
    }
};

/* ---------------------------------------------------------------------
PensDetails
Author: Dan P

Controls pen detail actions in the footer
------------------------------------------------------------------------ */
NERD.PenDetails = {
    $links: undefined,
    $panes: undefined,

    init: function() {
        var self   = this;
        var $links = $('#js-feature-list');
        var $panes = $('#js-feature-panes > div');

        if (!$links.length || !$panes.length) {
            return false;
        }

        self.$links = $links;
        self.$panes = $panes;
        self.bind();
    },

    bind: function() {
        var self = this;

        self.$links.delegate('a', 'click', function(e){
            var me = $(this);

            e.preventDefault();

            if (me.hasClass('active-detail')) {
                return false;
            }

            me.parents('ul').find('li.active-detail').removeClass('active-detail');
            me.parent().addClass('active-detail');

            self.$panes.hide().eq(me.parent().index()).show();

            return false;
        });
    }
};
