; (function ($) {

    $.scroller = function (opt) {
        return $.scroller.impl.init(this, opt);
    };


    $.fn.scroller = function (opt) {
        return $.scroller.impl.init(this, opt);
    };


    $.scroller.defaults =
    {
        left: 0
        , last: 0
        , name: "scroller"
        , next: "Next"
        , prev: "Prev"
        , scrollerclass: "scroller"
        , navpos: "inline"
        , navclass: "scroller-nav"
        , child: "a"
        , auto: true
        , speed: "2000"
        , loading: "Loading images..."
        , direction: "left"
        , panel: null
        , mask: null
        , btnnext: null
        , btnprev: null
        , loadImgs: 0
        , intVal: null
        , self: null
        , click: function (obj) {}
    };

    $.scroller.impl =
    {
        scroller: Array(),

        init: function (mask, opt) {


            var self = this;
            scroller = $.extend({}, $.scroller.defaults, opt);
            scroller.self = self;

            self.push(scroller);
            scroller.mask = mask
            scroller.panel = $("<div/>").addClass(scroller.scrollerclass);
            $(scroller.mask).parent().append(scroller.panel);

            scroller.panel.append(scroller.mask);

            scroller.mask.css({ overflow: "hidden" });
            scroller.mask.append(
				"<div style='clear:both; padding: 0px; margin: 0px;'>"
			);
            self.load(scroller);
            self.autoplay(scroller);
        },

        push: function (obj) {
            this.scroller.push(obj);
        },

        load: function (scroller) {
            var totImg = 0;
            var self = scroller.self;

            $("img", scroller.mask).load(
				function () {
				    scroller.loadImgs++;
				}
			);
            $.each(scroller.mask.children(":not(div)"), function () {
                switch (scroller.direction) {
                    case 'left':
                    case 'right':
                        if ($(this).children().length) {
                            $(this).width($(this).children(":eq(0)").width());
                        }
                        totImg += $(this).width();
                        break;
                    case 'top':
                    case 'bottom':
                        $(this).css("display", "block");
                        if ($(this).children().length) {
                            $(this).height($(this).children(":eq(0)").height());
                        }
                        totImg += $(this).height();
                        break;
                }

                $(this).css({
                    margin: "0px"
									, padding: "0px"
									, clear: "both"
                });

                $(this).bind("click", function () {
                    return scroller.click(this);

                }).bind("mouseover", function () {
                    if (scroller.auto) $("div:eq(0)", scroller.mask).stop();                                   
                }).bind("mouseout", function () {
                    if (scroller.auto) self.scrollStart(scroller);
                });

                $("div:eq(0)", scroller.mask).append($(this));
            });

            switch (scroller.direction) {
                case 'left':
                    $("div:eq(0)", scroller.mask).css("width", totImg + "px");
                    break;

                case 'right':
                    $("div:eq(0)", scroller.mask).css("width", totImg + "px");
                    $("div:eq(0)", scroller.mask).css({
                        marginLeft: -(totImg - scroller.mask.width()) + "px"
                    });
                    break;

                case 'top':
                    $("div:eq(0)", scroller.mask).css("height", totImg + "px");
                    break;

                case 'bottom':
                    $("div:eq(0)", scroller.mask).css("height", totImg + "px");
                    $("div:eq(0)", scroller.mask).css({
                        marginTop: -(totImg - scroller.mask.height()) + "px"
                    });
                    break;
            }
        },

        autoplay: function (scroller) {
            var self = scroller.self;
            if (scroller.auto) {
                $("<div/>").css({ clear: "both" }).appendTo(scroller.panel);
                self.scrollStart(scroller);
            }
            else {

                scroller.btnprev = $("<div/>").css({ cursor: "pointer" }).html(scroller.prev)
                .addClass('btnprev').click(function () {
                    self.turnLeft(scroller)
                });
                scroller.btnnext = $("<div/>").css({ cursor: "pointer" }).html(scroller.next)
                .addClass('btnnext').click(function () {
                    self.turnRight(scroller)
                });

                scroller.mask.height($("div:eq(0)", scroller.mask).height());

                if (scroller.navpos == "inline") {
                    scroller.mask.before(scroller.btnprev.css({ float: "left", height: scroller.mask.height() }))
                    .after(scroller.btnnext.css({ float: "right", height: scroller.mask.height() }))
                    .css({ float: "left" });
                    scroller.panel.width(scroller.mask.width() + scroller.btnprev.width() + scroller.btnnext.width());

                } else if (scroller.navpos == "top") {
                    var tmp = $("<div/>").css({ clear: "both", display: "block" })
                    .addClass(scroller.navclass)
                    .append(scroller.btnprev.css({ float: "left" }))
                    .append(scroller.btnnext.css({ float: "right" }));
                    scroller.mask.before(tmp);
                    tmp.height(scroller.btnprev.height());

                } else {
                    var tmp = $("<div/>").css({ clear: "both", display: "block" })
                    .addClass(scroller.navclass)
                    .append(scroller.btnprev.css({ float: "left" }))
                    .append(scroller.btnnext.css({ float: "right" }));
                    scroller.panel.append(tmp);
                    tmp.height(scroller.btnprev.height());
                }
                $("<div/>").css({ clear: "both" }).appendTo(scroller.panel);
            }

        },
        turnLeft: function (scroller) {
            var self = scroller;
            var panel = $("div:eq(0)", self.mask);
            var left = panel.offset().left;
            var mwidth = self.mask.width();
            var pwidth = panel.width();
            var iwidth = $("img:eq(0)", self.mask).outerWidth();
            var width = mwidth - (mwidth % iwidth);


            if (left < self.left) {
                if (self.left == 0)
                    self.left = left; //> width - pwidth ? left : pwidth % iwidth - pwidth)
                panel.animate({ marginLeft: left + width - self.left }, scroller.speed);
            }
            else {
                panel.stop();
            }

        },

        turnRight: function (scroller) {
            var self = scroller;
            var panel = $("div:eq(0)", self.mask);
            var left = panel.offset().left;
            var mwidth = self.mask.width();
            var pwidth = panel.width();
            var iwidth = $("img:eq(0)", self.mask).outerWidth();
            var width = mwidth - (mwidth % iwidth);

            if (left > self.left + width - pwidth) {
                if (self.left == 0)
                    self.left = left; //> width - pwidth ? left : pwidth % iwidth - pwidth)
                panel.animate({ marginLeft: left - width - self.left }, scroller.speed);
            }
            else {
                panel.stop();
            }
        },


        scrollStart: function (scroller) {
            var self = scroller.self;
            var scroll = $("div:eq(0)", scroller.mask);

            switch (scroller.direction) {
                case 'left':
                    var pos = -(scroll.children(":eq(0)").width());
                    var spd = scroller.speed;
                    if (scroll.children(":eq(0)").width() != null && scroll.children(":eq(0)").width() != 0)
                        spd = scroller.speed - (Math.abs(parseInt(scroll.css("marginLeft"))) * (scroller.speed / scroll.children(":eq(0)").width()));

                    break;

                case 'right':

                    var pos = -(scroll.width() - scroll.parents("div:eq(0)").width()) + scroll.children(":last").width();
                    var spd = scroller.speed;
                    if (scroll.children(":last").width() != null && scroll.children(":last").width() != 0)
                        spd = scroller.speed - ((scroll.children(":last").width() - (Math.abs(parseInt(scroll.css("marginLeft"))) - Math.abs(pos))) * (scroller.speed / scroll.children(":last").width()));
                    break;

                case 'top':
                    var tos = -(scroll.children(":eq(0)").height());
                    var spd = scroller.speed;
                    if (scroll.children(":eq(0)").height() != null && scroll.children(":eq(0)").height() != 0)
                        spd = scroller.speed - (Math.abs(parseInt(scroll.css("marginTop"))) * (scroller.speed / scroll.children(":eq(0)").height()));
                    break;

                case 'bottom':
                    var tos = -(scroll.height() - scroll.parents("div:eq(0)").height()) + scroll.children(":last").height();
                    var spd = scroller.speed;
                    if (scroll.children(":last").height() != null && scroll.children(":last").height() != 0)
                        spd = scroller.speed - ((scroll.children(":last").height() - (Math.abs(parseInt(scroll.css("marginTop"))) - Math.abs(tos))) * (scroller.speed / scroll.children(":last").height()));
                    break;
            }
            scroll.animate(
            {
                marginLeft: (pos || "0") + "px", marginTop: (tos || "0") + "px"
            }, spd, "linear", function () {
                switch (scroller.direction) {
                    case 'left':
                        scroll.append($(this).children(":eq(0)"));
                        scroll.css("marginLeft", "0px");
                        break;

                    case 'right':
                        scroll.prepend($(this).children(":last"));
                        scroll.css("marginLeft", -(scroll.width() - scroll.parents("div:eq(0)").width()) + "px");
                        break;

                    case 'top':
                        scroll.append($(this).children(":eq(0)"));
                        scroll.css("marginTop", "0px");
                        break;

                    case 'bottom':
                        scroll.prepend($(this).children(":last"));
                        scroll.css("marginTop", -(scroll.height() - scroll.parents("div:eq(0)").height()) + "px");
                        break;
                }

                self.scrollStart(scroller);
            });
        }
    };
})(jQuery);
