(function($) {

    $.carousel = function(el, options) {
        var base = this, o;

        base.$el = $(el).addClass('carousel_base').wrap('<div class="carousel_w"><div class="carousel" /></div>');

        // Add a reverse reference to the DOM object
        base.$el.data("carousel", base);

        base.init = function() {
            base.options = $.extend({}, $.carousel.defaults, options);
            base.$wrapper = base.$el.parent().closest('div.carousel_w');
            base.$window = base.$el.closest('div.carousel');
            base.$frames = base.$el.children('li')
            base.$slideControl = $('<ul class="carousel_frame_controls"></ul>').appendTo(base.$wrapper);
            for (var i = 0; i < base.$frames.length; i++) {
                var s = $('<li><a href="#" rel="' + i + '"></a></li>').appendTo(base.$slideControl);
            }
            base.$slideControls = base.$slideControl.children('li');
            base.currentFrame = 0;


            // set sizes
            base.$window.width(base.options.width).height(base.options.height);
            $.each(base.$frames, function(index, value){
                $(this).height(base.options.height).width(base.options.width).addClass('carousel_frame');
            });
            base.$el.width(base.options.width * base.$frames.length).height(base.options.height);


            // Trigger the event initialization
            base.initEvents();
            base.slideTo(base.options.defaultFrame);
        };

        base.initEvents = function() {
            base.$slideControl.find('a').click(function(e) {
                e.preventDefault();

                //alert($(this).attr('rel'));

                base.stopRotate().slideTo($(this).attr('rel'));
            });

            base.rotate();
        };

        base.slideTo = function(frameNo) {
            base.currentFrame = frameNo;
            base.makeControlActive();

            var newPosition = -1 * (frameNo * base.options.width);

            switch(base.options.effect) {
                case 'fade':
                    base.$el.stop().fadeOut(base.options.animationTime / 2, function() {
                        base.$el.css('left', newPosition);
                        base.$el.fadeIn(base.options.animationTime / 2, function(){
                            base.$el.trigger('afterChange', base.$el.data('carousel'));

                        });
                    });
                    break;

                case 'slide':
                default:
                    base.$el.stop().animate({
                        left: newPosition
                    }, base.options.animationTime, base.options.easing, function(){
                        base.$el.trigger('afterChange', base);
                    });
                    break;
            }
        }

        base.next = function() {
            if (base.currentFrame < base.$frames.length - 1) {
                base.slideTo(parseInt(base.currentFrame) + 1);
            } else {
                base.slideTo(0);
            }
        };

        base.previous = function() {
            if (base.currentFrame > 0) {
                base.slideTo(parseInt(base.currentFrame) - 1);
            } else {
                base.slideTo(base.$frames.length - 1);
            }
        };

        base.makeControlActive = function() {
            base.$slideControls.removeClass('active');
            $(base.$slideControls[base.currentFrame]).addClass('active');
        };

        base.getCurrentFrame = function() {
            return base.currentFrame;
        };

        base.startRotate = function() {
            base.options.autoPlay = true;
            base.rotate();
            return base;
        };

        base.stopRotate = function() {
            base.options.autoPlay = false;
            return base;
        };

        base.rotate = function() {
            setTimeout(function(){
                if (base.options.autoPlay == true) {
                    base.next();
                    base.rotate();
                }
            }, base.options.delay);
        };

        // Trigger the initialization
        base.init();
    };

    $.carousel.defaults = {
        // Operation
        autoPlay: true,
        defaultFrame: 0,
        easing: 'easeInOutSine',
        effect: 'slide',

        // Sizes
        width: 460,
        height: 170,

        // Times
        delay: 3000,
        animationTime: 600
    };

    $.fn.carousel = function(options, callback) {

        return this.each(function(){
            var page, carousel = $(this).data('Carousel');

            // initialize the slider but prevent multiple initializations
            if ((typeof(options)).match('object|undefined')){
                if (!carousel) {
                    (new $.carousel(this, options));
                } else {
            //carousel.updateSlider();
            }
            }
        // If options is a number, process as an external link to page #: $(element).anythingSlider(#)
        //                    } else if (/\d/.test(options) && !isNaN(options) && anySlide) {
        //                        page = (typeof(options) === "number") ? options : parseInt($.trim(options),10); // accepts "  2  "
        //                        // ignore out of bound pages
        //                        if ( page >= 1 && page <= anySlide.pages ) {
        //                            anySlide.gotoPage(page, false, callback); // page #, autoplay, one time callback
        //                        }
        //                        // Accept id or class name
        //                    } else if (/^[#|.]/.test(options) && $(options).length) {
        //                        anySlide.gotoPage(options, false, callback);
        //                    }
        });
    };

})(jQuery);
