(function($) {
    var slideshow;
    
    $.fn.slideshow = slideshow = function(options) {
        return this.each(function() {
            var instance = $.data(this, 'slideshow');
            if (instance) {
                $.extend(true, instance.options, options)
                instance.init();
            } else {
                $.data(this, 'slideshow', new slideshow.prototype.create(options, this));
            }
        });
    };
    
    slideshow.prototype = {
        /**
         * デフォルト設定
         * 呼び出し時に引数で指定することで上書き可能
         */
        options: {
            interval    : 6000,
            menuClass   : 'billboardBtn',
            contentClass: 'billboards'
        },
        
        /**
         * コンストラクタ
         * @param object options
         * @param jQuery element
         */
        create: function(options, element) {
            this.originalElement = element;
            this.options         = $.extend(true, {}, this.options, options);
            this.currentIndex    = 0;
            this.timeoutID       = null;
            
            this.init();
        },
        
        /**
         * 初期実行処理
         */
        init: function() {
            this.isMoving = false;
            
            var buttons = $('.' + this.options.menuClass, this.originalElement);
            this.contentWidth = parseInt($('.' + this.options.contentClass, this.originalElement).css('width'));
            var contents = $('.' + this.options.contentClass, this.originalElement).children();
            var self = this;
            
            // ビルボードの数だけマーク追加＆関数バインド
            var li;
            contents.each(function(i) {
                li = document.createElement('li');
                $.data(li, 'slideshow', {index:i});
                if (i == 0) $(li).addClass('current');
                $(li).bind('click', function(event) {
                    return self.menuClick(event);
                });
                buttons.append(li);
                
                // 最初のビルボード以外は右に隠す
                $(this).css('left', (self.contentWidth * i) + 'px');
            });
            
            this.timeoutID = setTimeout(function() {
                self.slideContent(0, 1);
            }, self.options.interval);
        },
        
        /**
         * コンテンツ部分をスライドさせる
         */
        slideContent: function(currentIndex, nextIndex) {
            this.isMoving = true;
            var self = this;
            var contents = $('.' + this.options.contentClass, this.originalElement).children();
            
            var diff = nextIndex - currentIndex;
            var diffX = (0 < diff) ?
                '-=' + (this.contentWidth * diff) + 'px' : '+=' + (this.contentWidth * -diff) + 'px';
            
            var imax = contents.size() - 1;
            this.setCurrent(nextIndex);
            contents.each(function(i) {
                $(this).animate({left:diffX}, 900, 'easeInOutCubic', function() {
                    if (i == imax) {
                        if (currentIndex < 0) {
                            // 巻き戻し後の処理
                            $(this).css('left', (self.contentWidth * imax) + 'px');
                        }
                        self.isMoving = false;
                        
                        // 次のスライドを予約
                        self.timeoutID = setTimeout(function() {
                            var nextNextIndex = nextIndex + 1;
                            if (imax < nextNextIndex) {
                                // 巻き戻し
                                self.rewindContent();
                            } else {
                                self.slideContent(nextIndex, nextNextIndex);
                            }
                        }, self.options.interval);
                    }
                });
            });
        },
        
        /**
         * スライドを巻き戻す
         */
        rewindContent: function() {
            var self = this;
            var contents = $('.' + this.options.contentClass, this.originalElement).children();
            var imax = contents.size() - 1;
            // 最後のビルボード以外のleftPositionを設定
            contents.each(function(i) {
                if (i == imax) return false;
                $(this).css('left', (self.contentWidth * (i + 1)) + 'px');
            });
            this.slideContent(-1, 0);
        },
        
        /**
         * 現在表示されているビルボードを設定する
         * @param numeric index
         */
        setCurrent: function(index) {
            var buttons = $('.' + this.options.menuClass, this.originalElement);
            buttons.children().each(function(i) {
                if (i == index) {
                    $(this).addClass('current');
                    $(this).siblings().removeClass('current');
                    return false;
                }
            });
        },
        
        /**
         * メニューがクリックされたときに呼ばれる
         */
        menuClick: function(event) {
            // メニュー動作中は無効
            if (this.isMoving) return;
            // 現在表示されている項目のクリックは無効
            if ($(event.target).hasClass('current')) return;
            
            var buttons = $('.' + this.options.menuClass, this.originalElement);
            var currentIndex;
            buttons.children().each(function(i) {
                if ($(this).hasClass('current')) {
                    currentIndex = i;
                    return false;
                }
            });
            // 次の予約破棄
            clearTimeout(this.timeoutID);
            
            $(event.target).removeClass('current');
            var data = $.data(event.target, 'slideshow');
            this.slideContent(currentIndex, data.index);
        }
    };
    
    slideshow.prototype.create.prototype = slideshow.prototype;
    
})(jQuery);

