/************************************************/
/* Author: Brandon Drake						*/
/* Copyright: Tech Media Network 2011			*/
/* Version: 2.3.0     							*/
/* Date: Nov 10, 2011							*/
/* Info: This plugin is used to extend the		*/
/*  the functionality of jcarousel to fit the	*/
/*  needs of TMN on LaptopMag.com				*/
/* NOTE: Only works with element ID				*/
/* Requires:                                    */
/*  jCarousel                                   */
/************************************************/

(function ($) {
    var defaults = {
        path: '',
        thumbPath: '',
        fullPath: '',
        fullGallery: false,
        columns: 3,
        imgHeight: 50,
        imgWidth: 75,
        jsonScript: '', //'./scripts/json/benchmark.js'
        jsonObject: null,
        ajaxData: {},
        cssClass: 'jcarousel-skin-tango',
        onComplete: $.noop,
        fullPos: 'top',
        showCount: false,
        imgEvent: 'mouseenter', // 'click' or 'mouseenter'
        afterEvent: $.noop,
        imgEventOverride: $.noop,
        onLargeImgClick: function () {
	            $(this).data('imageSlider').caller = "large_image";
	            methods._next($(this), $(this).data('imageSlider'));
	        },
        vertical: false,
        showButtons: false,
        precache: false,
        sliderEvent: $.noop
    },
	methods = {
	    _init: function (options) {
	        return this.each(function () {
	            var $this = $(this),
					data = $this.data('imageSlider');

	            if (!data) {
	                if (options) {
	                    options = $.extend({}, defaults, options)
	                }

	                var elementID = $this.attr('id'),
						sliderID = elementID + '_slider',
						counterID = elementID + '_ct',
						targetID = elementID + "_target",
						data = {
						    element: $this,
						    elementID: elementID,
						    sliderID: sliderID,
						    counterID: counterID,
						    targetID: targetID,
						    options: options,
						    imageCache: null,
						    total: 0
						};

	                if (options.jsonObject === null) {
	                    methods._processAjax(data);
	                } else {
	                    methods._process(data);

	                    if (options.onComplete !== $.noop) {
	                        options.onComplete.call();
	                    }
	                }
	            }
	        });
	    },
	    _carousel_initCallBack: function (carousel, data) {
	        // Previous Button Click
	        $("#" + data.elementID + " .big_img .prev").bind('click', function () {

	            var slider = '#' + data.sliderID,
                    target = $("#" + data.targetID),
                    num = target.data("num") - 1;

	            num = num > 0 ? num : data.total;

	            carousel.scroll($.jcarousel.intval(num));
	            data.caller = "prev";
	            methods._changeImage(num, data);
	        });

	        // Next and Main Image Click
	        $("#" + data.elementID + " .big_img .next").bind('click', function () {
	            data.caller = "next";
	            methods._next(carousel, data);
	        });

	        $("#" + data.elementID + "_target").bind('click', data.options.onLargeImgClick);
	    },
	    _changeImage: function (num, data) {
	        var options = data.options,
				jsonObject = options.jsonObject,
				target = $("#" + data.targetID);

	        if (options.precache === true) {
	            target.attr('src', data.imageCache[num - 1].src);
	        } else {
	            var pos = target.offset(),
					e = {
					    pageX: (pos.left - 20) + (target.width() / 2),
					    pageY: (pos.top - 40) + (target.height() / 2)
					},
                    imgPath = (options.path + (options.fullGallery ? jsonObject[num - 1].img : options.fullPath + jsonObject[num - 1].image_id + ".jpg"));

	            $('.slider_loading').css({
	                "top": (e.pageY) + "px",
	                "left": (e.pageX) + "px"
	            }).show();

	            target.attr('src', imgPath);

	            //console.log(target);
	        }

	        methods._setActive(num, data);
	        target.data('num', num);

	        if (options.showCount === true) {
	            $('#' + data.counterID).text('Image ' + num + ' of ' + data.total.toString());
	        }

	        if (options.afterEvent !== $.noop) {
	            options.afterEvent.call(this, data.caller);
	        }
	    },
	    _next: function (carousel, data) {
	        var target = $("#" + data.targetID),
                slider = '#' + data.sliderID,
                num = parseInt(target.data("num")) + 1;

	        num = num <= data.total ? num : 1;

	        carousel.scroll($.jcarousel.intval(num));
	        methods._changeImage(num, data);
	    },
	    next: function () {
	        var data = $(this).data("imageSlider");
	        methods._next($("#" + data.sliderID).data("jcarousel"), data);
	    },
	    _process: function (data) {
	        var jsonData = data.options.jsonObject;

	        if (jsonData.length > 0) {
	            var options = data.options,
					total = data.total = jsonData.length,
                    imgSrc,
					imgNum,
                    loader = '<div class="slider_loading" ><p><img src="http://www.laptopmag.com/images/loading.gif" /></p></div>',
	                imgHtml = '<div class="big_img">' +
						((options.showButtons === true) ? '<div class="prev"><div class="arrow prev_arrow" /></div>' : '') +
						'<img id="' + data.elementID + '_target" src="" alt="" />' +
						((options.showButtons === true) ? '<div class="next"><div class="arrow next_arrow" /></div>' : '') +
						'</div>\n',
					counter = '<span id="' + data.counterID + '">Image 1 of ' + total + '</span>',
					html = ((options.fullPos === 'top') ? (imgHtml + (options.showCount ? counter : '')) : '') +
						 '<ul id="' + data.sliderID + '" class=" ' + options.cssClass + '" >\n',
	                tempImg = [],
                    tempCt = 1;

	            // Generate Thumbnail images HTML
	            for (var i = 0; i < total; i++) {
	                //Has to be done this way to make IE6 and IE7 happy
	                var imgType = jsonData[i].img.match(/\.(\w+)$/);

	                if (imgType) {
	                    imgType = imgType[1];
	                }
	                else {
	                    imgType = 'jpg';
	                }

	                html += '<li ' + ((i === 0) ? 'class="active"' : '') + '><img src="' + options.path + options.thumbsPath + jsonData[i].image_id + '.' + imgType +
					'" alt="' + jsonData[i].name +
					'" height="' + options.imgHeight + 'px" width="' + options.imgWidth + 'px" /><p>' + jsonData[i].name + '</p></li>';

	                // Set the first image as the image to display
	                if (i === 0) {
	                    imgSrc = (options.path + (options.fullGallery ? jsonData[i].img : options.fullPath + jsonData[i].image_id + ".jpg"));
	                    imgNum = 1;
	                }

	                //pre cache the large images to make it more snappy
	                if (options.precache === true) {
	                    tempImg[i] = new Image();
	                    tempImg[i].src = (options.path + (options.fullGallery ? jsonData[i].img : options.fullPath + jsonData[i].image_id + ".jpg"));
	                }
	            }

	            html += '</ul>\n' + ((options.fullPos === 'bottom') ? ((options.showCount ? counter : '') + imgHtml) : '');

	            data.element.html(html); // Added in this manner to make IE6 & 7 happy

	            var slider = $('#' + data.sliderID),    // Set it here so we only look for it once
				    target = $('#' + data.targetID);    // Set it here so we only look for it once

	            slider.find('li img').each(function () {
	                $(this).data('num', tempCt)
	                tempCt++;
	            });

	            // Set the initial main image information
	            target.attr('src', imgSrc);
	            target.data('num', imgNum);

	            slider.jcarousel({
	                scroll: options.columns,
	                vertical: options.vertical,
	                initCallback: function (carousel) {
	                    methods._carousel_initCallBack(carousel, data);
	                }
	            });

	            if (options.sliderEvent !== $.noop) {
	                $("#" + data.elementID + " .jcarousel-prev").click(function () {
	                    options.sliderEvent.call(this, "prev");
	                });

	                $("#" + data.elementID + " .jcarousel-next").click(function () {
	                    options.sliderEvent.call(this, "next");
	                });
	            }

	            if (options.imgEventOverride === $.noop) {
	                $('#' + data.sliderID + ' .jcarousel-item').bind(options.imgEvent, function () {
	                    data.caller = "thumbnail";
	                    methods._changeImage($(this).attr('jcarouselindex'), data);
	                });
	            } else {
	                options.imgEventOverride.call();
	            }

	            //console.log(target, options.precache, typeof options.precache);

	            if (options.precache === true && total > 0) {
	                $(function () {
	                    $('body').append(loader);
	                });

	                data.imageCache = tempImg;
	            } else {
	                target.load(function () {
	                    //console.log("Loading");
	                    $('.slider_loading').hide();
	                })
                    .error(function () {
                        //console.log("Loading Failed");
                        $('.slider_loading').hide();
                    });
	            }

	            $("#" + data.elementID).data('imageSlider', data);
	        }
	    },
	    _processAjax: function (data) {
	        var options = data.options;

	        $.ajax({
	            url: options.jsonScript,
	            type: 'GET',
	            data: options.ajaxData,
	            dataType: 'json',
	            success: function (jsonData) {
	                options.jsonObject = jsonData;
	                methods._process(data);
	            },
	            complete: function (jqXHR, textStatus) {
	                if (options.onComplete !== $.noop) {
	                    options.onComplete.call();
	                }
	            }
	        });
	    },
	    _setActive: function (num, data) {
	        var liElems = $("#" + data.sliderID + " li"),
	            nthChild = $(liElems[num - 1]);

	        liElems.removeClass("active");
	        nthChild.addClass("active");
	    }
	}

    $.fn.imageSlider = function (method) {
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof method === 'object' || !method) {
            return methods._init.apply(this, arguments);
        } else {
            $.error('Method ' + method + ' does not exist on jQuery.imageSlider');
        }
    };
})(jQuery);
